android設備衆多,這致使適配各類機型很麻煩,其中屏幕適配也是一件棘手的事情。其中一種方式是在res文件夾下,根據不一樣的屏幕分辨率創建一一對應的values文件夾,以下圖所示: java
其實這種適配方式也能夠知足適配要求,使用起來中規中矩的感受。今天我想介紹另一種適配方案,那就是github.com/JessYanCodi…android
implementation 'me.jessyan:autosize:1.1.2'
git
<manifest>
<application>
<meta-data android:name="design_width_in_dp" android:value="360"/>
<meta-data android:name="design_height_in_dp" android:value="640"/>
</application>
</manifest>
複製代碼
public class CustomAdaptActivity extends AppCompatActivity implements CustomAdapt {
@Override
public boolean isBaseOnWidth() {
return false;
}
@Override
public float getSizeInDp() {
return 667;
}
}
複製代碼
若是某個特殊的activity不須要適配,則實現CancelAdapt
接口github
public class CancelAdaptActivity extends AppCompatActivity implements CancelAdapt {
}
複製代碼
fragment的適配跟activity如出一轍,都是實現CustomAdapt
接口進行適配,實現CancelAdapt
接口告訴框架不須要適配.markdown
「java.lang.RuntimeException: Unable to start activity ComponentInfo{com.wdg.tradecenter/com.yanzhenjie.permission.PermissionActivity}:java.lang.IllegalArgumentException: you must set design_width_in_dp in your AndroidManifest file」
app
能夠在Application#onCreate
方法中添加以下代碼取消對指定的activity和fragment取消適配檢查框架
AutoSizeConfig.getInstance()
.getExternalAdaptManager()
.addCancelAdaptOfActivity(PermissionActivity.class);
複製代碼
上圖是lanhu上的一張ui設計圖,咱們點擊控件,右下角直接就出現了對應的xml代碼,使用autosize進行適配,就能夠直接使用lanhu上生成的佈局代碼,這一點確實方便了一些。ide
單位 | 解釋 |
---|---|
px | 像素 |
dp | 獨立設備像素 計算公式:px = dp(dpi/160) |
dpi | 像素密度,指的是在系統軟件上指定的單位尺寸的像素數量,它每每是寫在系統出廠配置文件的一個固定值 |
經過上面的單位介紹及之間的轉換,咱們能夠獲得以下結論:oop
px= dp(dpi/160), density = dpi/160 => px = dp*density => dp = px/density; 明白上面這個結論,下面咱們來討論爲何咱們平常對控件設置的寬/高爲某一dp時,沒法作到各個手機屏幕的適配。佈局
設備 A , 屏幕寬度爲 720px, dpi爲160,則屏幕總dp爲 720/(160/160) = 720 dp 設備 B , 屏幕寬度爲 720px, dpi爲320,則屏幕總dp爲 720/(320/160) = 360 dp 能夠看到屏幕的總 dp 寬度在不一樣的設備上是會變化的,可是咱們在佈局中填寫的 dp 值倒是固定不變的,這就致使咱們設置的固定寬度在不一樣的設備上顯示的比例不同。 例如咱們佈局中有一個View設置固定寬度爲180dp,在設備A中會佔屏幕寬度的1/4,可是在設備B中只會佔屏幕寬度的1/2,這種差異是十分巨大的。
這時咱們要想完美適配,那就必須保證這個 View 在任何分辨率的屏幕上,與屏幕的比例都是相同的。
解決方案
由公式:dp = px/density 可知,因爲px是屏幕分辨率,這個值有硬件肯定,咱們是沒法改變的,那麼咱們能夠經過修改density 的值使得不一樣分辨率的手機寬度dp值是相同的,這樣當咱們對View設置爲某一特定的dp寬度時,佔總寬度的dp比例是相同的,這樣也就達到佔屏幕的比例相同。
那麼問題來了,咱們如何肯定density 的值呢?
由dp = px/density => 屏幕的總 px 寬度 / density = 屏幕的總 dp 寬度
屏幕的總 px 寬度 / density = 屏幕的總 dp 寬度 => 當前設備屏幕總寬度(單位爲像素)/ 設計圖總寬度(單位爲 dp) = density
若是咱們將一套設計圖的總寬度(dp)做爲最終手機屏幕的中寬度(dp), 從而達到修改density的目的,同時又能夠保證最終不一樣分辨率手機的屏幕總寬度是相同的,這也就完成了適配。
AndroidAutoSize
/今日頭條 就是基於這個原理來實現屏幕適配的。
AndroidAutoSize
是怎麼以最小侵入代價應用上述原理的
利用ContentProvider
初始化該庫—— ContentProvider
的onCreate
的調用時機介於Application
的attachBaseContext
和onCreate
之間。
在初始化的時候註冊了一個Application.ActivityLifecycleCallbacks
接口類回調
application.registerActivityLifecycleCallbacks(mActivityLifecycleCallbacks);
在接口Application.ActivityLifecycleCallbacks
的實現類中修改density,以達到適配目的。
總結 這個適配方案優勢明顯
使用成本低,簡單。 代碼侵入性低 沒有性能損耗 可適配activity/fragment/dialog/toast等 缺點
既然AndroidAutoSize庫能夠修改density,其它庫也能夠修改,那麼這樣就會致使衝突。