Android: requestLayout() improperly called - android

The following error occurs when I attempt to inflate a layout within a ListView:
requestLayout() improperly called by android.widget.TextView{...} during layout: running second layout pass
I am attempting to inflate a layout within a ListView as follows:
#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{...}
}
The layout being inflated can look as simple as the following, and will still produce the error
<TextView
android:id="#+id/txt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="#dimen/txt_size"/>
I have looked into similar questions, and no solutions found seem to work Question 1, Question 2, Question 3.
Does anyone know what causes this type of error? Any troubleshooting advice? For more context, this ListView is displayed within a Fragment within a ViewPager
UPDATE
Here is the full XML Layout (minus a bunch of attributes), that still results in the problem
<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>
Based on this, I would think the XML itself is not a problem, unless it has to do with the fact that I am using a ViewPager and Fragments

This issue seems to be a bug in the android implementation, please see: https://code.google.com/p/android/issues/detail?id=75516
Activating the fast scroll feature of a ListView in your code via ListView.setFastScrollEnabled(true) will trigger this bug and you'll start seeing the
requestLayout() improperly called by android.widget.TextView{...}
during layout: running second layout pass
message in your console.
This bug must have been introduced in one of the KitKat (4.4.x) updates, as I've not seen it with the initial KitKat (4.4.0) release. Apart from the ugly console spamming with the debug message from above, there seem to be no other impacts (maybe performance in some cases, which I haven't tested).
Cheers
PS: it's not the first time that the fast scroll feature is bugged, e.g. https://code.google.com/p/android/issues/detail?id=63545, 63545 was fixed in KitKat 4.4.3 but 75516 poped up thereafter --> seems to be a vexed subject for google ;-)
EDIT May 12 2015:
I updated my Nexus 7 to Android 5.1 some minutes ago (was Running 5.0 before) and stopped seeing this issue in this new version. As the appearance of the FastScroll indicator also changed in 5.1, I assume that google fixed this issue or at least commented out those ugly lines that spammed the console...
75516 & 82461 are still 'unresolved', but I guess that those refer to the same issue, that's now resolved in 5.1.

The problem is that while the method getView() of your adapter is displaying your layout some other code is trying to access this view to display it, resulting in a collision.
Note that some methods, that maybe you don't take care of (like setScale(), setTypeFace()) indeed call requestLayout(), so it would be interesting what you are doing after your inflate statement.

For me this issue was occurring upon a setLayoutParams() call. The solution was posting a runnable on the looper:
// java
imageView.post(new Runnable() {
#Override public void run() {
imageView.setLayoutParams(params);
}
});
// kotlin
post(Runnable { imageView.setLayoutParams(params) })

I fixed this issue by disabling fastScroll on the ListView in the XML.
<ListView
android:id="#+id/mListview"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:fastScrollEnabled="false"
/>

In my case (Samsung Galaxy S4, API 21) this happened in ListView with EditTexts. I have a listener for field validation. Something like:
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);
}
}
});
After settinging focus in one of these EditTexts an above check is called. After that a TextView will change (the TextView contains an error message and lies over the EditText).
Setting focus to the second or the third EditText led to permanent request of the first EditText and return to current. An applications runs in infinite loop of requests (focus edittext 1, unfocus edittext 1, focus 3, unfocus 3, focus 1, etc).
I tried to set listView.setFastScrollEnabled(false). Also I tried a requestLayout() of some elements like in https://github.com/sephiroth74/HorizontalVariableListView/issues/93 with no chances.
Currently I made that TextView of fixed width and height in XML:
<TextView
android:id="#+id/error"
android:layout_width="match_parent" (or "200dp", but not "wrap_content")
android:layout_height="20dp"
.../>
After some experiments I noticed that a height of 20dp can be replaced with "wrap_content". But if a text is too long that divides into 2 lines, the application again catches in the infinite loop. So, android:singleLine="true" will help. It is deprecated, but amazingly android:maxLines="1" with android:lines="1" don't help as they again request layout.
Eventually we have:
<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"/>
That's not a good solution, but at least it breaks the infinite loop.

