android ui适配方案,android UI适配简单记录三

作为一个开发人员,屁股决定脑袋,偶尔需要换位思考,站在UI设计人员的角度考虑下,想想UI设计是怎么来的。

Material是一个适应性指南,组件和工具系统,支持用户界面设计的最佳实践。在开源代码的支持下,Material简化了设计人员和开发人员之间的协作,并帮助团队快速构建精美的产品。

Material上的示例标识的单位是dp,但是现实中可能你拿到的图片标识单位还是px。

39dd0adfddc8

例如下图这种图。

39dd0adfddc8

想象一下,如何画一张这样简单的界面的图并标识尺寸。

打开电脑自带画图软件,新建一个400x400像素大小的文件(随便画画),单击查看,勾选标尺和状态栏,网格线。

39dd0adfddc8

image.png

这里只是简单画一画,并不是很精准。但是在画图的过程中加深了对px以及ui设计的了解。专业的画图工具功能会更全,但是一般都收费。

39dd0adfddc8

首先,这张图上的单位都是px,因为图片设计基本单位是px,要如何把px换成dp呢?

39dd0adfddc8

image.png

以下部分出处:

安卓UI图px标注适配攻略:批量转化px为dp

https://blog.youkuaiyun.com/zengd0/article/details/52464627

px转dp的公式:dp = px/density

density是设备密度,有了设备密度,我们才可以将px转为dp。

这时候你可能会想,Android系统不是提供了api供我们转换吗,或者Android系统获取设备密度:context.getResources().getDisplayMetrics().density,然后将UI图的px去除以desity?

非也。density值是获取了,但是请问UI图上的px值是按照你的手机来标注的吗?如果UI图是以iPhone6手机(4.7寸屏幕,分辨率1334*750)为基准进行设计的,那么你用这个px值去除以你自己安卓手机的设备密度,怎么可能对。

也就是说,我们要获取UI图的设备密度(density)。

这里说的设备密度是指density 。

计算公式:density = PPI/160。

ppi计算公式如下图。

39dd0adfddc8

image.png

由于示例图片在设计的时候是适配640 * 1136机型的图,屏幕尺寸应该是4.0英寸(根据分辨率搜索所得)。因此ppi ≈ 326。

density = 326/160 = 2.0。

所以为640 * 1136机型设计的ui图中, 一个 宽度为 50 px的图形转换 dp : dp =50 px/2.0 = 25dp。

640 * 1136并不是主流机型,这里以市面上较为主流720 * 1280机型分辨率为例,简单看下如何适配分辨率720 * 1280的屏幕。

这里计算下720 * 1280 与640 * 1136的宽高比率。720/640 = 1.125 1280/1136 ≈ 1.127,屏幕分辨率比率几乎相等,就按1.125 去计算,进行缩放。50 px应该 乘以 1.125, 50 px * 1.125 = 56.25px。

640 x 1136中宽度为 50 px的图形在720 x1280 中对应的图形大小是56.25px。

而720 * 1280的屏幕,缩放因子density一般是2.0,因此

dp = 56.25px / 2.0 ≈ 28.13dp 。因此在控件里写28.13dp。

如果不能理解可以看下下面的例子。

打开window自带画图工具,新建一个200 x 200 像素大小的图,以中心为原点画一个宽度100px的正方形,中心坐标(100,100),左上角坐标(50,50),右下角坐标(150,150)。

39dd0adfddc8

image.png

然后重新调整大小至800 x 800 px,扩大4倍。

39dd0adfddc8

此时,正方形宽度变成了400px ,中心坐标(400,400),左上角坐标(200,200),右下角坐标(600,600)。随着图片大小放大,正方形大小也放大了。不同分辨率中,正方形的宽度不一致(可以把正方形想象成如TextView、Button之类的控件)。

39dd0adfddc8

image.png

在有su权限的设备上,执行命令,将屏幕分辨率调整至

