转:http://blog.csdn.net/ljh102/article/details/45536293
2015.8.4 更新:
增加参数custom:autoScaleType 设置缩放模式,可以设为“fitWidth”,"fitHeigth" 和 "fitInside"。分别代表缩放至宽度匹配,缩放至高度匹配以及缩放至适合容器内部,默认为"fitInside"。
做过安卓开发的都知道,屏幕适配是一件非常困难的事情。
Google官方的解决方案:screens_support 需要写多个layout文件以及dimens.xml,工作量大不说,维护也麻烦。
其实很多时候我们的需求很简单,就是要求不同的屏幕看上去效果一样就可以了。这样就需要我们布局的时候采用百分比来定位。
说到百分比,我们第一时间想到的是layout_weight,但是layout_weight实际使用效果并不是很好,特别是一些复杂情况下需要层层嵌套。也无法解决所有问题,比如文字大小。
我想到的解决方案是根据屏幕大小重新对布局以及布局内部对象的大小进行调整。之前做过的一些项目里面的自定义view也用过这种方法。
我在网上也搜到了一些相关资料,比如 Vanteon Electronic Design。说明这种方法是可行的。剩下的问题就是怎么把这种方式封装成一个通用的解决方案,能以最简便的方式融入到开发中来。
经过一番实验,我初步开发出来了AutoScalingLayout
源码:https://github.com/Junhua102/AutoScalingLayout
实现原理:
原理类似我们用播放器看视频的时候,无论怎么调整窗口大小,播放器都可以自动调整视频大小适合窗口大小。因为视频有一个原始分辨率,播放器会根据窗口实际大小对视频进行缩放。
我们写布局的时候一般是根据某个基准分辨率来(比如UI给的原型图),自动缩放布局的作用就是将这个基准布局乘以一个缩放比例,达到适配所有分辨率的目的。
计算缩放比例公式: 实际大小 / 设计大小 = 缩放比例
只需要给定一个设计大小,就可以计算出缩放比例,然后将布局内部所有元素的尺寸都乘以这个缩放比例,就可以适配实际屏幕了。
使用方法:
studio用户使用release/AutoScalingLayout.aar
eclipse用户使用release/AutoScalingLayout.jar,并将attr.xml复制到value目录
替换布局:
只需要替换需要缩放的根布局即可,内部子布局会自动缩放
原布局 | 自动缩放布局 |
---|---|
RelativeLayout | ASRelativeLayout |
LinearLayout | ASLinearLayout |
FrameLayout | ASFrameLayout |
目前只支持以上3种布局
添加属性:
[html] view plain copy
- xmlns:custom="http://schemas.android.com/apk/res-auto"
- custom:designWidth="384dp"
- custom:designHeight="575dp"
- custom:autoScaleEnable="true"
- custom:autoScaleType="fitInside"
designWidth和designHeight就是你在可视化编辑xml时使用的屏幕大小。比如我使用的是Nexus 4,屏幕尺换算成dp就是384dp和575dp(减去状态栏和操作栏)
autoScaleEnable 用来开启和关闭自动缩放,默认开启
autoScaleType 设置缩放模式,可以设为“fitWidth”,"fitHeigth" 和 "fitInside"。分别代表缩放至宽度匹配,缩放至高度匹配以及缩放至适合容器内部,默认为"fitInside"。
注意事项:
1.designWidth和designHeight非常重要,千万不要填错,否则缩放出来就不是你想要的效果了。
2.如果designWidth和designHeight的单位是dp,那么所有内部子view的单位都必须是dp,不能写px、pt等其他单位。文字大小也不能用sp。如果你想无脑照抄UI给出的像素值,就全部单位用px就可以了。
3.AutoScalingLayout缩放时会保持deginWidth和designHeight的纵横比,不用担心正方形变矩形。
以sample中的 activity_login_dp.xml 为例
[html] view plain copy
- <me.dreamheart.autoscalinglayout.ASRelativeLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- xmlns:custom="http://schemas.android.com/apk/res-auto"
- custom:designWidth="384dp"
- custom:designHeight="575dp"
- custom:autoScaleEnable="true"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- tools:context=".LoginActivity"
- android:background="@drawable/login_bg"
- >
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="60dp"
- android:text="Title"
- android:textSize="30dp"
- android:textColor="#fff"
- android:layout_centerHorizontal="true"
- />
- <View android:id="@+id/login_input_form"
- android:layout_width="270dp"
- android:layout_height="100dp"
- android:layout_marginTop="125dp"
- android:layout_centerHorizontal="true"
- android:background="@drawable/login_input_form"
- />
- <TextView android:id="@+id/user_name_tv"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="140dp"
- android:layout_marginLeft="16dp"
- android:layout_alignLeft="@+id/login_input_form"
- android:text="@string/user_name"
- android:textSize="15dp"
- android:textColor="#666"
- />
- <TextView android:id="@+id/password_tv"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="190dp"
- android:layout_alignLeft="@+id/user_name_tv"
- android:text="@string/password"
- android:textSize="15dp"
- android:textColor="#666"
- />
- <EditText android:id="@+id/user_name"
- android:layout_toRightOf="@+id/user_name_tv"
- android:layout_marginLeft="10dp"
- android:layout_alignBaseline="@+id/user_name_tv"
- android:layout_height="wrap_content"
- android:layout_width="190dp"
- android:textSize="15dp"
- android:textColor="#444"
- android:hint="@string/prompt_name"
- android:inputType="text"
- android:maxLines="1"
- android:singleLine="true" />
- <EditText android:id="@+id/password"
- android:layout_toRightOf="@+id/user_name_tv"
- android:layout_marginLeft="10dp"
- android:layout_alignBaseline="@+id/password_tv"
- android:layout_height="wrap_content"
- android:layout_width="190dp"
- android:textSize="15dp"
- android:textColor="#444"
- android:hint="@string/prompt_password"
- android:inputType="textPassword"
- android:maxLines="1" android:singleLine="true" />
- <Button android:id="@+id/email_sign_in_button"
- android:background="@drawable/login_btn_selector"
- android:layout_marginTop="260dp"
- android:layout_centerHorizontal="true"
- android:layout_width="270dp"
- android:layout_height="40dp"
- android:text="@string/action_sign_in"
- android:textSize="20dp"
- android:textColor="#444"
- android:textStyle="bold" />
- </me.dreamheart.autoscalinglayout.ASRelativeLayout>
未使用AutoScalingLayout
使用AutoScalingLayout