AppBarLayout 有毒,我有一粒解藥,要不?(修改))

以前將這篇稿子發(fā)到專題 《Android 開發(fā)經(jīng)驗(yàn)談》 和 《Android 開發(fā)知識(shí)》的時(shí)候,過了很久,《Android開發(fā)知識(shí)》審核沒通過,《Android開發(fā)經(jīng)驗(yàn)談》被我自己撤回了。開始沒明白原因,重新重新讀了下文章,果然有問題,所以重新修改下。

上一次的錯(cuò)誤

第一次發(fā)稿的時(shí)候,錯(cuò)誤的將問題指向了view的高度,重新測(cè)試發(fā)現(xiàn),當(dāng)控件為隱藏的時(shí)候,高度為0,問題在margin高度

Paste_Image.png

問題:tabLayout會(huì)距離上面負(fù)幾個(gè)dp

111.gif
懷疑:fitSystemWindow 設(shè)置的問題

求證:將頂部的元素節(jié)點(diǎn)的fitSystemWindow設(shè)置為true和false都沒有效果,并且距離頂部負(fù)的地方在tabLayout顯示動(dòng)態(tài)一欄的前面,(開始沒想到這點(diǎn))

定位問題:元素是否滾動(dòng)是由appBarLayout控制

求證:查看appBarLayout 代碼,很容易就發(fā)現(xiàn)一段計(jì)算滾動(dòng)范圍的代碼

/** * Returns the scroll range of all children. 
* * @return the scroll range in px */
public final int getTotalScrollRange() {  
  if (mTotalScrollRange != INVALID_SCROLL_RANGE) {   
     return mTotalScrollRange;  
  }   
 int range = 0;   
 for (int i = 0, z = getChildCount(); i < z; i++) {   
     final View child = getChildAt(i);   
     final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 
     final int childHeight = child.getMeasuredHeight();    
     final int flags = lp.mScrollFlags;   
     if ((flags & LayoutParams.SCROLL_FLAG_SCROLL) != 0) {       
     // We're set to scroll so add the child's height    
        range += childHeight + lp.topMargin + lp.bottomMargin;   
         if ((flags & LayoutParams.SCROLL_FLAG_EXIT_UNTIL_COLLAPSED) != 0) {        
        // For a collapsing scroll, we to take the collapsed height into account.      
          // We also break straight away since later views can't scroll beneath       
         // us        
        range -= ViewCompat.getMinimumHeight(child);      
          break;        
      }    
    } else {      
      // As soon as a view doesn't have the scroll flag, we end the range calculation.      
      // This is because views below can not scroll under a fixed view.            break;   
     }   
 }    
  return mTotalScrollRange = Math.max(0, range - getTopInset());
}

簡單的翻譯下:判斷當(dāng)前滾動(dòng)范圍是否=-1,如果是開始往下執(zhí)行,遍歷子元素,獲取子元素的高度,判斷該元素是否可以滾動(dòng),如果可以滾動(dòng)加上該元素的高度和距離頂部以及底部的高度,如果子元素設(shè)置了exitUntilCollapsed,則減去該元素的最小高度。如果沒有設(shè)置Scroll 則什么都不做

尋找解決方案

我的tab 欄上面的一個(gè)元素的確設(shè)置了滾動(dòng),還設(shè)置了距離頂部和底部的Margin,用模擬器debug 到這行發(fā)現(xiàn)代碼沒有判斷是否隱藏,并且將margin值加到了range 中,
<code>
childHeight = 0;
lp.topMargin = 39
lp.bottomMargin = 42
</code>
問題就是應(yīng)該就是margin惹得禍,將margin去掉后,果然好了,另外一種方法,在view上再嵌套一個(gè)父元素,在計(jì)算高度的時(shí)候,沒計(jì)算子孫元素的margin

代碼

為了讓大家直觀的看到這個(gè)錯(cuò)誤,這里將問題代碼簡化后貼出

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:paddingBottom="16dp"
    android:paddingLeft="16dp"
    android:paddingRight="16dp"
    tools:context="wdwd.com.behave.MainActivity">
    <!--toolbar--> 
   <android.support.design.widget.AppBarLayout 
       android:layout_width="match_parent"
        android:layout_height="wrap_content"> 
       <android.support.v7.widget.Toolbar
            android:layout_width="match_parent" 
           android:layout_height="wrap_content"
            app:layout_scrollFlags="scroll|enterAlways" 
           android:id="@+id/toolbar" /> 
       <TextView   
         android:id="@+id/tv_problem_view"
            android:layout_width="match_parent"
            android:background="@android:color/black" 
           app:layout_scrollFlags="scroll" 
           android:layout_marginBottom="10dip"
            android:layout_marginTop="40dip" 
           android:layout_height="wrap_content"  
          android:text="我是好人"   
         android:visibility="visible">  
      </TextView>    
    <TextView     
       android:layout_width="match_parent"  
          android:layout_height="41dip"
            android:text="alsdjfalksdfj"/>
    </android.support.design.widget.AppBarLayout>
 </android.support.design.widget.CoordinatorLayout>

大家可以試試將tv_problem_view設(shè)置為隱藏看看,本來底部停靠的文本還能往上滾動(dòng)。

其他一些坑

CoordinaLayout的坑還么完,如果直接加Pulltorefresh 的話會(huì)出現(xiàn)拉一半就刷新的問題,這個(gè)問題網(wǎng)上能搜到解決方案,監(jiān)聽appbarLayoutOffsetChange事件。

coordinatorLayout 的子scrollview必須實(shí)現(xiàn)NestedChild,實(shí)際使用中發(fā)現(xiàn)在部分手機(jī)上有問題,結(jié)果全換成了recyclerview,webview網(wǎng)上找了段代碼,雖然能嵌套滑動(dòng),但是沒慣性,時(shí)間有限沒深入研究,希望有知道的同學(xué)分享,大家一起進(jìn)步。

這里捎帶提下md的tablayout,因?yàn)檫@期也用到了,md的tablayout很強(qiáng)大,強(qiáng)大在哪里,支持固定寬度,通俗講顯示一屏,加權(quán)重,也支持scrollable,超出屏幕滑動(dòng),但是用過的肯定知道tablayout不定自定義下面指示器的 紅色部分的寬度,我用的是簡書里的hackware 大神寫的magiclayout。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容