一行代码搞定安卓全屏幕适配——简单粗暴-低入侵,无继承,简单高效

 

话不多说,先上解决方案

方案 0(强烈推荐,最新方案)

复制AdaptScreenUtils.java工具类

//baseActivity (或需要适配的页面)中添加(注意750为设计图宽度)
override fun getResources(): Resources { return ScreenAdaptUtils.adaptWidth(super.getResources(), 750) }

代码中控件宽高设置可以使用Ada ptScreenUtils.pt2px()转化后赋值,字体大小由于系统默认是ps,可转化为ps或使用setTextSize(TypedValue.COMPLEX_UNIT_PT, size)方法

方案一(推荐)

 ##### 1.引用工具类  

    DensityHelper.java

 ##### 2.在自定义的 Application onCreate 方法中加入

    new DensityHelper(this, DESIGN_WIDTH).activate();  //DESIGN_WIDTH为设计图宽度,同样不要忘记清单文件配置Application,另 布局中使用pt

  为啥使用宽度,不考虑高度呢?

  因为高度有状态栏,等比例换算会导致变形

方案二  

 

  /**  将此文件直接复制到项目中,不要忘记清单文件配置Application,另 布局中使用pt
  *	(例如: android:layout_height="300pt" 用错可不适配哦!)
  *	feisher  @2017年8月11日14:52:27 二次整理,原稿 为新浪大牛 布隆  
  *	458079442@qq.com
  */
  public class MyApplication extends Application{

  	public final static float DESIGN_WIDTH = 750; //绘制页面时参照的设计图宽度

  	@Override
  	public void onCreate() {
  		super.onCreate();
  		resetDensity();//注意不要漏掉
  	}

  	@Override
  	public void onConfigurationChanged(Configuration newConfig) {
          super.onConfigurationChanged(newConfig);
          resetDensity();//这个方法重写也是很有必要的
  	}

      public void resetDensity(){
          Point size = new Point();
          ((WindowManager)getSystemService(WINDOW_SERVICE)).getDefaultDisplay().getSize(size);
          getResources().getDisplayMetrics().xdpi = size.x/DESIGN_WIDTH*72f;
      }
  }

为什么会有这么一篇文章呢?

现状

由于Android碎片化严重,屏幕适配一直是开发中较为头疼的问题。面对市面上五花八门的屏幕大小与分辨率,Android基于dp与res目录名称来适配的方案已无法满足一次编写全屏幕适配的需求,为了达到最优的视觉效果,开发过程中总是需要花费较多资源进行适配。也有开发者给出了一些自己的解决方案。首先来分析一下一些常见的解决方案的现状:

  1. 官方适配方案

玩家适配方案

广大玩家的适配目的很明确,目的就是要确保控件在不同屏幕的相对大小一致,看起来一毛一样的。以一位大神玩家的两种适配方案为例:

2

进行一下探索和尝试如何?

个人觉得AutoLayout的设计思想非常优秀,但是将LayoutParams与属性作为切入口在mesure过程中进行转换计算的方案存在效率与扩展性等方面的问题。那么Android计算长度的收口在哪里,能不能在Android计算长度时进行换算呢?如果能在Android计算长度时进行换算,那么就不需要一系列多余的计算以及适配,一切问题就都迎刃而解了。

经过一番寻觅,发现系统进行长度计算的收口为TypedValue中的applyDimension函数,传入单位与value将其计算为对应的px数值。

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;
}

基于以上几点,便有了以下方案。

3

方案 (注意划重点了

适配的目标是:完全按照设计图上标注的尺寸来编写页面,所编写的页面在所有大小与分辨率的屏幕上都表现一致,即控件在所有屏幕上相对于整个屏幕的相对大小都一致(看起来只是将设计图缩放至屏幕大小)。

 UI给我们提供的设计图是这样的

img

 创建什么样的预览使用的设备以设计图为准

img

- 怎么创建那个750设计稿分辨率的设备呐?看图,知道的同学请跳过

img

这样绘制出来的页面就跟设计图几乎完全一样,无论大小屏上看起来就只是将设计图缩放之后的结果。

适配前:

img

适配后:

img

ps:引用自新浪微博 布隆 博客,感谢辛勤的开创者

再次感谢辛勤的各位开发者