Android 一个全适配方案

来源:互联网 发布:linux如何进行源码安装 编辑:程序博客网 时间:2024/04/30 01:08

简介

其实Android 适配方案已经是老生常谈的事了,博主之前也深受其扰,常常羡慕做iOS的同学们不用在乎适配问题,直接使用绝对布局。随手查了一下umeng给出的分辨率分部情况,详细地地址点我,有兴趣的同学可以去看看,我也为懒得过去的同学贴一个截图吧。


有这么多的屏幕分辨率,适配也是一大难题,想必各位也想过很多相关的适配方案了吧,那么我也在这分享一套个人目前写出来觉得效果比较好的方案吧。

优点:

1.便于使用绝对布局
2.针对当前屏幕,自动适配
3.在使用绝对布局同时,可以减少onMeasure调用次数,优化UI
4.方便易用

缺点:

1.需要注入到View内部

那么列举一下我们需要了解的方面吧

dp 、 px 、 density
View 绘制流程
我们常常拿到的UI图是怎么样的
我们从什么地方着手去解决这个问题


1. dp、px、density

首先简单介绍下这些的概念

dp :

为了进一步简化适配工作,Android为我们提供了一个虚拟的像素单位 DP 或者 DIP (Density-Independent pixel),当然也可以理解为 Device-Independent Pixel。为什么说是虚拟呢,因为它的大小不是一个物理(Phisical)值,而是由操作系统根据屏幕大小和密度动态渲染出来的。

px :

pixels(像素) 屏幕上的点,不同设备不同的显示屏显示效果相同,这是绝对像素,是多少就永远是多少不会改变。

density :

简单的描述就是一个点 有几个像素。

其实这些这里就是要了解一个关键公式

px=dpdensity+0.5f

2.为什么要做这个方案

因为我们一般拿到的设计图是这样的

咋们的设计师一般就给个 这是1920 * 1080的,就这样了。
是不是觉得有些无助,这是什么鬼,我要布局可不是这样的,Android 那么多分辨率,会变形的呢。当然,有大神会考虑自己去绘制,但是我这里也就说一个点,团队中不是每个人都有那种能力,考虑到时间成本,又去看了看文档,写了这么一个小工具。

3.如何全适配

其实如何全适配,网上一找一大堆,但是要么出现了自定义属性,要不就反馈不是太好,当然还有另一种简单粗暴的方案,就是针对基本上所有的分辨率,生成一个对应的dimen放在对应的文件夹下面。
多么美好的方案,直到有一天用户反馈说他的设备适配有问题!!我觉得这么完美的方案,不支持的已定是奇怪的手机,直到有一天,我买了一个nexus 6 来做测试设备的时候

就是这个设备,我尝试了各种dimen 他也找不到对应的值 O.O,那么问题来了,是不是只有这一个设备是这样的?还有其他什么设备么?我没法一个个去尝试并且要求用户反馈。

那么进入正题

原理:

在应用启动前,我们要拿到当前屏幕的分辨率,以及density,这样就可以把需要显示的屏幕转换为一个假想的UI(即设计师给出的UI图),这样就可以跟设计给我们的UI图做等比转换。

那么我们将焦点关注到

protected void onFinishInflate() {}

这个函数是在讲View从XML加载完成后调用,在

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));    }

之前,并且已经可以获得其中子View的参数(注意这里是子View,包含在其内部的View)
因此,我们可以在这段时间对之前在xml中设置的单位进行换算了。

4.如何使用

在Application 中初始化工具,调用函数:

 //初始化,UI设计图模板为1280 * 720 的设计图 density 最好为 1,便于在XML中写适配以及测试 AutoUtils.init(context, 1280, 720, 1);
那我们就来看看这个有什么好用的地方吧

假如我们拿到了这么一个设计图(请忽略掉我只是简单的画了下框,实际设计图比这复杂得多)

首先这个Util 中包含

AutoScaleFrameLayout —> FrameLayout
AutoScaleLinearLayout —> LinearLayout
AutoScaleRelativeLayout —> RelativeLayout

