屏幕适配之今日头条适配(逻辑清晰简单)

屏幕适配基础图标

drawable 选择器, shape标签 ,帧动画列表 密度值 分辨率 密度比
drawable-ldpi 低分辨率目录 120 240320 0.75 公式 密度值除160
drawable-mdpi 中等分辨率目录 160 320
480 1
drawable-hdpi 高分辨率目录 240 480800 1.5
drawable-xhdpi 特高分辨率目录 320 720
1280 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.

/**
isBaseOnWidth()
是否按照宽度进行等比例适配 (为了保证在高宽比不同的屏幕上也能正常适配, 所以只>能在宽度和高度之中选一个作为基准进行适配)

@return {@code true} 为按照宽度适配, {@code false} 为按照高度适配
*/

/**
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">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;
}

猜你喜欢

转载自blog.csdn.net/u013512708/article/details/119042211
今日推荐