This might happen if you are using some 3rd party extension of ListView. Replace that with standard ListView and check if it still throws the error.
I had similar problem. Please check Android layout: running second layout pass and my answer.

I had the same issue with Kitkat 4.4.4 on Motorola X with Genymotion. In my case the list item is a simple CheckedTextView and the error occurred in AppCompatCheckedTextView.
As a normal implementation I inflated the item from XML layout file like below:
if (convertView == null) {
convertView = inflater.inflate(R.layout.checkable_list_entry, parent, false);
}
After some trying I found out that this has something to do with XML inflation. I don't know the root cause, but as a solution I decided to inflate the list item by code and set all the properties by code too.
It ended up like this:
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;
}

I had a problem with the same warning log :
requestLayout() improperly called by android.support.v7.widget.AppCompatTextView {...} during layout: running second layout pass
I was working with recylcerview and going to update it with new data.
The only solution that worked for me is as below :
Step(1). Remove current data :
public void removeAll() {
items.clear(); //clear list
notifyDataSetChanged();
}
Step(2). When you want to populate the recyclerview with new data, first set a new LayoutManager to recyclerview again:
private void initRecycleView() {
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, false));
}
Step(3). Update the recyclerview with new data. for example :
public void refreshData(List newItems) {
this.items = newItems;
notifyItemRangeChanged(0, items.size());
}

Try taking off the textSize from the xml and setting it in Java code. I think that's causing it to be laid out twice.

In my case this warning prevented a button from showing up in API 21 devices. The button visibility was previously set to GONE.
The only workaround I got it was setting to INVISIBLE instead of GONE for API 21. It wasn't a real solution but it was acceptable for me.
I only post this because it can be useful from somebody.
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP) {
theButton.setVisibility(View.INVISIBLE);
}
else {
theButton.setVisibility(View.GONE);
}

Sometimes you maybe already fixed the issue but it still keeps same error, so you need to close visual studio then delete all bin and obj folders from your projects, then uninstall the app from the emulator. then walah!! everything will works fine

I solved the problem like this:
mHolder.txt_fword.setTextSize(22);
mHolder.txt_farth.setTextSize(22);
mHolder.txt_fdef.setTextSize(22);
mHolder.txt_fdef2.setTextSize(22);
mHolder.txt_frem.setTextSize(22);
//if (fdef2.get(pos).equals("")) mHolder.txt_fdef2.setVisibility(View.GONE);
//if (frem.get(pos).equals("")) mHolder.txt_frem.setVisibility(View.GONE);
issue is .setVisibility(View.GONE); , change to .setVisibility(View.VISIBLE);

Related

Context Menu not appearing only at certain times on Edittext while in RecyclerView

I have a strange situation...
I have a RecyclerView with swipeRefresh enabled... and the 1st item in my RecyclerView is a CardView having
<com.daniribalbert.customfontlib.views.CustomFontEditText
android:id="#+id/start_chat_add_comment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerVertical="true"
android:paddingTop="#dimen/general_gap_smallest"
android:paddingBottom="#dimen/general_gap_smallest"
android:gravity="top"
android:layout_toLeftOf="#id/start_chat_post_comment"
android:layout_toRightOf="#id/start_chat_attach_media"
android:background="#android:color/transparent"
android:imeOptions="actionDone"
android:textColorHint="#color/edit_text_hint_color"
android:textColor="#color/newsfeed_text_card_owner_main_text_color"
android:textSize="#dimen/font_normal"
app:font="Roboto-Regular"/>
When the recyclerview is inflated 1st time, I am able to longpress on the EditText and access the context menu. However each time I refresh the recyclerview by pulling swiperefresh (a new card is added as it was added for the 1st time), my context menu never appears on longpress on EditText.
JFYI ... i do not experience a certain vibration on the phone either on longpress on EditText at this point in time when the context menu does not show up.
I have tried looking out for some information and stuff, but nothing looks to be helpful, except at some point someone mentioned that context menu may not work if edittext is a part of popup (alertbox), and even the option of textIsSelectable = "true" did not come any handy.
Any help is much appreciated.
This fix worked for me:
edtImgDesc.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
#Override
public void onViewAttachedToWindow(View v) {
edtImgDesc.setCursorVisible(false);
edtImgDesc.setCursorVisible(true);
}
#Override
public void onViewDetachedFromWindow(View v) {
}
})
Taken from: Long pressed broken for EditText (Or android.support.v7.widget.AppCompatEditText) after the view is recycled in RecyclerView

