天天看點

螢幕适配之今日頭條适配(邏輯清晰簡單)

螢幕适配基礎圖示

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;
}