android.support.design庫的引用和沖突解決
最近在工程中使用到android.support.design庫里的一些控件,在導入、編譯、運行的時候踩到了一些坑,在這里大概總結下,以成前車之鑒。
1.design庫的引入
在application或者library的build.gradle文件的dependencies加入compile'com.android.support:design:26.1.0' 。這里的版本號26.1.0,要和項目中“com.android.support:appcompat-v7”的版本號保持一致。
2.design控件使用
design庫引入之后,就可以在xml文件和java文件里面使用design控件,這里以FloatingActionButton為例.
<android.support.design.widget.FloatingActionButton
android:id="@+id/btn_float" android:layout_width="45dp" android:layout_height="45dp" android:layout_alignParentBottom="true" android:layout_alignParentEnd="true" android:layout_margin="16dp" android:src="@drawable/ic_add" app:backgroundTint="#2d7ad0" />
注意:當使用到控件特有屬性的時候,如backgroundTint的時候,要使用自定義的xmlns,xmlns:app="http://schemas.android.com/apk/res-auto"。
在完成如上兩步之后,在自己的demo里面,就可以顯示該button了,如圖:

3.design庫排雷過程
3.1 theme主題導致控件不可用
然鵝,在項目工程中使用的時候,可以正常編譯,但是運行的時候崩潰,報錯日志如下:
E/AndroidRuntime: FATAL EXCEPTION: main Process: com.guazi.android.expert, PID: 1390 android.view.InflateException: Binary XML file line #325: Binary XML file line #325: Error inflating class android.support.design.widget.FloatingActionButton Caused by: android.view.InflateException: Binary XML file line #325: Error inflating class android.support.design.widget.FloatingActionButton Caused by: java.lang.reflect.InvocationTargetException Caused by: java.lang.IllegalArgumentException: You need to use a Theme.AppCompat theme (or descendant) with the design library. at android.support.design.widget.ThemeUtils.checkAppCompatTheme(ThemeUtils.java:33) at android.support.design.widget.FloatingActionButton.<init>(FloatingActionButton.java:157)
這一段報錯日志很簡單,從最后給出的建議就可以得出結論,使用到design控件的activity必須使用Theme.AppCompat的主題。在style文件里定義parent為AppCompat的主題:
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> <item name="android:buttonStyle">@style/ButtonTheme</item> </style> <style name="ButtonTheme" parent="@style/Widget.AppCompat.Button.Borderless"></style>
然后在AndroidManifest文件里改變activity或者application主題即可。
3.2 不同庫之間的沖突問題
改完theme,滿心歡喜,以為終於可以在項目里使用design控件了,然后編譯,運行,到了程序中再一次crash。。。
這時的日志是這樣的:
E/AndroidRuntime: FATAL EXCEPTION: main Process: com.guazi.android.expert, PID: 1390 android.view.InflateException: Binary XML file line #325: Binary XML file line #325: Error inflating class android.support.design.widget.FloatingActionButton Caused by: android.view.InflateException: Binary XML file line #325: Error inflating class android.support.design.widget.FloatingActionButton Caused by: java.lang.reflect.InvocationTargetException Caused by: java.lang.NoSuchMethodError: No direct method <init>(Landroid/widget/ImageView;Landroid/support/v7/widget/AppCompatDrawableManager;)V in class Landroid/support/v7/widget/AppCompatImageHelper; or its super classes (declaration of 'android.support.v7.widget.AppCompatImageHelper' appears in /data/app/com.guazi.android.expert-1/base.apk:classes38.dex) at android.support.design.widget.FloatingActionButton.<init>(FloatingActionButton.java:133) at android.support.design.widget.FloatingActionButton.<init>(FloatingActionButton.java:110)
這一次的日志看起來不太好分析,No direct method等等一大坨,這時就分析項目工程和自己的demo到底還有哪里不一樣呢?經過仔細排查,發現項目工程里面多引入了一個
compile 'com.androidkun:XTabLayout:1.1.3'
這個開源組件是依賴於com.android.support:design庫的,進入FloatingActionButton的類發現,External Libraries里design庫的版本是23.4.0,而我們項目中appcompat-v7的版本是26.1.0,這就和我們第一點提示的有沖突了。但是這個com.android.support:design庫是我們使用的XTabLayout自動引入的啊,我們要做的就是不使用它自動引入的design庫,而是使用我們 想要的、 版本和appcompat-v7一致的design庫。
針對這種情況,我們在gradle里如下配置:
compile ('com.androidkun:XTabLayout:1.1.3') { transitive = false } compile 'com.android.support:design:26.1.0'
transitive字段為false代表項目不會自動引入該庫所依賴的父庫,若項目使用到父庫,則自行引入。這里以XTabLayout和android.support.design為例,其它的依賴沖突同理。
然后就,項目運行起來啦~