Android兼容性小总结(一)
前言
在完美完成過年增肥任務之后,新的一年又得投入到工作當中了,今天是新年的第一篇博客,我們來討論一下Android開發(fā)經(jīng)久不變的兼容性問題。
國內(nèi)有很多的廠商都定制了自己的安卓系統(tǒng),誰也不知道會他們私底下都做了哪些操蛋的修改,再加上安卓版本的更新周期目前還是比較穩(wěn)定,幾乎每一年都會發(fā)布新的版本,例如去年的8.0。目前國內(nèi)的Android系統(tǒng)主要是5.0和6.0,少量的4.x和7.0,掰掰手指頭就5、6個,所以如何做好兼容性問題,一直是開發(fā)者,也是老板最關(guān)心的問題。
今天我準備簡單介紹幾個比較細節(jié)的例子,大家一起學習討論下。
正文
我把兼容性問題主要分為兩大類:
1、功能兼容問題,主要是系統(tǒng)版本的新特性,api的變化,或者是sdk定制導致部分api的執(zhí)行結(jié)果出現(xiàn)差異導致的,一般需要重寫方法,或者判斷系統(tǒng)版本特殊處理。
2、布局兼容問題,主要是不同ViewGroup的特性和某些屬性不能同時使用的問題,也可能是由不同Android系統(tǒng)版本自帶的Theme或者其他特性導致的。
功能兼容問題
獲得從相冊選擇的圖片的路徑
從相冊選擇圖片,系統(tǒng)會返回給我們Uri,但是個別情況我們也需要得到路徑,其實這就有一個兼容性問題,在不同系統(tǒng)版本的手機你會發(fā)現(xiàn)有的能得到路徑,有的不能。
這是因為不同手機可能返回的Uri的Shceme,導致出現(xiàn)這個問題,我遇到這個問題是很久之前了,當時沒有自己寫總結(jié),這里分享一個博客鏈接:http://blog.csdn.net/angcyo/article/details/52776904,供大家參考學習。
照相機拍照以及調(diào)用系統(tǒng)安裝
從7.0以后,為了提高app安全,Android不允許app與其他app通信時,傳遞明文的文件路徑,比較典型的例子就是app下載更新,安裝的時候需要通過自己的ContentProvider對apk的路徑進行加密,然后調(diào)用系統(tǒng)安裝。
有的時候需要調(diào)用系統(tǒng)相機拍照,并且指定照片的保存路徑。這個路徑我們也必須加密,否則會直接崩潰,具體的解決辦法我之前有寫過:適配android7.0:獲取文件的Uri。
權(quán)限
在Android 6.0以及國內(nèi)部分手機在Android 5.0開啟了權(quán)限申請,部分敏感權(quán)限需要手動申請,所以如果你需要使用某些權(quán)限,一定要記得申請,網(wǎng)上這部分資料非常多,這里就不多說了。
ScrollView滑動到底部的問題
這個問題是最近才發(fā)現(xiàn)的,看來測試機多了還是有好處的,一般我們監(jiān)聽到ScrollView是否滑動到底部通過重寫
onOverScrolled方法,判斷clampedY是否是true,如果是true,表示滑動到了底部。
protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY)但是在部分手機上clampedY始終返回false,例如我發(fā)現(xiàn)的錘子手機。
解決辦法:不僅要判斷clampedY是否等于true,還要判斷ScrollView的scrollY + getHeight + paddingTop + paddingBottom是否等于第一個子View的高度,下面貼出代碼:
@Overrideprotected void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) {super.onOverScrolled(scrollX, scrollY, clampedX, clampedY);if (scrollY != 0 && null != onScrollToBottom) {// 如果是false,需要額外判斷,解決部分手機的兼容問題,例如錘子if (!clampedY) {// 解決在錘子if (getScrollY() + getHeight() - getPaddingTop() - getPaddingBottom() == getChildAt(0).getHeight()) {onScrollToBottom.onScrollBottomListener(true);return;}}onScrollToBottom.onScrollBottomListener(clampedY);}}Theme兼容問題
使用Theme,推薦使用Theme.AppCompat下的主題,這樣避免兼容性問題,如果你看到了你的錯誤提示:
You need to use a Theme.AppCompat theme (or descendant) with this activity說明你也是一個有故事的人了,我遇到多發(fā)生在Android 8.0 和 華為手機。
布局兼容問題
RelativeLayout子View的padding、margin和center屬性的沖突
首先我們看一段代碼:<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="100dp"android:background="#000000"android:paddingRight="30dp"android:paddingBottom="10dp"><TextViewandroid:layout_marginTop="50dp"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:text="@string/app_name"android:textColor="#ffffff" /></RelativeLayout>在RelativeLayout設(shè)置paddingBottom=20dp,但是TextView設(shè)置了centerInParent并且設(shè)置了marginTop=50dp,會顯示出什么效果呢? 很明顯paddingBottom和marginTop都沒有生效,同樣的道理,子View的centerInHorizontal,centerInVertical屬性也是和父View的padding和自身的margin是不能同時生效的。 Button的默認大小問題 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:orientation="vertical"android:gravity="center"android:layout_height="match_parent"><Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="#00ff00"android:drawablePadding="5dp"android:text="hello button" /><TextViewandroid:layout_marginTop="20dp"android:layout_width="wrap_content"android:layout_height="wrap_content"android:background="#00ff00"android:textSize="14sp"android:textColor="#000000"android:drawablePadding="5dp"android:text="hello button" /></LinearLayout>
這里我特意設(shè)置了text="hello button", 因為英文會讓問題更明顯,Button和TextView都是wrap_content,理論上應該是一樣的效果,看一下展示圖:
咦?很明顯結(jié)果并不和我們預料的一樣,強調(diào)一下我使用的sdk版本是26,如果你的展示效果和我的不一樣,那就說明了一個問題:Button在不同的sdk中有不同的默認樣式。
接下來我們看一看默認樣式是什么:
// 首先我們查看Button的構(gòu)造方法,看到了Button使用了buttonStyle樣式 // 用過style切換主題的朋友對這種用法一定很熟悉,接下來我們要看看style文件里怎么定義的buttonStyle public Button(Context context, AttributeSet attrs) {this(context, attrs, com.android.internal.R.attr.buttonStyle); } <!-- Button styles --> // 順著主題的繼承關(guān)系,我們跟蹤到了Base.Widget.AppCompat.Button主題 <item name="buttonStyle">@style/Widget.AppCompat.Button</item> <style name="Widget.AppCompat.Button" parent="Base.Widget.AppCompat.Button"/>當我們繼續(xù)跟蹤代碼的時候出現(xiàn)了一個選擇框:
這個主題在sdk 21以下 和sdk以上分別使用了兩種主題,我們先看看sdk 21以下的style:
<style name="Base.Widget.AppCompat.Button" parent="android:Widget"><item name="android:background">@drawable/abc_btn_default_mtrl_shape</item><item name="android:textAppearance">?android:attr/textAppearanceButton</item><item name="android:minHeight">48dip</item><item name="android:minWidth">88dip</item><item name="android:focusable">true</item><item name="android:clickable">true</item><item name="android:gravity">center_vertical|center_horizontal</item> </style>再看看sdk 21以上的style:
<style name="Base.Widget.AppCompat.Button" parent="android:Widget.Material.Button"/> <!-- Bordered ink button --> <style name="Widget.Material.Button"><item name="background">@drawable/btn_default_material</item><item name="textAppearance">?attr/textAppearanceButton</item><item name="minHeight">48dip</item><item name="minWidth">88dip</item><item name="stateListAnimator">@anim/button_state_list_anim_material</item><item name="focusable">true</item><item name="clickable">true</item><item name="gravity">center_vertical|center_horizontal</item> </style>通過對比,我們發(fā)現(xiàn)兩種主題的背景,字體樣式是不同的,同時發(fā)現(xiàn)了有minWidth和minHeight,所以Button會有默認的大小,字母會全大寫是textAppearance中定義的,感興趣的朋友可以自己去看看里面還定義了哪些樣式。
解決辦法:設(shè)置Button的minWidth和minHeight等于0,你也可以按照你的需要修改其他的屬性。
總結(jié)
上面的幾點是我臨時整理的,還有很多的內(nèi)容都沒有寫出來,以后會慢慢補充,最后祝大家在新的一年里技術(shù)薪資雙提升!!!
總結(jié)
以上是生活随笔為你收集整理的Android兼容性小总结(一)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java公路车为什么便宜_JAVA公路自
- 下一篇: android sina oauth2.