关于今日头条适配方案需要注意的
今日头条:一种极低成本的Android屏幕适配方式
https://mp.weixin.qq.com/s/d9QCoBP6kV9VSWvVldVVwA
自从看了今日头条的适配方案,就被这种容易操作,成本低廉的方案所吸引,大厂出品果然都是精品,大厂的开发在钻研技术上果然不是吹的。
下面说下第一次使用今日头条的方案,感受:
刚开始看到代码,方案理论,确实很好,++是以更改屏幕密度为核心++,直接把代码全部复制下来,放到测试项目中试用今日头条的方法代码
// 系统的Density
private static float sNoncompatDensity;
// 系统的ScaledDensity
private static float sNoncompatScaledDensity;
public static void setCustomDensity(Activity activity, Application application) {
DisplayMetrics displayMetrics = application.getResources().getDisplayMetrics();
if (sNoncompatDensity == 0) {
sNoncompatDensity = displayMetrics.density;
sNoncompatScaledDensity = displayMetrics.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() {
}
});
}
// 此处以360dp的设计图作为例子
float targetDensity=displayMetrics.widthPixels/360;
float targetScaledDensity=targetDensity*(sNoncompatScaledDensity/sNoncompatDensity);
int targetDensityDpi= (int) (160 * targetDensity);
displayMetrics.density = targetDensity;
displayMetrics.scaledDensity = targetScaledDensity;
displayMetrics.densityDpi = targetDensityDpi;
DisplayMetrics activityDisplayMetrics = activity.getResources().getDisplayMetrics();
activityDisplayMetrics.density = targetDensity;
activityDisplayMetrics.scaledDensity = targetScaledDensity;
activityDisplayMetrics.densityDpi = targetDensityDpi;
}
以上是今日头条的代码;
看到方法的参数和里面的内容,我就在想为啥同时使用Activity和Application
setCustomDensity(Activity activity, Application application)
其实可以直接使用Application,不必使用Activity啊,为啥要用两个呢?
然后我就试着只使用Application,抛弃了activity这个参数。
因为这样不必每一个activity中都要调用这个方法了,直接继承Application,写在里面就好了,想想的很美好的样子
上手开始run()代码;
发现方案并没有起作用,这让我百思不得其解,然后又重新回到了今日头条方案上,通过各种查资料发现:
Application中只能获取屏幕的density,scaledDensity,densityDpi,并不能修改,或者说修改了并不生效。
那好吧,今日头条的方法果然必须是这样的,没有多余,没有缺少,果然牛逼
然后我就封装了一个activity类,测试使用继承这个类,不必在每个activity中都调用一次这样的方法了。
然后我开始run()代码,果然很牛逼第一个手机试验成功,紧接着把手上的测试机全部试验一下,果然很完美,正在我开心的时候,测试机上收到其他APP的推送消息,我点了一下,调整到其他APP,然后我看完,回来准备接着享受这种低成本的适配方案时,发现刚刚适配的方案失效了,what?这是什么原因?
请注意:我刚刚是从适配的的demo跳转到了其他的APP,然后又回到了demo
通过多次尝试,试验发现适配方法只在调用布局之前更改了该activity的密度,更改完并不是一直更改,而是在onResume()后使用了系统的密度,而我没有在onResume()方法中添加所以导致了这个情况。
原来,在activity中除了要添加在onCreate中布局创建之前,还要在onResume()方法中添加一下
这些调整完,我紧接着想到了,弹出对话框,以及Toast等等这些,因为弹出对话框需要适配,Toast并不需要适配,但是我调整了字体大小,会不会影响到Toast;带着这些疑问,我就又开始探索了;
发现在使用Application的对象调用时Toast的字体大小正常,而弹出框的size就不行了不适配了,原因也很简单,上述说的,只在activity中适配了
使用activity的对象调用Toast时,字体大小发生了不适配,而弹出框就正常
由此发现Toast不能再activity中对象使用,不然会影响字体的,所以我直接封装了一个Toast使用Application的对象。对于弹出对话框,其实一般不怎么使用Application,只要不使用Application对象没啥问题的。
差不多到这,基本上没啥大问题了,项目中基本上都可以通用了。
最后:
1.Application中只能获取屏幕的density,scaledDensity,densityDpi,并不能修改,或者说修改了并不生效,需要在activity调用
2.在activity中除了要添加在onCreate中布局创建之前,还要在onResume()方法中添加一下
3.由此发现Toast不能再activity中对象使用,不然会影响字体的,所以我直接封装了一个Toast使用Application的对象。
4.对于弹出对话框,其实一般不怎么使用Application,只要不使用Application对象没啥问题的