今日头条的布局和字体适配方式

本文介绍了字节跳动技术团队提出的一种低成本Android屏幕适配方案,该方案通过调整Activity的DisplayMetrics实现。在Application中利用ActivityLifecycleCallbacks监听并设置适配,确保每个Activity都能正确应用。文章探讨了为何需要在每个Activity中重设适配信息,与Resource对象的生命周期相关。
摘要由CSDN通过智能技术生成

本文:https://www.jianshu.com/p/f1a61baf66a6
原文:一种极低成本的Android屏幕适配方式 - 字节跳动技术团队

前言

屏幕适配啊,老生长谈的问题,因为Android碎片化的原因,屏幕的分辨率简直是五花八门啊,不说别的,打开studio模拟器里就可以搞一大堆不同分辨率的模拟器。

适配是个头疼的事啊,虽然Android官方提供了dp单位来适配,但是在某些时候特殊的屏幕分辨率下,UI还是变形的难看的不行。

下面说一种字节跳动技术团队提供的适配方式,据说是今日头条中使用的方式。

详细的信息大家直接去看原文吧,链接如下:
原文:一种极低成本的Android屏幕适配方式 - 字节跳动技术团队

原文最终方案

我这里呢,就把原文里面实现的代码最终方案敲了一下,方便大家参阅。
同时在 Activity#onCreate 方法中调用下就行了。

    // 适配
    private static float sNonCompatDensity;
    private static float sNonCompatScaledDensity;

    // 默认设计图为360dp
    private final static float TARGET_SCREEN_WIDTH_DP = 360;

    private static void setCustomDensity(@NonNull Activity activity, @NonNull final Application application) {
        final DisplayMetrics appDisplayMetrics = application.getResources().getDisplayMetrics();

        if (sNonCompatDensity == 0) {
            sNonCompatDensity = appDisplayMetrics.density;
            sNonCompatScaledDensity = appDisplayMetrics.scaledDensity;

            application.registerComponentCallbacks(new ComponentCallbacks() {
                @Override
                public void onConfigurationChanged(Configuration newConfig) {
                    if (newConfig != null && newConfig.fontScale > 0) {
                        sNonCompatScaledDensity = application.getResources().getDisplayMetrics().scaledDensity;
                    }
                }

                @Override
                public void onLowMemory() {

                }
            });
        }
        final float targetDensity = appDisplayMetrics.widthPixels / TARGET_SCREEN_WIDTH_DP;
        final float targetScaledDensity = targetDensity * (sNonCompatScaledDensity / sNonCompatDensity);
        final int targetDensityDpi = (int) (160 * targetDensity);


        appDisplayMetrics.density = targetDensity;
        appDisplayMetrics.scaledDensity = targetScaledDensity;
        appDisplayMetrics.densityDpi = targetDensityDpi;

        final DisplayMetrics activityDisplayMetrics = activity.getResources().getDisplayMetrics();
        activityDisplayMetrics.density = targetDensity;
        activityDisplayMetrics.scaledDensity = targetScaledDensity;
        activityDisplayMetrics.densityDpi = targetDensityDpi;
    }
}

如何确保每个Activity的应用

在使用过程中,因为发现项目中存在不少未继承Base类的Activity,这就尴尬了。
觉得去找每一个Activity的onCreate又不太现实,这里想到了一个其它方式。

ActivityLifecycleCallbacks
Application 中通过 registerActivityLifecycleCallbacks 监听Activity的生命周期,并在onCreate中设置适配。


public class DemoApplication extends Application {

    private static DemoApplication mApplication = null;

    @Override
    public void onCreate() {
        super.onCreate();
        mApplication = this;

        ...

        registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
            @Override
            public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
                // 修改适配信息
                setCustomDensity(activity,mApplication);
            }

            @Override
            public void onActivityStarted(Activity activity) { }

            @Override
            public void onActivityResumed(Activity activity) { }

            @Override
            public void onActivityPaused(Activity activity) { }

            @Override
            public void onActivityStopped(Activity activity) { }

            @Override
            public void onActivitySaveInstanceState(Activity activity, Bundle outState) { }

            @Override
            public void onActivityDestroyed(Activity activity) { }
        });

    }

    private static void setCustomDensity( ... ) { ... }

}

为什么要每个Activity都进行重设

主要和 Resource 的创建有关。
我这里先简单说一下,详细可以翻阅资料,或者以后有时间在做个 Resource 相关的文章。

每个Activity的Resource资源是独立的,并且有缓存。
在Activity启动的时候,根据activityToken,overrideConfig等关键信息去更新或者重新生成Resource放入缓存种以供使用。
而我们目前适配的方式,更改的只是某个Resource对象,不是全部,即使是全部的,也存在一个Resource可能被更新的问题。所以才需要每个Activity中都进行设置。

结语

有什么不对的地方,欢迎大家指正。

参考文献

本文:https://blog.csdn.net/CrazyApes/article/details/117136453
原文:一种极低成本的Android屏幕适配方式 - 字节跳动技术团队
参考:https://developer.android.google.cn/guide/practices/screens_support

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值