adb shell wm size 200x200

由于这台设备带有底部虚拟键并且android默认带状态栏和工具栏,所以需要这里先隐藏下。

//因此状态栏和底部导航栏

public class MainActivity extends AppCompatActivity {

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

View decorView = getWindow().getDecorView();

int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION

| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_FULLSCREEN;

decorView.setSystemUiVisibility(uiOptions);

}

}

因此工具栏则需要修改manifest文件中,application节点下的 android:theme,修改结果如下所示。

android:theme="@style/Theme.AppCompat.Light.NoActionBar"

xml文件如所示。由于设备density为1.0,所以layout_width写100dp。

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical"

android:gravity="center">

android:layout_width="100dp"

android:layout_height="100dp"

android:text="test"

android:textSize="12sp"

android:gravity="center"

android:background="@color/colorPrimary"/>

运行结果如下所示。白色部分内为界面内,黑色部分为界外,黑色部分可忽略。

39dd0adfddc8

此时再将屏幕分辨率调到800x800

adb shell wm size 800x800

屏幕上会变成如下所示。

39dd0adfddc8

可以发现控件宽度为100px,要想使控件宽度为400px,此时就需要修改xml文件了。将layout_width和textSize都放大4倍。

android:layout_width="400dp"

android:layout_height="400dp"

android:text="test"

android:textSize="48sp"

android:gravity="center"

android:background="@color/colorPrimary"/>

运行结果如下所示

39dd0adfddc8

将截屏图片与设计图片简单对比,大小基本一致,控件的宽度达到了设计图的宽度为400px的效果。

39dd0adfddc8

这是比较极端的情况,仅用于举例。

但是其实刚刚将屏幕分辨率调到800x800后,要想使控件宽度为400px,除了修改xml文件,还有另一种修改方法:修改屏密度。

首先将layout_width和layout_height改回100dp,textSize改回12sp。

android:layout_width="100dp"

android:layout_height="100dp"

android:text="test"

android:textSize="12sp"

android:gravity="center"

android:background="@color/colorPrimary"/>

然后运行以下命令修改dpi。

//160*4 = 640 这是设置android中的Dpi 值

adb shell wm density 640

运行该命令可以修改屏幕密度。

此时缩放因子density = dpi/160 = 4。

又 px = dp * density

所以当layout_width为100dp时, 控件的实际物理大小为100dp*4 即 400px。

运行结果如下所示,与方法一结果一致。

39dd0adfddc8

这个例子很直观的显示出,UI受density和分辨率的影响。

我们先控制单一变量去思考适配ui。

先以分辨率为变量为例进行说明。

由于UI受屏幕分辨率影响,屏幕分辨率限定符法就出现了。这个方法我真的没有找到出处。

屏幕分辨率限定符法,即每种屏幕分辨率的设备需要定义一套 dimens.xml 文件。这种方法也有人称之为,百分比适配方法。

以某一分辨率为基准,生成所有分辨率对应像素数列表。

现在我们以200x200的分辨率为基准:

将屏幕的宽度分为200份,取值为x1~x200

将屏幕的高度分为200份,取值为y1~y200

在values目录下新建lay_x.xml和lay_y.xml文件。

简单来说,就是将 android:layout_width,android:layout_height, android:textSize等尺寸大小,按不同的分辨率,定义在不同的values下。

在android studio中新建MakeXml .java文件,根据MakeXml 生成xml文件。

代码如下。由于我手上屏幕为横屏,所以稍微修改了一点,以480x320为基准分辨率。

import java.io.File;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.PrintWriter;

