53

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

Community
  • 1
  • 1
Daiwik Daarun
  • 3,804
  • 7
  • 33
  • 60

13 Answers13

45

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.

darksaga
  • 2,166
  • 2
  • 18
  • 21
22

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.

axl coder
  • 739
  • 3
  • 19
  • I'm trying to persist my `ImageView` size in `onSaveInstanceState`, and that's when this error showed up and crashed my app. Not sure how to fix it, but this answer is more descriptive than just "it's a bug", so thanks for that. So, for me, it was not a scrolling issue. – Azurespot Apr 08 '15 at 01:19
12

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) })
Cullub
  • 2,901
  • 3
  • 30
  • 47
VladimirVip
  • 384
  • 3
  • 13
  • 5
    I'm probably having the same problem, but that link is broken. **EDIT:** resolved with the following: `imageView.post(new Runnable() { @Override public void run() { imageView.setLayoutParams(params); }});` – rjr-apps Jan 12 '18 at 00:29
5

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"
/>
Joaquin Iurchuk
  • 5,499
  • 2
  • 48
  • 64
2

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.

CoolMind
  • 26,736
  • 15
  • 188
  • 224
1

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.

Community
  • 1
  • 1
ksarmalkar
  • 1,884
  • 1
  • 16
  • 21
1

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;
}
Thomas R.
  • 7,988
  • 3
  • 30
  • 39
1

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());
}
Ghasem Sadeghi
  • 1,734
  • 13
  • 24
0

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.

Gabe Sechan
  • 90,003
  • 9
  • 87
  • 127
0

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);
}
Javier Torón
  • 99
  • 3
  • 12
0

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

A. Almazidi
  • 25
  • 1
  • 5
0

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

Stefan Cizmar
  • 51
  • 1
  • 3
-1

There is many reason for this but one in my case lies in Manifest.xml file.

First you should check the corresponding activity in your Manifest file because when we move activity in different package then 'android:name' in 'activity' tag in 'application' tag in Menifest File may be changed automatically or may be not so in that case we need to change our activity name accordingly.