概述

Android 开发中面对这么多机型,这么多大小不一的手机屏幕,需要寻求一种高效的多屏适配方案,本文只针对不支持转屏的应用。

问题

一般来说应用的适配可分一下几个内容:

  1. 系统组件(Actionbar,Dialog, Pupupmenu…)
  2. 控件块区(View 的大小,间距)
  3. 图文相关(文字大小,图片)

方案

  1. 系统组件:使用相关 Compat 库+自定义 View 的方式
  2. 控件块区:控件的位置大小,使用 dp + 百分比缩放的方式
  3. 图文相关:文子大小使用 sp,或者根据需要使用百分比缩放

适配细节

一、Android 原生 dp

二、百分比缩放

已知库

  1. android-percent-support-lib
    宽高只能和父容器的宽高对应比例。

  2. android-percent-support-lib-
    基于上面扩展,实现可以分别选择占父容器的比例。

然而对于这样的在布局文件中直接定义百分比的方式,存在两大问题

  1. 计算麻烦
    视觉给你标注图肯定都是标的真实的长度,百分比还得自己计算。
  2. 精度丢失
    如果效果图的父容器宽是 1080px,子 View 的宽是 38px,占 3.3333~%,1080 * 3% = 32;1080 * 3.3% = 35 无论取什么值,连视觉的设计样本都会偏移像素。

最终方案

  1. 上下滑动的界面按屏幕宽等比缩放
  2. 左右滑动的界面按屏幕高等比缩放
以上下滑动为例
1
2
3
4
5
float percent = mScreenWidth / designScreenWidth // 屏幕比
float designDP = getPixelSize() / mDensity // designDP是写入在xml文件中的,需要通过getPixel还原出来
float designPixel = designDP * designDensity // dp 转 pixel
float realPixel = percent * designPixel
float realPixel = (mScreenWidth * designDensity * getPixelSize()) / (designScreenWidth * mDensity)

基于最终方案的 ScaleLayout 实现

Github:Android-ScaleLayout

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<cn.gavinliu.android.lib.scale.ScaleRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_design_density="@integer/app_design_density"
app:layout_design_height="@dimen/app_design_height"
app:layout_design_width="@dimen/app_design_width">

<TextView
android:id="@+id/view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#46b34b"
android:text="@string/hello_world"
app:layout_height="120dp"
app:layout_marginLeft="12dp"
app:layout_marginTop="8dp"
app:layout_scale_by="width"
app:layout_width="166dp" />

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/view"
android:background="#46b34b"
android:text="@string/hello_world"
app:layout_height="120dp"
app:layout_marginLeft="4dp"
app:layout_marginTop="8dp"
app:layout_paddingLeft="12dp"
app:layout_paddingTop="12dp"
app:layout_scale_by="width"
app:layout_width="166dp" />

</cn.gavinliu.android.lib.scale.ScaleRelativeLayout>