讨论:今日头条适配方案使用中出现的问题

2,320 阅读3分钟

这里主要是想和大家讨论下头条适配原文使用中出现的一些问题和解决方法 有更好的方法或者有什么不对的欢迎批评

头条适配代码

  1. 启动页图片问题

    • 给启动的activity指定一个背景,不设置布局让程序快速进入启动页
    <!--启动页主题-->
    <style name="ThemeSplash" parent="Theme.AppCompat.Light.NoActionBar">
    	<item name="android:background">@drawable/layer_bg_splash</item>
    	<item name="android:windowFullscreen">true</item>
    	<item name="android:windowTranslucentNavigation">true</item>
    </style>
    <!--启动页 背景-->
    <?xml version="1.0" encoding="utf-8"?>
    <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:drawable="@color/bg_main_color" />
        <item
            android:gravity="center">
            <bitmap
                android:gravity="center"
                android:src="@drawable/ic_logo_white" />
        </item>
    </layer-list>
    
    • 问题:activity应用还在初始化,onCreate还没有执行,默认显示了背景图,此时的背景图上的logo是没有使用适配方案的效果,当onCrate被执行后,屏幕的密度发生变化,logo会放大缩小。
    • 解决方法:
      1. 不让启动页适配
      2. 启动页主题设置<item name="android:windowDisablePreview">true</item>,让app加载完后进入启动页
  2. 横竖切换适配无效

    • 当横竖屏切换且我们在配置文件中设置了android:configChanges=,在我们切换了屏幕方向,或者其它操作时会调用:
    @Override
    public void onConfigurationChanged(Configuration newConfig) {
            super.onConfigurationChanged(newConfig);
    
            if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
                Logger.e("当前屏幕为横屏");
            } else {
                Logger.e("当前屏幕为竖屏");
                //退出全屏后重新适配屏幕
                ScreenFitUtils.setCustomDensity(this, getApplication());
            }
        }
    

    我们在看下super调用的父类方法做了什么

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
            super.onConfigurationChanged(newConfig);
            getDelegate().onConfigurationChanged(newConfig);
            if (mResources != null) {
                // The real (and thus managed) resources object was already updated
                // by ResourcesManager, so pull the current metrics from there.
                final DisplayMetrics newMetrics = super.getResources().getDisplayMetrics();
                mResources.updateConfiguration(newConfig, newMetrics);
            }
        }
    

    可以看到被重置了,所以我们在前面的适配又变成了原始的数据,如果这时候你刷新界面,界面会变成没有适配的效果。

    • 解决办法:
      1. 在回调中再调用一次适配方法
  3. 第三方库问题

    • 当我使用节操播放器退出全屏的时候,再打开其他界面界面变得非常奇怪
    • 原因
    if (sRoncompatDennsity == 0) {
    	sRoncompatDennsity = appDisplayMetrics.density;
    	sRoncompatScaledDensity = appDisplayMetrics.scaledDensity;
    	application.registerComponentCallbacks(new ComponentCallbacks() {
    		@Override
    		public void onConfigurationChanged(Configuration newConfig) {
    			if (newConfig != null && newConfig.fontScale > 0) {
    				sRoncompatScaledDensity = application.getResources().getDisplayMetrics().scaledDensity;
                        }
                    }
            @Override
    		public void onLowMemory() {}
    	});
    }
    

    当节操播放器横屏播放退出时系统调用了onConfigurationChanged(我也不知道为啥)方法,而且scaledDensity发生了变化(我的设备是pixel默认2.6,适配后3.0,退出全屏变成了4.0)。最糟糕的是只要sRoncompatDennsity不等于0就不会去获取系统默认的density,scaledDensity导致字体变得超级大

    • 解决办法:
      • 不设置registerComponentCallbacks监听这样系统修改文字不能实时更新
      • 注释掉if (sRoncompatDennsity == 0)每次都去获取系统的密度参数
  4. AlertDialog等弹窗超出屏幕

    因为dialog用的是activitycontext,所以被动的被适配了,密度发生了变化。

    • 解决办法:
      • 修改style
        <style name="CustomAlertDialog" parent="ThemeOverlay.AppCompat.Dialog.Alert">
            <!--<item name="android:windowBackground">@drawable/shape_dialog_bg</item>-->
            <!-- 宽度 -->
            <item name="android:windowMinWidthMinor">300dp</item>
            <item name="windowFixedWidthMinor">300dp</item>
        </style>
        
      • 手动修改宽度,适合那些无法设置宽度属性的弹窗
         Window window = dialog.getWindow();
         WindowManager.LayoutParams layoutParams;
        if (window != null) {
            window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
            window.getDecorView().setPadding(0, 0, 0, 0);
            layoutParams = window.getAttributes();
            layoutParams.width = RuleUtils.getScreenWidth(context);
            window.setAttributes(layoutParams);
            window.setGravity(Gravity.CENTER);
            window.setWindowAnimations(R.style.PopScaleAnimStyle);
        }