300X300下
1px
600X600下
2px
1200X1200下
3px
所以这个就是方案1 ,附上文章链接。
Android 屏幕适配方案 我们可以看下面的图:
我们可以看到列举了所有可能的屏幕分辨率的values,然后手动按照倍数,进行相应的赋值。当然这些文件不可能手写,通过Java自动生成相应的文件:
这样最终影响结果的就只是分辨率的了,分辨率越大的,x1的值越大。
但是这个方案有一个致命的缺陷,那就是需要精准命中才能适配,比如1920x1080的手机就一定要找到1920x1080的限定符,否则就只能用统一的默认的dimens文件了。而使用默认的尺寸的话,UI就很可能变形,简单说,就是容错机制很差。
2.2 生成values -sw 文件夹
可以参考:
骚年你的屏幕适配方式该升级了!-smallestWidth 限定符适配方案
其实这个方式跟上面的2.1方法原理可以说一模一样。唯一的区别就是使用了sw来保证一定的容错性。
我们看到其实就是把上面具体的分辨率values改成了values - sw而已。
2.3 百分比布局库
Android 百分比布局库(percent-support-lib) 解析与扩展 Android 增强版百分比布局库 为了适配而扩展
其实这个也是很简单的,字面意思,我写了这个Button宽度为父布局的百分之50,则在不同手机上,都是占据了百分之50。使用过过百分比布局的人都应该知道,我们写的时候是这么写的:
<android.support.percent. PercentRelativeLayout 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”>
其实原理很简单,就是动态计算实际的百分之50在不同机器的时候到底占了多少px,2.1,2.2则是等于提前帮我们计算好了具体的px,然后写在了文件里面,然后我们去读数据。
那它的实现原理是什么呢?简单来说就是二步:
- 获取用户到底填了多少的百分比数值
- 获取父布局的空间,然后乘以用户填的百分比数值,或者一个新数值,然后赋值给该控件。
我们一步步来看源码:
2.3.1 获取用户到底填了多少的百分比数值:
我们知道我们的百分比布局中的核心属性是子控件填写:
app:layout_heightPercent=“20%”
app:layout_widthPercent=“30%”
所以我们需要在PercentRelativeLayout中遍历它下面的子控件,然后分别获取每个子控件的百分比数值。 其实很简单,写过自定义View的人应该都知道,因为这个其实就是自定义属性而已。
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.PercentLayout_Layout); float value = array.getFraction(R.styleable.PercentLayout_Layout_layout_widthPercent, 1, 1,-1f);
2.3.2 获取计算后的值并且赋值:
因为要动态获取父控件的控件,同时把新的值赋值给子控件,所以该行为在onMeasure
方法中执行。
//传入的ViewGroup.LayoutParams params是遍历的每个子View的LayoutParams public void fillLayoutParams(ViewGroup.LayoutParams params, int widthHint, int heightHint) { // Preserve the original layout params, so we can restore them after the measure step. mPreservedParams.width = params.width; mPreservedParams.height = params.height; if (widthPercent >= 0) { params.width = (int) (widthHint * widthPercent); } if (heightPercent >= 0) { params.height = (int) (heightHint * heightPercent); } if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, “after fillLayoutParams: (” + params.width + ", " + params.height + “)”); } }
当然具体源码会更多,我不会大篇幅完整讲流程,更多的是讲解思路。
2.4 AutoLayout
Android AutoLayout全新的适配方式 堪称适配终结者
使用方式很简单:
- 注册设计图尺寸
将autolayout引入
dependencies { compile project(‘:autolayout’) }
在你的项目的AndroidManifest中注明你的设计稿
的尺寸。
- Activity中开启设配 让你的Activity去继承
AutoLayoutActivity
我们想到的原理,肯定也是把填在AndroidManifest.xml里面的数值读取出来,然后作为参考值。然后在不同手机上动态的计算出来数值,是不是感觉和百分比布局有点相似。
我们来看下AutoLayoutActivity源码:
public class AutoLayoutActivity extends AppCompatActivity { private static final String LAYOUT_LINEARLAYOUT = “LinearLayout”; private static final String LAYOUT_FRAMELAYOUT = “FrameLayout”; private static final String LAYOUT_RELATIVELAYOUT = “RelativeLayout”; @Override public View onCreateView(String name, Context context, AttributeSet attrs) { View view = null; if (name.equals(LAYOUT_FRAMELAYOUT)) { view = new AutoFrameLayout(context, attrs); } if (name.equals(LAYOUT_LINEARLAYOUT)) { view = new AutoLinearLayout(context, attrs); } if (name.equals(LAYOUT_RELATIVELAYOUT)) { view = new AutoRelativeLayout(context, attrs); } if (view != null) return view; return super.onCreateView(name, context, attrs); } }
我们发现把我们写在Layout.xml里面的布局控件替换成AutoXXXX等自定义控件。那我们以AutoLinearLayout来分析:其实看过百分比布局的源码,就会发现基本架构都一样,所以百分比布局的代码看得懂,再去看AutoLayout相关代码会很快。
2.5 动态更改density
- 假如设计图是按1920px * 1080px来设计,以density为3来标注,也就是屏幕其实是640dp * 360dp。这时候如果我们的Button想要占据一半,是不是宽度需要设置成180dp。
- 那假如我们的手机屏幕是1280X 720,density是2 ,则宽度是360dp,的确当设置成180dp的时候也正好占据一半。