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