public class MakeXml {

private final static String rootPath = "D:\\layoutroot\\values-{0}x{1}\\";

/* private final static float dw = 320f;

private final static float dh = 480f;*/

private final static float dw = 480f;

private final static float dh = 320f;

private final static String WTemplate = "{1}px\n";

private final static String HTemplate = "{1}px\n";

public static void main(String[] args) {

/* makeString(320, 480);

makeString(480, 800);

makeString(480, 854);

makeString(540, 960);

makeString(600, 1024);

makeString(720, 1184);

makeString(720, 1196);

makeString(720, 1280);

makeString(768, 1024);

makeString(800, 1280);

makeString(1080, 1812);

makeString(1080, 1920);

makeString(1440, 2560);*/

makeString(480, 320);

makeString(800, 480);

makeString(854, 480);

makeString(960, 540);

makeString(1024 ,600 );

makeString(1184 ,720 );

makeString(1196 ,720 );

makeString(1280 , 720);

makeString( 1024 ,768 );

makeString(1280 ,800 );

makeString( 1812 ,1080 );

makeString(1920 ,1080 );

makeString(2560 ,1440 );

}

public static void makeString(int w, int h) {

StringBuffer sb = new StringBuffer();

sb.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");

sb.append("");

float cellw = w / dw;

for (int i = 1; i < 480; i++) {

sb.append(WTemplate.replace("{0}", i + "").replace("{1}",

change(cellw * i) + ""));

}

sb.append(WTemplate.replace("{0}", "480").replace("{1}", w + ""));

sb.append("");

StringBuffer sb2 = new StringBuffer();

sb2.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");

sb2.append("");

float cellh = h / dh;

for (int i = 1; i < 320; i++) {

sb2.append(HTemplate.replace("{0}", i + "").replace("{1}",

change(cellh * i) + ""));

}

sb2.append(HTemplate.replace("{0}", "320").replace("{1}", h + ""));

sb2.append("");

String path = rootPath.replace("{0}", w + "").replace("{1}", h + "");

File rootFile = new File(path);

if (!rootFile.exists()) {

rootFile.mkdirs();

}

File layxFile = new File(path + "lay_x.xml");

File layyFile = new File(path + "lay_y.xml");

try {

PrintWriter pw = new PrintWriter(new FileOutputStream(layxFile));

pw.print(sb.toString());

pw.close();

pw = new PrintWriter(new FileOutputStream(layyFile));

pw.print(sb2.toString());

pw.close();

} catch (FileNotFoundException e) {

e.printStackTrace();

}

}

public static float change(float a) {

int temp = (int) (a * 100);

return temp / 100f;

}

}

选中java文件后右键,然后选择run 'MakeXml.main()'。

39dd0adfddc8

image.png

将生成的文件copy至src\main\res目录下。

39dd0adfddc8

image.png

39dd0adfddc8

image.png

又由于必须在默认values里面也创建对应默认lay_x.xml和lay_y.xml文件。

由于我这里以480x320为基准分辨率,因此将values-480x320下的lay_x.xml和lay_y.xml中的px先全部通过notepad++替换成dp,再放到values目录下。

39dd0adfddc8

39dd0adfddc8

image.png

在activity中增加测试textview控件大小的代码。

mTextView.post(new Runnable() {

@Override

public void run() {

int width = mTextView.getWidth();

int height = mTextView.getHeight();

Log.d(TAG,"width = " + width + " , height =" + height);

}

});

然后将TextView属性改为如下所示。

android:id="@+id/test_text_view"

android:layout_width="@dimen/x240"

android:layout_height="@dimen/y160"

android:background="@color/colorPrimary"

android:gravity="center"

android:text="test" />

运行程序后,不断通过wm size命令修改屏幕分辨率,并且运行程序。运行结果如下。

07-05 17:19:06.547 3859-3859/com.demo.myapplication D/MainActivity: screenWidth = 480 , screenHeight =320

07-05 17:19:06.641 3859-3859/com.demo.myapplication D/MainActivity: width = 240 , height =160

07-05 17:19:31.083 3859-3859/com.demo.myapplication D/MainActivity: screenWidth = 480 , screenHeight =800

07-05 17:19:31.132 3859-3859/com.demo.myapplication D/MainActivity: width = 240 , height =160

