Android: requestLayout() improperly called

AndroidPerformanceAndroid Listview

Android Problem Overview


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

Android Solutions


Solution 1 - Android

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.

Solution 2 - Android

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.

Solution 3 - Android

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) })

Solution 4 - Android

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"
/>

Solution 5 - Android

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 https://stackoverflow.com/questions/22078961/android-layout-running-second-layout-pass and my answer.

Solution 6 - Android

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;
}

Solution 7 - Android

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.

Solution 8 - Android

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());
}

Solution 9 - Android

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.

Solution 10 - Android

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);
}

Solution 11 - Android

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

Solution 12 - Android

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);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDaiwik DaarunView Question on Stackoverflow
Solution 1 - AndroiddarksagaView Answer on Stackoverflow
Solution 2 - Androidaxl coderView Answer on Stackoverflow
Solution 3 - AndroidVladimirVipView Answer on Stackoverflow
Solution 4 - AndroidJoaquin IurchukView Answer on Stackoverflow
Solution 5 - AndroidksarmalkarView Answer on Stackoverflow
Solution 6 - AndroidThomas R.View Answer on Stackoverflow
Solution 7 - AndroidCoolMindView Answer on Stackoverflow
Solution 8 - AndroidGhasem SadeghiView Answer on Stackoverflow
Solution 9 - AndroidGabe SechanView Answer on Stackoverflow
Solution 10 - AndroidJavier TorónView Answer on Stackoverflow
Solution 11 - AndroidA. AlmazidiView Answer on Stackoverflow
Solution 12 - AndroidStefan CizmarView Answer on Stackoverflow