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

屏幕适配基础图标

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:0.9.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).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

}

/**
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;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容