07-05 17:19:31.468 3859-3859/com.demo.myapplication D/MainActivity: screenWidth = 800 , screenHeight =480

07-05 17:19:31.517 3859-3859/com.demo.myapplication D/MainActivity: width = 240 , height =160

07-05 17:20:11.736 3859-3859/com.demo.myapplication D/MainActivity: screenWidth = 854 , screenHeight =480

07-05 17:20:11.782 3859-3859/com.demo.myapplication D/MainActivity: width = 240 , height =160

07-05 17:20:26.221 3859-3859/com.demo.myapplication D/MainActivity: screenWidth = 960 , screenHeight =540

07-05 17:20:26.259 3859-3859/com.demo.myapplication D/MainActivity: width = 427 , height =240

07-05 17:20:51.721 3859-3859/com.demo.myapplication D/MainActivity: screenWidth = 1024 , screenHeight =600

07-05 17:20:51.774 3859-3859/com.demo.myapplication D/MainActivity: width = 480 , height =270

07-05 17:21:23.098 3859-3859/com.demo.myapplication D/MainActivity: screenWidth = 1024 , screenHeight =768

07-05 17:21:23.138 3859-3859/com.demo.myapplication D/MainActivity: width = 512 , height =300

07-05 17:21:57.911 3859-3859/com.demo.myapplication D/MainActivity: screenWidth = 1184 , screenHeight =720

07-05 17:21:57.959 3859-3859/com.demo.myapplication D/MainActivity: width = 512 , height =300

07-05 17:22:36.078 3859-3859/com.demo.myapplication D/MainActivity: screenWidth = 1196 , screenHeight =720

07-05 17:22:36.128 3859-3859/com.demo.myapplication D/MainActivity: width = 512 , height =300

07-05 17:22:51.951 3859-3859/com.demo.myapplication D/MainActivity: screenWidth = 1280 , screenHeight =720

07-05 17:22:52.002 3859-3859/com.demo.myapplication D/MainActivity: width = 512 , height =300

07-05 17:22:59.092 3859-3859/com.demo.myapplication D/MainActivity: screenWidth = 1280 , screenHeight =800

07-05 17:22:59.142 3859-3859/com.demo.myapplication D/MainActivity: width = 640 , height =360

07-05 17:23:18.623 3859-3859/com.demo.myapplication D/MainActivity: screenWidth = 1812 , screenHeight =1080

07-05 17:23:18.678 3859-3859/com.demo.myapplication D/MainActivity: width = 640 , height =400

07-05 17:23:48.159 3859-3859/com.demo.myapplication D/MainActivity: screenWidth = 1920 , screenHeight =1080

07-05 17:23:48.200 3859-3859/com.demo.myapplication D/MainActivity: width = 640 , height =400

07-05 17:24:16.942 3859-3859/com.demo.myapplication D/MainActivity: screenWidth = 2560 , screenHeight =1440

07-05 17:24:16.997 3859-3859/com.demo.myapplication D/MainActivity: width = 960 , height =540

但是从运行结果上来看,效果并不理想。

screenWidth = 800 , screenHeight =480时, width = 240 , height =160。

但是我定义的values-800x480下。

values-800x480

lay_x.xml

400.0px

lay_y.xml

240.0px

按定义去工作,结果应该是 width = 400 , height =240。这里values-800x480并没有生效。

而且wm size 2560x1440时, width = 960 , height =540,匹配的是values-1920x1080下的dimen。

values-1920x1080

lay_x.xml

960.0px

lay_y.xml

540.0px

values-2560x1440

lay_x.xml

1280.0px

lay_y.xml

720.0px

分辨率限定符根本没有按我的想象去工作!!!

后来我找到了解释,一直以来其实都误用了分辨率限定符。

详细解释可以看这里。

被误用的屏幕分辨率限定符

https://www.jianshu.com/p/b0253e457031

