requestLayout() improperly called by CollapsingToolbarLayout

匿名 (未验证) 提交于 2019-12-03 08:52:47

问题:

I have a collapsing toolbar layout which contains an image and on collapse shows the toolbar title. I needed to change the toolbar title font so I added a textview inside toolbar layout. Now I'm getting the following error generated repeatedly whenever I collapse the toolbar.

08-12 13:14:19.604 2263-2263/com.panoroma.admin W/View: requestLayout() improperly called by android.support.design.widget.CollapsingToolbarLayout{2d353cd6 V.ED.... ........ 0,0-1080,390 #7f0c0070 app:id/collapsing_toolbar} during second layout pass: posting in next frame  08-12 13:14:19.604 2263-2263/com.panoroma.admin W/View: requestLayout() improperly called by android.support.v7.widget.AppCompatTextView{1bb84b57 V.ED.... ........ 168,48-407,119 #7f0c0073 app:id/toolbar_title} during second layout pass: posting in next frame 

my layout...

<android.support.design.widget.CoordinatorLayout     xmlns:android="http://schemas.android.com/apk/res/android"     xmlns:app="http://schemas.android.com/apk/res-auto"     android:layout_width="match_parent"     android:layout_height="match_parent">  <android.support.design.widget.AppBarLayout     android:id="@+id/appbar"     android:layout_width="match_parent"     android:layout_height="wrap_content"     android:theme="@style/AppTheme.AppBarOverlay">      <android.support.design.widget.CollapsingToolbarLayout         android:id="@+id/collapsing_toolbar"         android:layout_width="match_parent"         android:layout_height="wrap_content"         app:contentScrim="?attr/colorPrimary"         app:layout_scrollFlags="scroll|enterAlways|enterAlwaysCollapsed|exitUntilCollapsed">          <ImageView             android:id="@+id/header"             android:layout_width="100dp"             android:layout_height="100dp"             android:adjustViewBounds="true"             android:layout_gravity="center"             android:scaleType="centerCrop"             android:layout_marginTop="15dp"             android:layout_marginBottom="15dp"             android:background="@drawable/dashboard80"             app:layout_collapseMode="parallax"             app:layout_collapseParallaxMultiplier="0.5"  />          <android.support.v7.widget.Toolbar             android:id="@+id/da_toolbar"             app:popupTheme="@style/AppTheme.PopupOverlay"             app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"             xmlns:android="http://schemas.android.com/apk/res/android"             xmlns:app="http://schemas.android.com/apk/res-auto"             android:layout_width="match_parent"             app:layout_collapseMode="pin"             android:layout_height="?attr/actionBarSize">              <TextView                 android:layout_width="wrap_content"                 android:layout_height="wrap_content"                 android:textSize="20sp"                 android:textColor="?attr/colorAccent"                 android:id="@+id/toolbar_title"/>          </android.support.v7.widget.Toolbar>      </android.support.design.widget.CollapsingToolbarLayout> </android.support.design.widget.AppBarLayout>   <ScrollView     android:layout_width="match_parent"     android:layout_height="match_parent"     android:layout_below="@+id/rel_dash_icon"     app:layout_behavior="@string/appbar_scrolling_view_behavior" >  .........................  </ScrollView>  </android.support.design.widget.CoordinatorLayout> 

java file..

Typeface ubuntuC = Typeface.createFromAsset(getAssets(), "ubuntuC.ttf"); Toolbar toolbar = (Toolbar) findViewById(R.id.da_toolbar);     toolbar.setTitle("");     setSupportActionBar(toolbar);      toolbar_title = (TextView)toolbar.findViewById(R.id.toolbar_title);     toolbar_title.setTypeface(ubuntuC);      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)         getSupportActionBar().setHomeAsUpIndicator(getResources().getDrawable(R.drawable.abc_ic_ab_back_mtrl_am_alpha, null));     else         getSupportActionBar().setHomeAsUpIndicator(getResources().getDrawable(R.drawable.abc_ic_ab_back_mtrl_am_alpha));     getSupportActionBar().setDisplayHomeAsUpEnabled(true);      final CollapsingToolbarLayout collapsingToolbarLayout = (CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar);     AppBarLayout appBarLayout = (AppBarLayout) findViewById(R.id.appbar);     appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {         boolean isShow = false;         int scrollRange = -1;          @Override         public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {             if (scrollRange == -1) {                 scrollRange = appBarLayout.getTotalScrollRange();             }             if (scrollRange + verticalOffset == 0) { //                    collapsingToolbarLayout.setTitle("Dashboard");                 toolbar_title.setText("Dashboard");                 isShow = true;             } else if(isShow) { //                    collapsingToolbarLayout.setTitle("");                 toolbar_title.setText("");                 isShow = false;             }         }     }); 

I just want a toolbar with a center image which on collapse will display the title. Title will have custom font. Now, is there a better way doing this?

回答1:

Following piece of code worked for me added post Runnable on AppBarLayout

mAppBar.addOnOffsetChangedListener(new AppBarStateChangeListener() {             @Override             public void onStateChanged(AppBarLayout appBarLayout, final int state, int done) {                 mAppBar.post(new Runnable() {                     @Override                     public void run() {                         if (state == COLLAPSED) {                             mToolBarTitle.setText(model.getTitle());                         } else if (state == EXPANDED || state == IDLE) {                             mToolBarTitle.setText("");                         }                     }                 });             }         }); 


回答2:

I had the same problem with my onOffsetChangedListener. To fix it, I had to wrap my code a runnable that runs on the UI thread. So with yours you would have to do the following:

    @Override     public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {         getActivity().runOnUiThread(new Runnable() {                 @Override                 public void run() {                     if (scrollRange == -1) {                         scrollRange = appBarLayout.getTotalScrollRange();                     }                     if (scrollRange + verticalOffset == 0) {                         collapsingToolbarLayout.setTitle("Dashboard");                         toolbar_title.setText("Dashboard");                         isShow = true;                     } else if(isShow) {                         collapsingToolbarLayout.setTitle(" ");                         toolbar_title.setText(" ");                         isShow = false;                     }                 }         }); 

Note the space between the quotation marks in setTitle and setText. I believe you need a space or it won't work. Also, make sure in your xml that you have

app:titleEnabled="false" 

on your CollapsingToolbarLayout.

Hope that solved the problem :)



回答3:

You can actually set a title colour for collapsed and expanded mode which will transition between the two when the toolbar is collapsing.

In your case rather then manually handling the collapse/expansion and setting the title you could set the expanded title colour to transparent and the collapsed title colour to whatever you originally wanted it to be.

So now when expanded the toolbar title is invisible and when collapsed the toolbar title is visible.



回答4:

I had the same problem and this page gives me a hint : here

I removed the collapsingToolbarLayout.setTitle("Dashboard"); collapsingToolbarLayout.setTitle(" "); and created two styles in styles.xml:

<style name="CustomCollapsingCollapsed">    <item name="android:textColor">@color/colorText</item> </style> <style name="CustomCollapsingExpanded">   <item name="android:textColor">@color/transparent</item> </style> 

And use them in

<android.support.design.widget.CollapsingToolbarLayout    android:layout_width="match_parent"    android:layout_height="match_parent"    app:contentScrim="@color/colorAccent"    app:layout_scrollFlags="scroll|exitUntilCollapsed"    app:expandedTitleTextAppearance="@style/CustomCollapsingExpanded"    app:collapsedTitleTextAppearance="@style/CustomCollapsingCollapsed"    > 

No logs anymore... Hope it helps!



回答5:

onOffsetChanged() is called so many times and android is throwing that warning because you are requesting layout as part of toolbar_title.setText("Dashboard"); . What you should do is , use a boolean flag and call it only once if the condition is met or check the VISIBILITY flag for the toolbar text view ,something like this.

  1. Add textview inside your toolbar layout under CollapsingLayout

       < android.support.v7.widget.Toolbar      android:id="@+id/toolbar"      android:layout_width="match_parent"      android:layout_height="?attr/actionBarSize"      app:layout_collapseMode="pin"      app:popupTheme="@style/ThemeOverlay.AppCompat.Light">           <TextView             android:id="@+id/toolbar_title"             style="@style/Toolbar.Title"             android:layout_width="wrap_content"             android:layout_height="wrap_content"             android:visibility="gone"             android:layout_gravity="center" />    </android.support.v7.widget.Toolbar> 
  2. In your activity or fragment class inside OnOffsetChangedListener() modify some thing like below with check. This will stop the warnings.

    appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {   @Override   public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {     if (verticalOffset == toolbar.getHeight() - collapsingToolbarLayout.getHeight()) {        if (textView.getVisibility() != View.VISIBLE) {         textView.setVisibility(View.VISIBLE);         textView.setText(title); // show toolbar title       }     } else {       if (textView.getVisibility() != View.GONE) {         textView.setVisibility(View.GONE); // hide title bar       }     }   } }); 

    }



回答6:

 appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {         boolean isShow = false;         int scrollRange = -1;          @Override         public void onOffsetChanged(final AppBarLayout appBarLayout, final int verticalOffset) {             if (scrollRange == -1) {                 scrollRange = appBarLayout.getTotalScrollRange();             }             if (scrollRange + verticalOffset == 0) {                 if (mToolbarTitle.getVisibility() == View.GONE) {                     mToolbarTitle.setVisibility(View.VISIBLE);                     mCollapsingToolbarLayout.setTitle("昵称");                     mToolbarTitle.setText("昵称");                 }                 isShow = true;             } else if (isShow) {                 mToolbarTitle.setVisibility(View.GONE);                 isShow = false;             }         }     }); 

Hope that solved the problem



易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!