螢幕适配基礎圖示
drawable 選擇器, shape标簽 ,幀動畫清單 密度值 分辨率 密度比
drawable-ldpi 低分辨率目錄 120 240320 0.75 公式 密度值除160
drawable-mdpi 中等分辨率目錄 160 320480 1
drawable-hdpi 高分辨率目錄 240 480800 1.5
drawable-xhdpi 特高分辨率目錄 320 7201280 2
drawable-xxhpi 超高分辨率目錄 480 1080*1920 3
drawable-xxxhdpi 超超高分辨率目錄
在螢幕密度是120的手機上 1dp=0.75px
在螢幕密度是160的手機上 1dp=1px
在螢幕密度是240的手機上 1dp=1.5px
在螢幕密度是320的手機上 1dp=2px
在螢幕密度是480的手機上 1dp=3px
在螢幕密度是640的手機上 1dp=4px
寬度是100px 160 100dp
寬度是100px 240 66.7dp
寬度是100px 320 50dp
寬度是100px 480 33.3dp
寬度是100px 640 25dp
适配市場上主流的手機螢幕(流量研究院,全域羅盤)
今日頭條适配
大概的實作原理:
px = dp * density
目前裝置螢幕總寬度(機關為像素)/ 設計圖總寬度(機關為 dp) = density
mPx:目前裝置螢幕總寬度(變化)
mDp:設計圖總寬度(不變)
mDensity: mPx/mDp 系數比(變化)
1.假設目前裝置的螢幕總寬度為1080px,目前設計圖總寬度為375dp,根據以上計算出mDensity為2.88
螢幕上有一個50dp50dp的控件,轉化為px是50dp2.88=144px
144px/1080px=0.133 即此控件占螢幕的實際比例為0.133
2.假設目前裝置的螢幕總寬度為1440 px,目前設計圖總寬度為375dp,根據以上計算出mDensity為 3.84
螢幕上有一個50dp50dp的控件,轉化為px是50dp 3.84= 192px
192px/1080px=0.133 即此控件占螢幕的實際比例為0.133
由此可看出,随着螢幕大小的變化,控件的實際占比是一樣的
第一步:
1.使用步驟:
implementation 'me.jessyan:autosize:1.2.1'
2.聲明設計圖中的尺寸(如果項目完全使用副機關, 則可以直接以像素為機關填寫 AndroidManifest 中需要填寫的設計圖尺寸, 不需再把像素轉化為 dp)
<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>
3.MyApplication中(記得清單檔案注冊)可以設定副機關(隻能在 pt、in、mm 這三個冷門機關中選擇一個作為副機關,選擇什麼機關就在 layout 檔案中用什麼機關進行布局)。
AutoSizeConfig.getInstance().getUnitsManager()
.setSupportDP(false)
.setSupportSP(false)
.setSupportSubunits(Subunits.MM);
副機關是用于規避修改 {@link DisplayMetrics#density} 所造成的對于其他使用 dp 布局的系統控件或三方庫控件的不良影響
副機關是用于規避修改 {@link DisplayMetrics#density} 所造成的對于其他使用 dp 布局的系統控件或三方庫控件的不良影響
public enum Subunits {
/**
* 不使用副機關
*/
NONE,
/**
* 機關 pt
*
* @see android.util.TypedValue#COMPLEX_UNIT_PT
*/
PT,
/**
* 機關 in
*
* @see android.util.TypedValue#COMPLEX_UNIT_IN
*/
IN,
/**
* 機關 mm
*
* @see android.util.TypedValue#COMPLEX_UNIT_MM
*/
MM
4.
/**
getSizeInDp()
傳回設計圖上的設計尺寸, 機關 dp
{@link #getSizeInDp} 須配合 {@link #isBaseOnWidth()} 使用, 規則如下:
如果 {@link #isBaseOnWidth()} 傳回 {@code true}, {@link #getSizeInDp} 則應該傳回設計圖的總寬度
如果 {@link #isBaseOnWidth()} 傳回 {@code false}, {@link #getSizeInDp} 則應該傳回設計圖的總高度
如果您不需要自定義設計圖上的設計尺寸, 想繼續使用在 AndroidManifest 中填寫的設計圖尺寸,
{@link #getSizeInDp} 則傳回 {@code 0}
@return 設計圖上的設計尺寸, 機關 dp
Activity(BaseActivity)
public class CustomAdaptActivity extends AppCompatActivity implements CustomAdapt {
@Override
public boolean isBaseOnWidth() {
return false;
}
@Override
public float getSizeInDp() {
return 667;
}
}
Fragment
public class CustomAdaptFragment extends Fragment implements CustomAdapt {
@Override
public boolean isBaseOnWidth() {
return false;
}
@Override
public float getSizeInDp() {
return 667;
}
}
XML
<TextView
android:layout_width="200mm"
android:layout_height="100mm"
android:background="@color/colorAccent" />
完整demo
<!-- 這個 Demo 主要展示副機關的用法, 如果隻使用副機關 (pt、in、mm) 就可以直接以像素作為機關填寫設計圖的尺寸, 不需再把像素轉化為 dp-->
<meta-data
android:name="design_width_in_dp"
android:value="1080"/>
<meta-data
android:name="design_height_in_dp"
android:value="1920"/>
BaseApplication
public class BaseApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
//對機關的自定義配置, 請在 App 啟動時完成
configUnits();
}
/**
* 注意!!! 布局時的實時預覽在開發階段是一個很重要的環節, 很多情況下 Android Studio 提供的預設預覽裝置并不能完全展示我們的設計圖
* 是以我們就需要自己建立模拟裝置, 以下連結是給大家的福利, 按照連結中的操作可以讓預覽效果和設計圖完全一緻!
* @see <a href="https://github.com/JessYanCoding/AndroidAutoSize/blob/master/README-zh.md#preview" target="_blank" rel="external nofollow" >dp、pt、in、mm 這四種機關的模拟裝置建立方法</a>
* <p>
* v0.9.0 以後, AndroidAutoSize 強勢更新, 将這個方案做到極緻, 現在支援5種機關 (dp、sp、pt、in、mm)
* {@link UnitsManager} 可以讓使用者随意配置自己想使用的機關類型
* 其中 dp、sp 這兩個是比較常見的機關, 作為 AndroidAutoSize 的主機關, 預設被 AndroidAutoSize 支援
* pt、in、mm 這三個是比較少見的機關, 隻可以選擇其中的一個, 作為 AndroidAutoSize 的副機關, 與 dp、sp 一起被 AndroidAutoSize 支援
* 副機關是用于規避修改 {@link DisplayMetrics#density} 所造成的對于其他使用 dp 布局的系統控件或三方庫控件的不良影響
* 您選擇什麼機關, 就在 layout 檔案中用什麼機關布局
* <p>
* 兩個主機關和一個副機關, 可以随時使用 {@link UnitsManager} 的方法關閉和重新開啟對它們的支援
* 如果您想完全規避修改 {@link DisplayMetrics#density} 所造成的對于其他使用 dp 布局的系統控件或三方庫控件的不良影響
* 那請調用 {@link UnitsManager#setSupportDP}、{@link UnitsManager#setSupportSP} 都設定為 {@code false}
* 停止對兩個主機關的支援 (如果開啟 sp, 對其他三方庫控件影響不大, 也可以不關閉對 sp 的支援)
* 并調用 {@link UnitsManager#setSupportSubunits} 從三個冷門機關中選擇一個作為副機關
* 三個機關的效果都是一樣的, 按自己的喜好選擇, 比如我就喜歡 mm, 翻譯為中文是妹妹的意思
* 然後在 layout 檔案中隻使用這個副機關進行布局, 這樣就可以完全規避修改 {@link DisplayMetrics#density} 所造成的不良影響
* 因為 dp、sp 這兩個機關在其他系統控件或三方庫控件中都非常常見, 但三個冷門機關卻非常少見
*/
private void configUnits() {
//AndroidAutoSize 預設開啟對 dp 的支援, 調用 UnitsManager.setSupportDP(false); 可以關閉對 dp 的支援
//主機關 dp 和 副機關可以同時開啟的原因是, 對于舊項目中已經使用了 dp 進行布局的頁面的相容
//讓開發者的舊項目可以漸進式的從 dp 切換到副機關, 即新頁面用副機關進行布局, 然後抽時間逐漸的将舊頁面的布局機關從 dp 改為副機關
//最後将 dp 全部改為副機關後, 再使用 UnitsManager.setSupportDP(false); 将 dp 的支援關閉, 徹底隔離修改 density 所造成的不良影響
//如果項目完全使用副機關, 則可以直接以像素為機關填寫 AndroidManifest 中需要填寫的設計圖尺寸, 不需再把像素轉化為 dp
AutoSizeConfig.getInstance().getUnitsManager()
.setSupportDP(false)
//當使用者想将舊項目從主機關過渡到副機關, 或從副機關過渡到主機關時
//因為在使用主機關時, 建議在 AndroidManifest 中填寫設計圖的 dp 尺寸, 比如 360 * 640
//而副機關有一個特性是可以直接在 AndroidManifest 中填寫設計圖的 px 尺寸, 比如 1080 * 1920
//但在 AndroidManifest 中卻隻能填寫一套設計圖尺寸, 并且已經填寫了主機關的設計圖尺寸
//是以當項目中同時存在副機關和主機關, 并且副機關的設計圖尺寸與主機關的設計圖尺寸不同時, 可以通過 UnitsManager#setDesignSize() 方法配置
//如果副機關的設計圖尺寸與主機關的設計圖尺寸相同, 則不需要調用 UnitsManager#setDesignSize(), 架構會自動使用 AndroidManifest 中填寫的設計圖尺寸
// .setDesignSize(2160, 3840)
//AndroidAutoSize 預設開啟對 sp 的支援, 調用 UnitsManager.setSupportSP(false); 可以關閉對 sp 的支援
//如果關閉對 sp 的支援, 在布局時就應該使用副機關填寫字型的尺寸
//如果開啟 sp, 對其他三方庫控件影響不大, 也可以不關閉對 sp 的支援, 這裡我就繼續開啟 sp, 請自行斟酌自己的項目是否需要關閉對 sp 的支援
// .setSupportSP(false)
//AndroidAutoSize 預設不支援副機關, 調用 UnitsManager#setSupportSubunits() 可選擇一個自己心儀的副機關, 并開啟對副機關的支援
//隻能在 pt、in、mm 這三個冷門機關中選擇一個作為副機關, 三個機關的适配效果其實都是一樣的, 您覺的哪個機關看起順眼就用哪個
//您選擇什麼機關就在 layout 檔案中用什麼機關進行布局, 我選擇用 mm 為機關進行布局, 因為 mm 翻譯為中文是妹妹的意思
//如果大家生活中沒有妹妹, 那我們就讓項目中最不缺的就是妹妹!
.setSupportSubunits(Subunits.MM);
}
BaseActivity
public class BaseActivity extends AppCompatActivity implements CustomAdapt {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_custom_adapt);
}
/**
* 是否按照寬度進行等比例适配 (為了保證在高寬比不同的螢幕上也能正常适配, 是以隻能在寬度和高度之中選擇一個作為基準進行适配)
*
* @return {@code true} 為按照寬度進行适配, {@code false} 為按照高度進行适配
*/
@Override
public boolean isBaseOnWidth() {
return false;
}
/**
* 這裡使用 iPhone 的設計圖, iPhone 的設計圖尺寸為 750px * 1334px, 因為這個頁面使用副機關進行布局
* 是以可以直接以像素作為機關傳回設計圖的尺寸
* <p>
* 傳回設計圖上的設計尺寸
* {@link #getSizeInDp} 須配合 {@link #isBaseOnWidth()} 使用, 規則如下:
* 如果 {@link #isBaseOnWidth()} 傳回 {@code true}, {@link #getSizeInDp} 則應該傳回設計圖的總寬度
* 如果 {@link #isBaseOnWidth()} 傳回 {@code false}, {@link #getSizeInDp} 則應該傳回設計圖的總高度
* 如果您不需要自定義設計圖上的設計尺寸, 想繼續使用在 AndroidManifest 中填寫的設計圖尺寸, {@link #getSizeInDp} 則傳回 {@code 0}
*
* @return 設計圖上的設計尺寸
*/
@Override
public float getSizeInDp() {
return 1334;
}