这个方案后面基本上也没有人推荐了,基本上退出历史舞台了。

现在来看看以density为变量为例进行ui适配。这种方案最近比较火,由 字节跳动技术团队 提出。

https://mp.weixin.qq.com/s/d9QCoBP6kV9VSWvVldVVwA

可以参考这个链接,简单看看下效果。

Android今日头条UI适配完善版

https://www.jianshu.com/p/41930fde7aac

这个方案从竖屏测试结果上来看,效果还不错。不过横屏仍需要另外布局。

上面介绍了屏幕分辨率和density适配ui2种方法,其实还有一种写法,就是把TextView嵌套进LinearLayout然后通过android:layout_weight这个属性让其控件大小自适应。

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical">

android:layout_width="match_parent"

android:layout_height="0dp"

android:layout_weight="1" />

android:layout_width="match_parent"

android:layout_height="0dp"

android:layout_weight="2">

android:layout_width="0dp"

android:layout_height="match_parent"

android:layout_weight="1" />

android:layout_width="0dp"

android:layout_height="match_parent"

android:layout_weight="2">

android:layout_width="match_parent"

android:layout_height="match_parent"

android:background="@color/colorPrimary"

android:gravity="center"

android:text="test" />

android:layout_width="0dp"

android:layout_height="match_parent"

android:layout_weight="1" />

android:layout_width="match_parent"

android:layout_height="0dp"

android:layout_weight="1" />

200x200和800x800分辨率时运行结果分别如下图所示。

39dd0adfddc8

200x200

39dd0adfddc8

800x800

运行结果控件大小虽然效果一致,但是字体大小效果不一致,可以代码中动态调节,或者去定义 不同dimens.xml 文件。

先来看看通过代码去适配的做法。

大致思路是以200x200为基准,设置一个大小,例如12sp.

在values下新建一个dimens文件。

12sp

然后再获取屏幕分辨率,例如800x800,去计算放大或缩小比例,例如这里是倍数是4,通过setTextSize设置大小为48sp。

DisplayMetrics dm = new DisplayMetrics();

getWindowManager().getDefaultDisplay().getRealMetrics(dm);

int screenWidth = dm.widthPixels;

int screenHeight = dm.heightPixels;

Log.d(TAG,"screenWidth = " + screenWidth + " , screenHeight =" + screenHeight);

int dimen = getResources().getDimensionPixelSize(R.dimen.text_size);

if (screenWidth != 200){

dimen = dimen * screenWidth/200;

Log.d(TAG,"dimen = " + dimen);

}

mTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX,dimen);

运行结果如下,字体变大了。

39dd0adfddc8

看完代码中动态调节的方式,下面来看看通过定义不同dimens.xml 文件去适配的方式。

除了前面的 根据 屏幕分辨率限定符 定义 dimens,还可以用另一种方式定义dimens,那就是 android中的 sw(smallestWidth)限定符 (这个限定符android官网是有介绍的)。

下面来介绍下给 smallestWidth(最小宽度) 限定符方式定义dimens.xml 文件,这种方式定义dimens可以使apk体积更小。

先看看什么是smallestWidth。

android中定义了配置修饰符-sw。例如-sw600dp。

//以下部分出处:android编程权威指南

配置修饰符-sw600dp的作用是:如果设备尺寸大于某个指定值,就使用对应的资源文件。

sw是smallest width(最小宽度)的缩写。虽然字面上是宽度的含义,但它实际指的是屏幕最小尺寸(dimension),因而sw与设备的当前方向无关。

在确定可选资源时,-sw600dp配置修饰符表明:对任何最小尺寸为600dp或更高dp的设备,都使用该资源。

在res目录下新建values-sw800dp文件夹,再新建一个dimens文件。

39dd0adfddc8

image.png

48sp