What could be responsible for an ImageView not being clickable

I am using an ImageView as a NEXT button in my Android app which is responsible for loading the next page of results into the current activity. However, despite that I bind a click listener to it, I cannot seem to capture click events on this ImageView. Here is the XML:
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="50"
android:gravity="left"
android:orientation="horizontal">
<ImageView
android:id="#+id/listBackIcon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/back_icon"/>
<TextView
android:id="#+id/listBackLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Prev"
android:textSize="16dip"/>
</LinearLayout>
And here is the relevant Java code:
ImageView forwardIconView = (ImageView)findViewById(R.id.listBackIcon);
// not sure if necessary; doesn't fix it anyway
forwardIconView.setClickable(true);
forwardIconView.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
++pageNumber;
try {
params.put("page", pageNumber);
} catch (JSONException e) {
// do something
}
ConnectionTask task = new ConnectionTask();
task.execute(new String[0]);
}
});
I spent about an hour researching this on Stack Overflow. I found a few places which claimed that ImageView could directly be made clickable, but most things recommended workarounds using other types of widgets.
Does anything about my layout/code stand out as being a culprit for this behavior?
Update:
I also tried binding a click listener to the TextView at the same level as the ImageView and this too failed to capture clicks. So now I am suspecting that the views are being masked by something. Perhaps something is capturing the clicks instead of the views.
I would set it up like this:
private ImageView nextButton;
nextButton = (ImageView)view.findViewById(R.id.back_button);
Util.loadImage(getActivity(),R.drawable.some_image,nextButton); //Here i would load the image, but i see you do it in XML.
nextButton.setOnClickListener(nextButtonListener);
nextButton.setEnabled(true);
View.OnClickListener nextButtonListener = new View.OnClickListener() {
#Override
public void onClick(View view) {
Log.v(TAG, "ImageView has been clicked. do something.");
}
};
This works for me.
Why not use android:drawableLeft attribute for the textview instead of using imageView​ and textview both in a linearlayout .
<ImageView
android:id="#+id/listBackIcon"
...
android:clickable="true"
Or you can try overriding onTouchListener with ACTION_DOWN event filter, not onClickListener. Also check for parrents with android:clickable="false", they could block childs for click events.
What seemed to work for me was the accepted answer from this SO question, which suggests adding the following the every child element of the LinearLayout which I pasted in my question:
android:duplicateParentState="true"
I don't know exactly what was happening, but it appears the click events were not making it down to the TextView and ImageView. Strangely, the click events were reaching a Button, when I added one for debugging purposes. If someone has more insight into what actually happened, leave a comment and this answer can be updated.

TextInputLayout disable animation

