修改TabLayout下劃線寬度,以及在Api28下遇到的問題—— tabLayout.getDeclaredField 空指標以及水波紋背景問題
阿新 • • 發佈:2018-11-22
在API28之前,我們修改TabLayout下劃線寬度,程式碼如下:
/** * 設定tabLayout下劃線的寬 */ public static void setIndicator(TabLayout tabs, int leftDip, int rightDip) { Class<?> tabLayout = tabs.getClass(); Field tabStrip = null; try { tabStrip = tabLayout.getDeclaredField("mTabStrip"); } catch (NoSuchFieldException e) { e.printStackTrace(); } tabStrip.setAccessible(true); LinearLayout llTab = null; try { llTab = (LinearLayout) tabStrip.get(tabs); } catch (IllegalAccessException e) { e.printStackTrace(); } int left = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, leftDip, Resources.getSystem().getDisplayMetrics()); int right = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, rightDip, Resources.getSystem().getDisplayMetrics()); for (int i = 0; i < llTab.getChildCount(); i++) { View child = llTab.getChildAt(i); child.setPadding(0, 0, 0, 0); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.MATCH_PARENT, 1); params.leftMargin = left; params.rightMargin = right; child.setLayoutParams(params); child.invalidate(); } }
呼叫如下:
mTabLayout.post(() -> Tools.setIndicator(mTabLayout, 20, 20));
在API28下執行正常,當我把API改為28時,此時出問題了, 空指標異常: 錯誤如下:
後來我就開始找問題了:
有人說:是程式碼混淆導致的;在混淆裡面加入這句即可。
-keep class android.support.design.widget.TabLayout{*;}
試用 無效!!
然後我就查看了API28下的TabLayout 原始碼,發現把原來的mTabStrip改名為slidingTabIndicator
修改下的程式碼如下:
/** * 設定tabLayout下劃線的寬 */ public static void setIndicator(TabLayout tabs, int leftDip, int rightDip) { Class<?> tabLayout = tabs.getClass(); Field tabStrip = null; try { //在API28下 呼叫:tabLayout.getDeclaredField("mTabStrip") tabStrip = tabLayout.getDeclaredField("slidingTabIndicator"); } catch (NoSuchFieldException e) { e.printStackTrace(); } tabStrip.setAccessible(true); LinearLayout llTab = null; try { llTab = (LinearLayout) tabStrip.get(tabs); } catch (IllegalAccessException e) { e.printStackTrace(); } int left = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, leftDip, Resources.getSystem().getDisplayMetrics()); int right = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, rightDip, Resources.getSystem().getDisplayMetrics()); for (int i = 0; i < llTab.getChildCount(); i++) { View child = llTab.getChildAt(i); child.setPadding(0, 0, 0, 0); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.MATCH_PARENT, 1); params.leftMargin = left; params.rightMargin = right; child.setLayoutParams(params); child.invalidate(); } }
繼續看原始碼,你會發現,API28下mTextView改名為textView了 如果你呼叫了:
tabLayout.getDeclaredField("mTextView"),在API28下記得改為:tabLayout.getDeclaredField("textView");
接著,你就會又出現一個問題,TabTab的點選有水波紋的背景樣式, 如下:
在佈局檔案中我已經加上了 tabBackground 屬性
app:tabBackground="@null"
但是不管用,在API28下還需要加上一句屬性:
app:tabBackground="@null"
app:tabRippleColor="@null"
整體xml程式碼如下:
<android.support.design.widget.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="@dimen/px88"
android:background="@color/white"
app:tabBackground="@null"
app:tabRippleColor="@null"
app:tabIndicatorColor="#30A6F5"
app:tabIndicatorHeight="3dp"
app:tabMode="fixed"
app:tabSelectedTextColor="@color/text_select_color"
app:tabTextAppearance="@style/TabLayoutTextAppearance"
app:tabTextColor="#666666"
/>
好了!問題已解決,你可以接著使用了;