古人已用三冬足,年少今开万卷余。这篇文章主要讲述Android:requestLayout()调用不当相关的知识,希望能为你提供帮助。
当我尝试在ListView
中膨胀布局时发生以下错误:
requestLayout() improperly called by android.widget.TextView{...} during layout: running second layout pass
我试图在
ListView
内膨胀布局如下:@Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null){
LayoutInflater inflater = (LayoutInflater) musicActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.list_item, parent, false);
...
}else{...}
}
膨胀的布局可以看起来像下面这样简单,并且仍然会产生错误
<
TextView
android:id="@+id/txt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="@dimen/txt_size"/>
我已经研究了类似的问题,并没有找到解决方案似乎工作Question 1,Question 2,Question 3。
有谁知道导致此类错误的原因是什么?任何疑难解答建议更多的背景信息,这个
ListView
显示在Fragment
内的ViewPager
中UPDATE这是完整的XML布局(减去一堆属性),仍然会导致问题
<
RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<
TextView
android:id="@+id/txt1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<
TextView
android:id="@+id/txt2"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<
TextView
android:id="@+id/txt3"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<
TextView
android:id="@+id/txt4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<
/RelativeLayout>
基于此,我认为XML本身不是问题,除非它与我使用ViewPager和Fragments这一事实有关
答案这个问题似乎是android实现中的一个错误,请参阅:https://code.google.com/p/android/issues/detail?id=75516
通过
ListView
在您的代码中激活ListView.setFastScrollEnabled(true)
的快速滚动功能将触发此错误,您将开始看到requestLayout()在布局期间由android.widget.TextView {...}不正确地调用:运行第二个布局传递【Android(requestLayout()调用不当)】控制台中的消息。
这个bug必须在其中一个KitKat(4.4.x)更新中引入,因为我没有在最初的KitKat(4.4.0)版本中看到它。除了丑陋的控制台垃圾邮件与上面的调试消息,似乎没有其他影响(在某些情况下可能性能,我还没有测试)。
干杯
PS:这不是第一次快速滚动功能被窃听,例如https://code.google.com/p/android/issues/detail?id=63545,63545固定在KitKat 4.4.3但75516此后加速 - > 似乎是google的烦恼主题; -)
编辑2015年5月12日:
几分钟前我将Nexus 7更新为Android 5.1(之前运行的是5.0)并且在这个新版本中停止了这个问题。由于FastScroll指标的外观在5.1中也发生了变化,我认为google修复了这个问题,或者至少注释掉那些垃圾邮件控制台的丑陋线条......
75516和82461仍然“未解决”,但我想那些引用相同的问题,现在已经在5.1中解决了。
另一答案尝试从xml中取出textSize并在java代码中设置它。我认为这会导致它被布置两次。
另一答案有时您可能已经解决了问题,但它仍然保持相同的错误,因此您需要关闭visual studio然后从项目中删除所有bin和obj文件夹,然后从模拟器中卸载应用程序。然后walah !!一切都会好起来的
另一答案问题是,虽然适配器的方法
getView()
正在显示您的布局,但其他一些代码正试图访问此视图以显示它,从而导致冲突。请注意,某些方法,也许你不关心(如
setScale()
,setTypeFace()
)确实调用requestLayout()
,所以在你的膨胀声明后你正在做的事情会很有趣。另一答案对我来说,这个问题发生在
setLayoutParams()
电话上。正如here所说,解决方案是在looper上发布了一个runnable另一答案我通过在XML中禁用ListView上的fastScroll来修复此问题。
<
ListView
android:id="@+id/mListview"
android:layout_width="wrap_content"
android:layout_height="match_parent"android:fastScrollEnabled="false"
/>
另一答案如果您使用ListView的某些第三方扩展,则可能会发生这种情况。用标准ListView替换它,并检查它是否仍然抛出错误。
我有类似的问题。请检查Android layout: running second layout pass和我的答案。
另一答案我在带有Genymotion的摩托罗拉X上遇到了与Kitkat 4.4.4相同的问题。在我的例子中,列表项是一个简单的CheckedTextView,错误发生在AppCompatCheckedTextView中。
作为一个正常的实现,我从XML布局文件中膨胀了项目,如下所示:
if (convertView == null) {
convertView = inflater.inflate(R.layout.checkable_list_entry, parent, false);
}
经过一番尝试后,我发现这与XML通胀有关。我不知道根本原因,但作为一个解决方案,我决定按代码对列表项进行膨胀,并按代码设置所有属性。
结果是这样的:
CheckedTextView view;
if (convertView == null) {
view = new CheckedTextView(parent.getContext());
view.setMinHeight(getResources().getDimensionPixelSize(R.dimen.default_touch_height));
if (Build.VERSION.SDK_INT >
= Build.VERSION_CODES.M) {
view.setTextAppearance(R.style.SectionEntry);
} else {
view.setTextAppearance(parent.getContext(), R.style.SectionEntry);
}
view.setBackgroundResource(R.drawable.form_element);
view.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
view.setLayoutParams(new AbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT, AbsListView.LayoutParams.WRAP_CONTENT));
} else {
view = (CheckedTextView) convertView;
}
另一答案在我的情况下,此警告阻止按钮显示在API 21设备中。按钮可见性先前已设置为GONE。
我得到它的唯一解决方法是为API 21设置为INVISIBLE而不是GONE。这不是一个真正的解决方案,但它对我来说是可以接受的。
我只发布这个,因为它可以从某人有用。
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP) {
theButton.setVisibility(View.INVISIBLE);
}
else {
theButton.setVisibility(View.GONE);
}
另一答案在我的情况下(三星Galaxy S4,API 21),这发生在带有EditTexts的ListView中。我有一个字段验证的监听器。就像是:
edit.setOnFocusChangeListener(new View.OnFocusChangeListener() {
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
error.setVisibility(View.INVISIBLE);
error.setText("");
} else {
String s = edit.getText().toString();
if (s.isEmpty()) {
error.setText("Error 1");
} else if (s.length() <
2 || s.length() >
100) {
error.setText("Error 2");
}
error.setVisibility(View.VISIBLE);
}
}
});
在其中一个EditTexts中设置焦点后,将调用上面的检查。之后,TextView将更改(TextView包含错误消息并位于EditText上)。将焦点设置为第二个或第三个EditText导致第一个EditText的永久请求并返回当前。应用程序在无限循环的请求中运行(焦点编辑文本1,非焦点编辑文本1,焦点3,非焦点3,焦点1等)。
我试图设置listView.setFastScrollEnabled(false)。我也尝试了一些像https://github.com/sephiroth74/HorizontalVariableListView/issues/93这样的元素的requestLayout(),没有机会。目前我用XML制作了固定宽度和高度的TextView:
<
TextView
android:id="@+id/error"
android:layout_width="match_parent" (or "200dp", but not "wrap_content")
android:layout_height="20dp"
.../>
经过一些实验,我注意到20dp的高度可以用“wrap_content”代替。但是如果文本太长而不能分成2行,则应用程序会再次陷入无限循环。所以,
android:singleLine="true"
会有所帮助。它已被弃用,但令人惊讶的android:maxLines="1"
与android:lines="1"
没有帮助,因为他们再次请求布局。最终我们有:<
TextView
android:id="@+id/error"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:textColor="#f00"
android:textSize="20sp"
tools:text="Error message"/>
这不是一个好的解决方案,但至少它打破了无限循环。
另一答案我遇到了同一个警告日志的问题:
requestLayout() improperly called by android.support.v7.widget.AppCompatTextView {...} during layout: running second layout pass
我正在使用recyclerview并使用新数据更新它。
The only solution that worked for me is as below :步骤1)。删除当前数据:
public void removeAll() {
items.clear();
//clear list
notifyDataSetChanged();
}
第2步)。如果要使用新数据填充recyclerview,请先再次将新LayoutManager设置为recyclerview:
private void initRecycleView() {
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, false));
}
步骤(3)。使用新数据更新recyclerview。例如 :
public void refreshData(List newItems) {
this.items = newItems;
notifyItemRangeChanged(0, items.size());
}
推荐阅读
- 更改了arraylist时,ArrayList和ListView的Android数组适配器不会更新
- CardView在Android L中没有显示Shadow
- 如何在Android中使用Appcelerator Titanium构建Oauth 2.0
- Android上的Spring OAuth2异常(在路径上找不到类“javax.xml.transform.stax.StAXSource”:DexPathList)
- Linkedin signin(无法检索访问令牌:appId或重定向uri与授权代码或授权代码已过期不匹配)
- Flutters资源加载速度比原生Android快
- 如何解决Symfony 4中的KnpPaginator异常(即使应用容器中存在服务”knp_paginator”,也找不到)
- 如何在C#中将Unixtime转换为DateTime类,反之亦然
- 2020年最值得学习的编程语言列表