屏幕适配方案有很多,比如原生的dp,鸿洋大神的AutoLayout,宽高限定符,今天我用缺点比较小的今日头条方案
头条适配方案的文章链接:https://mp.weixin.qq.com/s/d9QCoBP6kV9VSWvVldVVwA
测试后可以适配我身边的所有机型(其他的应该是都可以)
优点:适配简单,无侵入,调用简单,未使用非官方api,不影响性能
缺点:基本可以通过骚操作来避免
复制工具类
-
import android.app.Activity;
-
import android.util.DisplayMetrics;
-
-
/**
-
* 创 建: lt 2018/8/15--14:45
-
* 作 用: 使用并优化今日头条的适配方案的工具类
-
* 注意事项: 在Activity的onCreate里,并在setContextView之上调用,可以直接放在Base里
-
*/
-
-
public
class FitUtil {
-
private
static
float width =
750;
//todo 手动设置为设计图的宽,适配将根据宽为基准,也可以设置高,但是推荐设置宽,如果不需要px=dp则不设置也行
-
private
static
int dpi =
375;
//todo 手动设置设计图的dpi,不知道可以设计图的宽除2测试一下
-
private
static
float nativeWidth =
0;
//真实屏幕的宽,不需要手动改
-
-
/**
-
* 在Activity的onCreate中调用,修改该Activity的density,即可完成适配,使用宽高直接使用设计图上px相等的dp值
-
*
-
* @param activity 需要改变的Activity
-
* @param isPxEqualsDp 是否需要设置为设计图上的px直接在xml上写dp值(意思就是不需要自己计算dp值,直接写设计图上的px值,并改单位为dp),但开启后可能需要手动去设置ToolBar的大小,如果不用可以忽略
-
*/
-
public static void autoFit(Activity activity, boolean isPxEqualsDp) {
-
if (nativeWidth ==
0) {
-
nativeWidth = activity.getWindowManager().getDefaultDisplay().getWidth();
-
}
-
DisplayMetrics displayMetrics = activity.getResources().getDisplayMetrics();
-
displayMetrics.density = isPxEqualsDp ? nativeWidth / dpi / (width / dpi) : nativeWidth / dpi;
-
displayMetrics.densityDpi = (
int) (displayMetrics.density *
160);
-
}
-
}
在Activity的onCreate里,并在setContextView之上调用,可以直接放在Base里,比如:
-
public
class BaseActivity extends AppCompatActivity {
-
-
@Override
-
protected void onCreate(Bundle savedInstanceState) {
-
super.onCreate(savedInstanceState);
-
FitUtil.autoFit(
this,
true);
//this
-
}
-
}
手动设置好UI给你的设计图的宽和dp(请查看注释自行计算)
单位用dp,字体单位也用dp,就可以自动适配了
需要注意方法的第二个参数
如果UI给你的图纸是按照dp为单位,就设置为false,然后页面上直接写相应的dp值就ok
如果UI给你的图纸是按照px为单位,就设置为true,然后页面上写对应的px值,但是单位写成dp,相当于直接从UI设计图上抄下来,很方便
但是推荐设置为false,如果设计图纸是px为单位则自行计算,因为设置为true会使其他的三方View变得偏小
由于px=dp方案留有一些坑(三方View框架也会用到dp值,而部分无法手动去修改),所以该px=dp的方案并不推荐使用,但是若小伙伴又想如此适配,又想使用px=dp方案的话,接下来我会提供一下骚操作供参考
查看源码可知,系统在使用距离值的时候会把所有的单位值转换为px值来应用,而转换方法如下:
-
TypedValue.java下
-
public static float applyDimension(int unit, float value,
-
DisplayMetrics metrics)
-
{
-
switch (unit) {
-
case COMPLEX_UNIT_PX:
-
return
value;
-
case COMPLEX_UNIT_DIP:
-
return
value * metrics.density;
-
case COMPLEX_UNIT_SP:
-
return
value * metrics.scaledDensity;
-
case COMPLEX_UNIT_PT:
-
return
value * metrics.xdpi * (
1.0f/
72);
-
case COMPLEX_UNIT_IN:
-
return
value * metrics.xdpi;
-
case COMPLEX_UNIT_MM:
-
return
value * metrics.xdpi * (
1.0f/
25.4f);
-
}
-
return
0;
-
}
可以看到系统提供了六种单位,上面就是修改了dp的计算系数来适配屏幕,而一些三方框架可能会使用dp,sp甚至是px来给View设置宽高,所以可以将目光放在基本不用的单位上
我们可以使用in这个单位(英寸),修改方法:
-
public static void autoFit2(Activity activity, boolean isPxEqualsDp) {
-
if (nativeWidth ==
0) {
-
nativeWidth = activity.getWindowManager().getDefaultDisplay().getWidth();
-
}
-
DisplayMetrics displayMetrics = activity.getResources().getDisplayMetrics();
-
displayMetrics.xdpi = isPxEqualsDp ? nativeWidth / dpi / (width / dpi) : nativeWidth / dpi;
-
}
然后所有值抄设计图上的,单位用in,则可以解决上述问题
亲测可以使用,并且适配三方框架,也不会影响到系统控件;但,该方案缺点也有,所以该方案仅供参考
所以上面的几种方案需要自行选择判断