在TextView中增加属性 android:textSize="@dimen/text_size",当屏幕分辨率为800x800时(这里是随便测试用的分辨率),android会自动适配values-sw800dp下的dimens文件。

android:id="@+id/test_text_view"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:background="@color/colorPrimary"

android:gravity="center"

android:text="test"

android:textSize="@dimen/text_size"/>

这种最后运行结果与通过代码去适配一致。

这种sw限定符 相对于 屏幕分辨率限定符 ,所需的dimens.xml文件更少,匹配度也更好一些。

因此这种sw限定符 的方法广泛使用。

但是上面的这种定义xml文件的方法,布局嵌套层级太深了,会增加渲染层次,致使性能下降。针对这种情况google为我们提供了一个百分比布局兼容库:Android Percent Support Library。

39dd0adfddc8

但是后面这个方法又被废弃了,推荐我们去使用ConstraintLayout 。

39dd0adfddc8

所以我们到底是为了什么一直在学习这种要被废弃的东西??我们一直在不停地使用轮子,然后再这个过程中无数的轮子都被抛弃了。如果只会用轮子我们还剩什么?

em。。还是要学会思想,原理,理论结合实践,转换成自己的东西。多写文章,好记性不如烂笔头。

下面来粗略看下谷歌提供的百分比库的简单使用。

首先在gradle中添加依赖。

implementation 'com.android.support:percent:28.0.0'

定义xml文件。

xmlns:app="http://schemas.android.com/apk/res-auto"

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

tools:context=".MainActivity">

android:layout_width="0dp"

android:layout_height="0dp"

android:id="@+id/one"

android:background="#f0f000"

app:layout_heightPercent="30%"

app:layout_widthPercent="70%"

android:text="Hello World!"

/>

android:layout_width="0dp"

android:layout_toRightOf="@id/one"

android:layout_height="0dp"

app:layout_heightPercent="30%"

app:layout_widthPercent="30%"

android:background="#ff0000"

android:text="Hello World!"

/>

android:layout_width="0dp"

android:layout_below="@id/one"

android:layout_height="0dp"

app:layout_heightPercent="70%"

app:layout_widthPercent="100%"

android:background="#ff00ff"

android:text="Hello World!"

/>

预览图如下。

39dd0adfddc8

在3台设备上运行结果如下。

39dd0adfddc8

1

39dd0adfddc8

2

39dd0adfddc8

3

在横竖屏中运行效果一致。看起来是比较理想的方法。官方推了一段时间这个,但是最后还是将其废弃,原因未知。因此随着android系统的更新,后续的使用会有问题。这个是别人在使用中遇到的一些问题。

关于使用百分比布局导致布局设定失效的记录

https://blog.youkuaiyun.com/wzgl708937822/article/details/80880492

废弃百分比布局兼容库后又推出了ConstraintLayout 。到今天(2019.7.8)为止使用android studio新建project都会默认生成以ConstraintLayout 为根节点的xml文件。

思考:上面写了多种使用方法,那么到底什么时候该用什么方法呢?各自的使用场景最佳使用?

先不管了,看看ConstraintLayout (约束布局)再说。

ConstraintLayout 目前为止并没有完全代替LinearLayout 、 RelatvieLayout等,并且学习成本较高,我经历过入门到放弃的过程。