I am using the TextInputLayout to implement the floating label pattern. However, when I set the text programmatically on the EditText, I still get the animation of the label moving from the control to the label - the same as if the user had clicked it.
I don't want this animation though if I set it programmatically, is this possible? Here is my code:
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/root">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/editText1" />
</android.support.design.widget.TextInputLayout>
And in the onResume I do:
TextInputLayout root = (TextInputLayout)findViewById(R.id.root);
EditText et = (EditText)root.findViewById(R.id.editText1);
et.setText("Actual text");
root.setHint("Hint");
As of v23 of the support libs, a setHintAnimationEnabled method has been added. Here are the docs. So you can set this new attribute to false in the XML and then programmatically set it to true after you've finished populating the editText. OR simply handle it all programmatically, as needed.
So in your example, that would become something like:
TextInputLayout root = (TextInputLayout)findViewById(R.id.root);
root.setHintAnimationEnabled(false);
root.setHint("Hint");
EditText et = (EditText)root.findViewById(R.id.editText1);
et.setText("Actual text");
// later...
root.setHintAnimationEnabled(true);
Of course, be sure to open your Android SDK Manager and update your Android Support Library to rev. 23 and Android Support Repository to rev. 17 first and then add that to build.gradle via:
compile 'com.android.support:design:23.0.0'
Note that as the Design library depends on the Support v4 and AppCompat Support Libraries, those will be included automatically when you add the Design library dependency.
Put this attribute app:hintEnabled="false" here:
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:hintEnabled="false">
It works for me
I have found an (unwieldy) way to do that. Looking into the source code of the TextInputLayout, I've discovered that the only occasion when the class doesn't update it's hint with animation is when the EditText is added to it. The only obstacle is that you can only add it once to the layout, once it is there, it will permanently be tied to it, and there's no way to remove it.
So here's the solution:
Create a TextInputLayout without the EditText. Programmatically or via XML inflation - doesn't matter, but it has to be empty.
Create the EditText and set its text to whatever you need.
Add the EditText to the TextInputLayout.
Here's an example:
TextInputLayout hintView = (TextInputLayout) findViewById(R.id.hint_view);
hintView.setHint(R.string.hint);
EditText fieldView = new EditText(hintView.getContext());
fieldView.setText(value);
hintView.addView(fieldView);
Unfortunately, if you want to set the text to something else without the animation, you will have to repeat all these steps, except for the creation of a new EditText (the last one can be reused). I hope Google can fix this, because it is really inconvenient, but for now that's what we have.
Update: this is, thankfully, fixed in the design library 23.0.0, so just update to that version, and you won't have to do all this crazy stuff.
You can disable it by using
app:hintAnimationEnabled="false"
I will give you simple code and you don't have to make all programmatically just add xlm attribute and that's all.
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:hintAnimationEnabled="true"
app:passwordToggleEnabled="true">
<EditText
android:id="#+id/password_field_activity_login"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/transparent"
android:hint="#string/password"
android:inputType="textPassword"
android:padding="10dp"
android:textColor="#color/color_holo_light_gray"
android:textColorHint="#color/color_holo_light_gray"
android:textCursorDrawable="#drawable/cursor_drawable" />
</android.support.design.widget.TextInputLayout>
Hope it will help
I wrote a small method to run after loading the view hierarchy that disables animation on initial display but enables it after wards. Add this to your Base Activity/Fragment/View and it will solve it issue.
private void setTextInputLayoutAnimation(View view) {
if (view instanceof TextInputLayout) {
TextInputLayout til = (TextInputLayout) view;
til.setHintAnimationEnabled(false);
til.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
#Override public boolean onPreDraw() {
til.getViewTreeObserver().removeOnPreDrawListener(this);
til.setHintAnimationEnabled(true);
return false;
}
});
return;
}
if (view instanceof ViewGroup) {
ViewGroup group = (ViewGroup) view;
for (int i = 0; i < group.getChildCount(); i++) {
View child = group.getChildAt(i);
setTextInputLayoutAnimation(child);
}
}
}
I check out ideas about support library v23 - it's does not work yet :( Programmatically inserting of EditText is unusable if you wish to use databinding labrary
In result of research I found solution without full disabling of animation:
layout.xml
<android.support.design.widget.TextInputLayout
android:id="#+id/text_til"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/product_title_placeholder">
<android.support.design.widget.TextInputEditText
android:id="#+id/text_tiet"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#={bindingText}"/>
</android.support.design.widget.TextInputLayout>
Activity.java
final TextInputLayout textLayout = (TextInputLayout) findViewById(R.id.text_til);
if(binding.getText() != null) {
// disable animation
textLayout.setHintAnimationEnabled(false);
final TextInputEditText editText = (TextInputEditText) titleLayout.findViewById(R.id.text_tiet);
editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View view, boolean b) {
// enable animation after layout inflated
textLayout.setHintAnimationEnabled(true);
editText.setOnFocusChangeListener(null);
}
});
}
// manage focus for new binding object
((View)textLayout .getParent()).setFocusableInTouchMode(binding.getText() == null);
It's looks not prettily, but it works :)

Android: ListView causing requestLayout() to be improperly called