在布局文件中,我们可以先这样写:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical">    <FrameLayout        android:layout_width="640px"        android:layout_height="360px">        <FrameLayout            android:layout_width="320px"            android:background="#aa0040"            android:layout_height="360px">        </FrameLayout>        <View            android:layout_gravity="end"            android:layout_width="160px"            android:background="#af80f1"            android:layout_height="180px"/>        <View            android:layout_gravity="end"            android:layout_marginTop="180px"            android:layout_width="160px"            android:background="#f1a061"            android:layout_height="180px"/>        <View            android:layout_marginLeft="320px"            android:layout_width="160px"            android:background="#0f80f1"            android:layout_height="180px"/>        <View            android:layout_marginLeft="320px"            android:layout_width="160px"            android:layout_marginTop="180px"            android:background="#4ff0f1"            android:layout_height="180px"/>    </FrameLayout>    <FrameLayout        android:layout_width="match_parent"        android:layout_height="360px">        <TextView            android:layout_width="880px"            android:layout_height="120px"            android:text="@string/t1"            android:textSize="30px" />        <TextView            android:layout_width="match_parent"            android:layout_height="120px"            android:layout_marginTop="120px"            android:gravity="center"            android:text="@string/t2"            android:textSize="33px" />    </FrameLayout></LinearLayout>

接下来我们就可以使用Preview来预览了,用一个图,直接来说明吧

这就是我所需要的界面啦,并且所有设备上,都会这么显示,当然这仅仅是预览。接下来做件事:
1.把上面所有我xxxxLayout换成工具中的AutoScaleXXXXXLayout。
2.把所有的 px 换成 dp
改完后是这样的:

<?xml version="1.0" encoding="utf-8"?><com.ly2251.autoscaleviewui.autoviewutils.AutoScaleLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical">    <com.ly2251.autoscaleviewui.autoviewutils.AutoScaleFrameLayout        android:layout_width="640dp"        android:layout_height="360dp">        <com.ly2251.autoscaleviewui.autoviewutils.AutoScaleFrameLayout            android:layout_width="320dp"            android:background="#aa0040"            android:layout_height="360dp">        </com.ly2251.autoscaleviewui.autoviewutils.AutoScaleFrameLayout>        <View            android:layout_gravity="end"            android:layout_width="160dp"            android:background="#af80f1"            android:layout_height="180dp"/>        <View            android:layout_gravity="end"            android:layout_marginTop="180dp"            android:layout_width="160dp"            android:background="#f1a061"            android:layout_height="180dp"/>        <View            android:layout_marginLeft="320dp"            android:layout_width="160dp"            android:background="#0f80f1"            android:layout_height="180dp"/>        <View            android:layout_marginLeft="320dp"            android:layout_width="160dp"            android:layout_marginTop="180dp"            android:background="#4ff0f1"            android:layout_height="180dp"/>    </com.ly2251.autoscaleviewui.autoviewutils.AutoScaleFrameLayout>    <com.ly2251.autoscaleviewui.autoviewutils.AutoScaleFrameLayout        android:layout_width="match_parent"        android:layout_height="360dp">        <TextView            android:layout_width="880dp"            android:layout_height="120dp"            android:text="@string/t1"            android:textSize="30dp" />        <TextView            android:layout_width="match_parent"            android:layout_height="120dp"            android:layout_marginTop="120dp"            android:gravity="center"            android:text="@string/t2"            android:textSize="33dp" />    </com.ly2251.autoscaleviewui.autoviewutils.AutoScaleFrameLayout></com.ly2251.autoscaleviewui.autoviewutils.AutoScaleLinearLayout>

然后编译,完事大吉,是不是不用再去纠结这怎么就少了几个像素,完美的处女座杀手。

最后附上Demo地址:https://github.com/ly2251/AutoScaleView
此工具还有不是很完善的地方,也欢迎大家提出遇到的问题。

2 0
原创粉丝点击