而且属性特别多,很容易迷失在一堆资料中,思绪乱掉。应对这种情况我的解决办法是找简单的demo去练习(越简单的demo越好,太复杂真的不容易入门,容易劝退的,这篇文章入门我觉得还可以。哲♂学三幻神带你学习ConstraintLayout(约束布局) https://www.jianshu.com/p/639fa7377cc0),然后再自己写一遍,再对照官方文档查属性。

//从写这篇文开始到写到这里其实已经过了一周多了虽然字不多但是真的很难憋出来

39dd0adfddc8

这里可以先通过使用ConstraintLayout 代替代替常见布局LinearLayout 、 RelatvieLayout 、 PercentLayout等,来简单对比他们之间的差异。

先使用LinearLayout 、 RelatvieLayout实现如下两种经典布局。

39dd0adfddc8

image.png

首先使用LinearLayout 。

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="horizontal"

tools:context=".MainActivity">

android:layout_width="0dp"

android:layout_height="match_parent"

android:layout_weight="1"

android:text="1"

android:gravity="center"

android:textSize="30sp"

android:background="#f0f000"/>

android:layout_width="0dp"

android:layout_height="match_parent"

android:layout_weight="2"

android:text="2"

android:gravity="center"

android:textSize="30sp"

android:background="#ff0000"/>

android:layout_width="0dp"

android:layout_height="match_parent"

android:layout_weight="1"

android:text="3"

android:gravity="center"

android:textSize="30sp"

android:background="#ff00ff"/>

39dd0adfddc8

image.png

这个在一个横屏和2个竖屏设备上显示效果基本一致。

然后再来看RelatvieLayout。

下面的xml是针对我手中分辨率为1080x1920,density为3的设备去写的。

但是在分辨率为 720x1280,density为2的时候显示效果也基本一致。

但是在横屏上这个xml显示效果就不太行了。

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

tools:context=".MainActivity">

android:id="@+id/text_view_1"

android:layout_width="match_parent"

android:layout_height="500dp"

android:text="1"

android:gravity="center"

android:textSize="30sp"

android:background="#f0f000"/>

android:id="@+id/text_view_2"

android:layout_width="240dp"

android:layout_height="140dp"

android:layout_below="@id/text_view_1"

android:text="2"

android:gravity="center"

android:textSize="30sp"

android:background="#ff0000"/>

android:id="@+id/text_view_3"

android:layout_width="120dp"

android:layout_height="140dp"

android:layout_below="@id/text_view_1"

android:layout_toEndOf="@id/text_view_2"

android:text="3"

android:gravity="center"

android:textSize="30sp"

android:background="#ff00ff"/>

运行结果如下。

39dd0adfddc8

竖屏

39dd0adfddc8

横屏

PercentLayout这里就不用看了,前文有写。现在就来看ConstraintLayout 要怎么去写这2种布局。

先看LinearLayout 。

首先在根目录下写上ConstraintLayout,然后切到design界面。

选中TextView控件,拖到3个TextView下面的区域区中去。

39dd0adfddc8

39dd0adfddc8

image.png

添加2条Guideline。

39dd0adfddc8

image.png

选中Guideline,可以直接设置layout_constraintGuide_percent。

39dd0adfddc8

填0.25就是25%的位置。

39dd0adfddc8

image.png

或者可以选中Guideline,点击Cycle Guideline,切到百分比。

39dd0adfddc8

image.png

39dd0adfddc8

image.png

然后分别手动拖到25%和75%的地方。

39dd0adfddc8

然后把最左边的TextView控件的右边连到25%那条Guideline,最右边的TextView控件的左边连到75%那条Guideline,中间的TextView控件左右分别连到25%和75%的Guideline,其余部分连离各自最近的边框。

39dd0adfddc8

image.png

然后再设置每个TextView控件大小以及边距。修改箭头所示部分。

39dd0adfddc8

image.png

修改后如下。

39dd0adfddc8

image.png

然后每个都这样改,最后为了更好区分,给TextView加上背景色并且调大字体,并且把字改成123。

最终xml文件如下所示。

xmlns:app="http://schemas.android.com/apk/res-auto"

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

tools:context=".MainActivity">

android:id="@+id/textView"

android:layout_width="0dp"

android:layout_height="0dp"

android:background="#f0f000"

android:text="1"

android:textSize="30sp"

android:gravity="center"

app:layout_constraintBottom_toBottomOf="parent"

app:layout_constraintEnd_toStartOf="@+id/guideline"

app:layout_constraintStart_toStartOf="parent"

app:layout_constraintTop_toTopOf="parent" />

android:id="@+id/textView2"

android:layout_width="0dp"

android:layout_height="0dp"

android:background="#ff0000"

android:text="2"

android:textSize="30sp"

android:gravity="center"

app:layout_constraintBottom_toBottomOf="parent"

app:layout_constraintEnd_toStartOf="@+id/guideline2"

app:layout_constraintHorizontal_bias="0.0"

app:layout_constraintStart_toStartOf="@+id/guideline"

app:layout_constraintTop_toTopOf="parent" />

android:id="@+id/textView3"

android:layout_width="0dp"

android:layout_height="0dp"

android:background="#ff00ff"

android:text="3"

android:textSize="30sp"

android:gravity="center"

app:layout_constraintBottom_toBottomOf="parent"

app:layout_constraintEnd_toEndOf="parent"

app:layout_constraintStart_toStartOf="@+id/guideline2"

app:layout_constraintTop_toTopOf="parent" />

android:id="@+id/guideline"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:orientation="vertical"

app:layout_constraintGuide_percent="0.25" />

android:id="@+id/guideline2"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:orientation="vertical"

app:layout_constraintGuide_percent="0.75" />

在3台设备上运行结果如下所示。

39dd0adfddc8

1

39dd0adfddc8

2

39dd0adfddc8

3

这个布局与LinearLayout 相比,写的过程中没感觉到有什么优势,可能胜在性能吧。

为了减少代码量,一般这种统一风格的属性,可以通过定义一个style,让TextView等控件去引用就好。

在values下的styles.xml文件中,定义如下style。

center

30sp

然后再在TextView中加上一句

style="@style/style_main_text"

再来看RelativeLayout 。

新建一个horizontal方向的Guideline,设置百分比为0.78125(500/640),一个vertical方向的Guideline,设置百分比为667(240/360),再拖3个Textview,并且将其与Guideline连接起来。

最后xml文件如下。

xmlns:app="http://schemas.android.com/apk/res-auto"

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

tools:context=".MainActivity">

android:id="@+id/textView1"

android:layout_width="0dp"

android:layout_height="0dp"

android:background="#f0f000"

android:text="1"

android:textSize="30sp"

android:gravity="center"

app:layout_constraintBottom_toTopOf="@+id/guideline4"

app:layout_constraintEnd_toEndOf="parent"

app:layout_constraintStart_toStartOf="parent"

app:layout_constraintTop_toTopOf="parent" />

android:id="@+id/textView2"

android:layout_width="0dp"

android:layout_height="0dp"

android:background="#ff0000"

android:text="2"

android:textSize="30sp"

android:gravity="center"

app:layout_constraintBottom_toBottomOf="parent"

app:layout_constraintEnd_toStartOf="@+id/guideline11"

app:layout_constraintStart_toStartOf="parent"

app:layout_constraintTop_toTopOf="@+id/guideline4" />

android:id="@+id/textView3"

android:layout_width="0dp"

android:layout_height="0dp"

android:background="#ff00ff"

android:text="3"

android:textSize="30sp"

android:gravity="center"

app:layout_constraintBottom_toBottomOf="parent"

app:layout_constraintEnd_toEndOf="parent"

app:layout_constraintStart_toStartOf="@+id/guideline11"

app:layout_constraintTop_toTopOf="@+id/guideline4" />

android:id="@+id/guideline4"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:orientation="horizontal"

app:layout_constraintGuide_percent="0.78125" />

android:id="@+id/guideline11"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:orientation="vertical"

app:layout_constraintGuide_percent="0.6667" />

从运行结果上来看,横竖屏效果基本一致,效果比RelativeLayout 要好。

由此可见,ConstraintLayout使用场景上来说应该更适用于复杂布局,用来代替RelativeLayout 效果还不错。

总结:ConstraintLayout+sw限定符方式应该是不错的ui适配组合。

以上只是个人分析,具体情况具体操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值