0
点赞
收藏
分享

微信扫一扫

Android屏幕适配方案,内含福利

中间件小哥 2022-01-20 阅读 140

一句话,总结下,dp能够让同一数值在不同的分辨率展示出大致相同的尺寸大小。但是当设备的尺寸差异较大的时候,就无能为力了。适配的问题还需要我们自己去做,于是我们可能会这么做:

<?xml version="1.0" encoding="utf-8"?>

<resources>

<dimen name=“imagewidth”>120dip</dimen>

</resources>

<resources>

<dimen name=“imagewidth”>220dip</dimen>

</resources>

<?xml version="1.0" encoding="utf-8"?>

<resources>

<dimen name=“imagewidth”>80dip</dimen>

</resources>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

可以看出,dp并没有能解决适配问题。下面看百分比。

  • 百分比

这个概念不用说了,web中支持控件的宽度可以去参考父控件的宽度去设置百分比,最外层控件的宽度参考屏幕尺寸设置百分比,那么其实中Android设备中,只需要支持控件能够参考屏幕的百分比去计算宽高就足够了。

比如,我现在以下几个需求:

  • 对于图片展示的Banner,为了起到该有的效果,我希望在任何手机上显示的高度为屏幕高度的1/4

  • 我的首页分上下两栏,我希望每个栏目的屏幕高度为11/24,中间间隔为1/12

  • slidingmenu的宽度为屏幕宽度的80%

当然了这仅仅是从一个大的层面上来说,其实小范围布局,可能百分比将会更加有用。

那么现在不支持百分比,实现上述的需求,可能需要1、代码去动态计算(很多人直接pass了,太麻烦);2、利用weight(weight必须依赖Linearlayout,而且并不能适用于任何场景)

再比如:我的某个浮动按钮的高度和宽度希望是屏幕高度的1/12,我的某个Button的宽度希望是屏幕宽度的1/3。

上述的所有的需求,利用dp是无法完成的,我们希望控件的尺寸可以按照下列方式编写:

<Button

android:text="@string/hello_world"

android:layout_width=“20%w”

android:layout_height=“10%h”/>

  • 1
  • 2
  • 3
  • 4

利用屏幕的宽和高的比例去定义View的宽和高。

好了,到此我们可以看到dp与百分比的区别,而百分比能够更好的解决我们的适配问题。

  • some 适配tips

我们再来看看一些适配的tips

  1. 多用match_parent

  2. 多用weight

  3. 自定义view解决

其实上述3点tip,归根结底还是利用百分比,match_parent相当于100%参考父控件;weight即按比例分配;自定义view无非是因为里面多数尺寸是按照百分比计算的;

通过这些tips,我们更加的看出如果能在Android中引入百分比的机制,将能解决大多数的适配问题,下面我们就来看看如何能够让Android支持百分比的概念。

3、百分比的引入

1、引入

其实我们的解决方案,就是在项目中针对你所需要适配的手机屏幕的分辨率各自简历一个文件夹。

如下图:

然后我们根据一个基准,为基准的意思就是:

  • 宽度为320,将任何分辨率的宽度分为320份,取值为x1-x320

  • 高度为480,将任何分辨率的高度分为480份,取值为y1-y480

例如对于800*480的宽度480:

可以看到x1 = 480 / 基准 = 480 / 320 = 1.5 ;

其他分辨率类似~~

你可能会问,这么多文件,难道我们要手算,然后自己编写?不要怕,下文会说。

那么,你可能有个疑问,这么写有什么好处呢?

假设我现在需要在屏幕中心有个按钮,宽度和高度为我们屏幕宽度的1/2,我可以怎么编写布局文件呢?

<FrameLayout >

<Button

android:layout_gravity=“center”

android:gravity=“center”

android:text="@string/hello_world"

android:layout_width="@dimen/x160"

android:layout_height="@dimen/x160"/>

</FrameLayout>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

可以看到我们的宽度和高度定义为x160,其实就是宽度的50%;

那么效果图:

可以看到不论在什么分辨率的机型,我们的按钮的宽和高始终是屏幕宽度的一半。

  • 对于设计图

假设现在的UI的设计图是按照480*320设计的,且上面的宽和高的标识都是px的值,你可以直接将px转化为x[1-320],y[1-480],这样写出的布局基本就可以全分辨率适配了。

你可能会问:设计师设计图的分辨率不固定怎么办?下文会说~

  • 对于上文提出的几个dp做不到的

你可以通过在引入百分比后,自己试试~~

好了,有个最主要的问题,我们没有说,就是分辨率这么多,尼玛难道我们要自己计算,然后手写?

2、自动生成工具

好了,其实这样的文件夹手写也可以,按照你们需要支持的分辨率,然后编写一套,以后一直使用。

当然了,作为程序员的我们,怎么能做这么low的工作,肯定要程序来实现:

那么实现需要以下步骤:

  1. 分析需要的支持的分辨率
  1. 编写自动生成文件的程序

代码如下

import java.io.File;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.PrintWriter;

/**

* Created by zhy on 15/5/3.

*/

public class GenerateValueFiles {

private int baseW;

private int baseH;

private String dirStr = “./res”;

private final static String WTemplate = “<dimen name=\“x{0}\”>{1}px\n”;

private final static String HTemplate = “<dimen name=\“y{0}\”>{1}px\n”;

/**

* {0}-HEIGHT

*/

private final static String VALUE_TEMPLATE = “values-{0}x{1}”;

private static final String SUPPORT_DIMESION = “320,480;480,800;480,854;540,960;600,1024;720,1184;720,1196;720,1280;768,1024;800,1280;1080,1812;1080,1920;1440,2560;”;

private String supportStr = SUPPORT_DIMESION;

public GenerateValueFiles(int baseX, int baseY, String supportStr) {

this.baseW = baseX;

this.baseH = baseY;

if (!this.supportStr.contains(baseX + “,” + baseY)) {

this.supportStr += baseX + “,” + baseY + “;”;

}

this.supportStr += validateInput(supportStr);

System.out.println(supportStr);

File dir = new File(dirStr);

if (!dir.exists()) {

dir.mkdir();

}

System.out.println(dir.getAbsoluteFile());

}

/**

* @param supportStr

* w,h_…w,h;

* @return

*/

private String validateInput(String supportStr) {

StringBuffer sb = new StringBuffer();

String[] vals = supportStr.split("_");

int w = -1;

int h = -1;

String[] wh;

for (String val : vals) {

try {

if (val == null || val.trim().length() == 0)

continue;

wh = val.split(",");

w = Integer.parseInt(wh[0]);

h = Integer.parseInt(wh[1]);

} catch (Exception e) {

System.out.println("skip invalidate params : w,h = " + val);

continue;

}

sb.append(w + “,” + h + “;”);

}

return sb.toString();

}

public void generate() {
, 136, 0); box-sizing: border-box;">";");

}

return sb.toString();

}

public void generate() {

举报

相关推荐

0 条评论