Having fast scroll enabled in my ListView is causing the following error:
08-09 01:47:33.294 10816-10816/com.exampleW/View﹕ requestLayout() improperly called by android.widget.TextView{...} during layout: running second layout pass
I know the ListView is causing the problem because removing the following line of code from the ListView's XML removes the error:
android:fastScrollEnabled="true"
Is there any way to fix this error? To be thorough, I have also included the TextView's XML:
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
i think this error is not because of android:fastScrollEnabled="true" however try below code in your java file..
try list.smoothScrollToPosition(0); also with android:fastScrollEnabled="true"
so that data appears when scroll is called...
something like this..
new Handler().postDelayed(new Runnable()
{
#Override
public void run()
{
list.smoothScrollToPosition(0);
}
}, 100);
this is known bug in android implementation when you set fastScrollEnabled = true, which appears in some android versions.
https://code.google.com/p/android/issues/detail?id=75516
Apart from the ugly console spamming with the debug message from above, there seem to be no other impacts (maybe performance in some cases, which I haven't tested).

Strange XML layout bug when targeting Android 4.3

I'm experiencing a really peculiar bug with an XML layout file when building my application while targeting API level 18. It doesn't happen with API level 17. I'm running the application on Android 4.3 devices, and the bug persists on all three devices.
Here's what it looks like:
API 17 (correct):
API 18 (incorrect):
I'm using the StickyGridHeaders library, and the following is my getHeaderView() method:
#Override
public View getHeaderView(int position, View convertView, ViewGroup parent) {
RowItem holder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.seasons_row_header, parent, false);
holder = new RowItem();
holder.title = (TextView) convertView.findViewById(R.id.seasonTitle);
holder.episodeCount = (TextView) convertView.findViewById(R.id.episodeCount);
convertView.setTag(holder);
} else {
holder = (RowItem) convertView.getTag();
}
if (seasons.get(position).equals("00")) {
holder.title.setText(R.string.stringSpecials);
} else {
holder.title.setText(getString(R.string.showSeason) + " " + seasons.get(position));
}
int size = seasonEpisodeCount.get(Integer.valueOf(seasons.get(position)));
holder.episodeCount.setText(size + " " + getResources().getQuantityString(R.plurals.episodes, size, size));
convertView.setClickable(false);
convertView.setFocusable(false);
return convertView;
}
Here's the layout XML file:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#80000000"
android:padding="#dimen/list_padding" >
<TextView
android:id="#+id/seasonTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_marginRight="#dimen/list_padding"
android:layout_toLeftOf="#+id/episodeCount"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textIsSelectable="false"
android:textStyle="bold" />
<TextView
android:id="#+id/episodeCount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/seasonTitle"
android:layout_alignParentRight="true"
android:layout_alignTop="#+id/seasonTitle"
android:gravity="bottom"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textIsSelectable="false" />
</RelativeLayout>
Does anyone else have a clue as to what's going on here? I find it really strange that it's working when targeting API level 17 and not working when targeting the latest API level (18).
Update:
This is what it looks like in the visual layout editor with Android 4.3 as the target:
I managed to solve the issue myself.
Like I said, I am using the StickyGridHeaders library and referencing it in my application. It appears that the library was targeting API level 17. I changed it to level 18, compiled and ran the application - great success!
In conclusion: Make sure your application and libraries target the same API level.
I have the same issue, too.
My experiences have shown that crossed alignments are the reason of the problem (TextView #+id/seasonTitle has the property android:layout_toLeftOf="#+id/episodeCount"; TextView #+id/episodeCount has the properties android:layout_alignBottom="#+id/seasonTitle" and layout_alignTop="#+id/seasonTitle". One of the Layouts won't refresh its childs correct.
Changing the Layout-XML that crossed alignments are prevented, you no longer have this problem.
I have the same issue :
a ListView with a white background
each child has a View with a gray background and width and height to match_parent, within a RelativeLayout
on API 17, every is OK
on API 18+, the ListView is white
instead of setting a fixed height, I put a min_height to the View, and the problem is (temporary) solved!
hope it helps

Categories

Resources