一部手机做好屏幕适配

一.Android多机型适配:

多机型适配在Android开发中经常会碰到,那么如果我们只有一部测试机,如何能做到用这一部手机来看各种不同分辨率手机的UI显示呢!不需要桌前摆一排手机来一个一个的是看。

二.WM命令:

1.什么是WM命令:

说了这么多前提,实际上需要使用的就是一行 wm 命令,可以通过 adb shell 来操作它。

wm 命令主要用来帮助我们修改一些屏幕的参数,先来看看它的文档。使用 adb shell wm 命令,可以方便的查看 wm 的文档描述


可以看到,wm 命令可以帮助我们修改当前设备的 size density 等参数,而这两个参数就是决定了当前设备的显示效果。

2.2 WM命令

上面的文档中有很多命令,其实我们平时用到的一般只有size,density这两个,以下例子为一部1080x1920的设备:

1. wm size命令

wm size 命令,可以用来查询和修改当前设备的尺寸,如果想要修改尺寸,可以使用 px 或者 dp 为单位(默认为 px),使用 x 进行连接,这个其实看看 wm size 的输出,你就清楚了。


上面的例子中,调用了不同的命令:

1.使用 wm size 命令查看当前设备的尺寸。


2.使用 wm size 命令将当前尺寸修改成了 1000x2000


3.再次使用 wm size 命令查看当前设备的尺寸。


4.最后使用 wm size reset 命令,将屏幕尺寸还原。


5.再用 wm size 命令,查看还原后的尺寸。

这几个步骤就已经涵盖了 wm size 命令的所有使用步骤,可以使用它查看当前屏幕尺寸,并且修改屏幕尺寸和还原它。


2.wm density命令

wm density 命令,可以用来查看和修改当前设备的 density 参数。

使用起来跟wm size相同,我们直接上命令吧。



在这个例子中,我做了几件事情:

1.使用 wm density 查看当前设备的 density


2.在使用 wm density 命令,修改当前设备的 density 560,580


3.然后再使用 wm density 查看修改后的参数。


4.最后使用 wm density reset 将设备的 density 还原。


5.最后再查看一下还原后的值。


3.wm overscan命令

wm overscan 命令,可以修改当前设备的屏幕内边距。这个命令一般用不到。



在这个例子中,做了两件事:


1.使用 wm overscan 修改边距为 30


2.然后使用 wm overscan reset 将其还原。


WM命令源码:

package com.android.commands.wm;
20
21import android.content.Context;
22import android.graphics.Point;
23import android.graphics.Rect;
24import android.os.RemoteException;
25import android.os.ServiceManager;
26import android.os.UserHandle;
27import android.util.AndroidException;
28import android.util.DisplayMetrics;
29import android.view.Display;
30import android.view.IWindowManager;
31import com.android.internal.os.BaseCommand;
32
33import java.io.PrintStream;
34import java.util.regex.Matcher;
35import java.util.regex.Pattern;
36
37public class Wm extends BaseCommand {
38
39    private IWindowManager mWm;
40
41    /**
42     * Command-line entry point.
43     *
44     * @param args The command-line arguments
45     */
46    public static void main(String[] args) {
47        (new Wm()).run(args);
48    }
49
50    @Override
51    public void onShowUsage(PrintStream out) {
52        out.println(
53                "usage: wm [subcommand] [options]\n" +
54                "       wm size [reset|WxH|WdpxHdp]\n" +
55                "       wm density [reset|DENSITY]\n" +
56                "       wm overscan [reset|LEFT,TOP,RIGHT,BOTTOM]\n" +
57                "       wm scaling [off|auto]\n" +
58                "       wm screen-capture [userId] [true|false]\n" +
59                "\n" +
60                "wm size: return or override display size.\n" +
61                "         width and height in pixels unless suffixed with 'dp'.\n" +
62                "\n" +
63                "wm density: override display density.\n" +
64                "\n" +
65                "wm overscan: set overscan area for display.\n" +
66                "\n" +
67                "wm scaling: set display scaling mode.\n" +
68                "\n" +
69                "wm screen-capture: enable/disable screen capture.\n" +
70                "\n" +
71                "wm dismiss-keyguard: dismiss the keyguard, prompting the user for auth if " +
72                "necessary.\n"
73                );
74    }
75
76    @Override
77    public void onRun() throws Exception {
78        mWm = IWindowManager.Stub.asInterface(ServiceManager.checkService(
79                        Context.WINDOW_SERVICE));
80        if (mWm == null) {
81            System.err.println(NO_SYSTEM_ERROR_CODE);
82            throw new AndroidException("Can't connect to window manager; is the system running?");
83        }
84
85        String op = nextArgRequired();
86
87        if (op.equals("size")) {
88            runDisplaySize();
89        } else if (op.equals("density")) {
90            runDisplayDensity();
91        } else if (op.equals("overscan")) {
92            runDisplayOverscan();
93        } else if (op.equals("scaling")) {
94            runDisplayScaling();
95        } else if (op.equals("screen-capture")) {
96            runSetScreenCapture();
97        } else if (op.equals("dismiss-keyguard")) {
98            runDismissKeyguard();
99        } else {
100            showError("Error: unknown command '" + op + "'");
101            return;
102        }
103    }
104
105    private void runSetScreenCapture() throws Exception {
106        String userIdStr = nextArg();
107        String enableStr = nextArg();
108        int userId;
109        boolean disable;
110
111        try {
112            userId = Integer.parseInt(userIdStr);
113        } catch (NumberFormatException e) {
114            System.err.println("Error: bad number " + e);
115            return;
116        }
117
118        disable = !Boolean.parseBoolean(enableStr);
119
120        try {
121            mWm.setScreenCaptureDisabled(userId, disable);
122        } catch (RemoteException e) {
123            System.err.println("Error: Can't set screen capture " + e);
124        }
125    }
126
127    private void runDisplaySize() throws Exception {
128        String size = nextArg();
129        int w, h;
130        if (size == null) {
131            Point initialSize = new Point();
132            Point baseSize = new Point();
133            try {
134                mWm.getInitialDisplaySize(Display.DEFAULT_DISPLAY, initialSize);
135                mWm.getBaseDisplaySize(Display.DEFAULT_DISPLAY, baseSize);
136                System.out.println("Physical size: " + initialSize.x + "x" + initialSize.y);
137                if (!initialSize.equals(baseSize)) {
138                    System.out.println("Override size: " + baseSize.x + "x" + baseSize.y);
139                }
140            } catch (RemoteException e) {
141            }
142            return;
143        } else if ("reset".equals(size)) {
144            w = h = -1;
145        } else {
146            int div = size.indexOf('x');
147            if (div <= 0 || div >= (size.length()-1)) {
148                System.err.println("Error: bad size " + size);
149                return;
150            }
151            String wstr = size.substring(0, div);
152            String hstr = size.substring(div+1);
153            try {
154                w = parseDimension(wstr);
155                h = parseDimension(hstr);
156            } catch (NumberFormatException e) {
157                System.err.println("Error: bad number " + e);
158                return;
159            }
160        }
161
162        try {
163            if (w >= 0 && h >= 0) {
164                // TODO(multidisplay): For now Configuration only applies to main screen.
165                mWm.setForcedDisplaySize(Display.DEFAULT_DISPLAY, w, h);
166            } else {
167                mWm.clearForcedDisplaySize(Display.DEFAULT_DISPLAY);
168            }
169        } catch (RemoteException e) {
170        }
171    }
172
173    private void runDisplayDensity() throws Exception {
174        String densityStr = nextArg();
175        int density;
176        if (densityStr == null) {
177            try {
178                int initialDensity = mWm.getInitialDisplayDensity(Display.DEFAULT_DISPLAY);
179                int baseDensity = mWm.getBaseDisplayDensity(Display.DEFAULT_DISPLAY);
180                System.out.println("Physical density: " + initialDensity);
181                if (initialDensity != baseDensity) {
182                    System.out.println("Override density: " + baseDensity);
183                }
184            } catch (RemoteException e) {
185            }
186            return;
187        } else if ("reset".equals(densityStr)) {
188            density = -1;
189        } else {
190            try {
191                density = Integer.parseInt(densityStr);
192            } catch (NumberFormatException e) {
193                System.err.println("Error: bad number " + e);
194                return;
195            }
196            if (density < 72) {
197                System.err.println("Error: density must be >= 72");
198                return;
199            }
200        }
201
202        try {
203            if (density > 0) {
204                // TODO(multidisplay): For now Configuration only applies to main screen.
205                mWm.setForcedDisplayDensityForUser(Display.DEFAULT_DISPLAY, density,
206                        UserHandle.USER_CURRENT);
207            } else {
208                mWm.clearForcedDisplayDensityForUser(Display.DEFAULT_DISPLAY,
209                        UserHandle.USER_CURRENT);
210            }
211        } catch (RemoteException e) {
212        }
213    }
214
215    private void runDisplayOverscan() throws Exception {
216        String overscanStr = nextArgRequired();
217        Rect rect = new Rect();
218        if ("reset".equals(overscanStr)) {
219            rect.set(0, 0, 0, 0);
220        } else {
221            final Pattern FLATTENED_PATTERN = Pattern.compile(
222                    "(-?\\d+),(-?\\d+),(-?\\d+),(-?\\d+)");
223            Matcher matcher = FLATTENED_PATTERN.matcher(overscanStr);
224            if (!matcher.matches()) {
225                System.err.println("Error: bad rectangle arg: " + overscanStr);
226                return;
227            }
228            rect.left = Integer.parseInt(matcher.group(1));
229            rect.top = Integer.parseInt(matcher.group(2));
230            rect.right = Integer.parseInt(matcher.group(3));
231            rect.bottom = Integer.parseInt(matcher.group(4));
232        }
233
234        try {
235            mWm.setOverscan(Display.DEFAULT_DISPLAY, rect.left, rect.top, rect.right, rect.bottom);
236        } catch (RemoteException e) {
237        }
238    }
239
240    private void runDisplayScaling() throws Exception {
241        String scalingStr = nextArgRequired();
242        if ("auto".equals(scalingStr)) {
243            mWm.setForcedDisplayScalingMode(Display.DEFAULT_DISPLAY, 0);
244        } else if ("off".equals(scalingStr)) {
245            mWm.setForcedDisplayScalingMode(Display.DEFAULT_DISPLAY, 1);
246        } else {
247            System.err.println("Error: scaling must be 'auto' or 'off'");
248        }
249    }
250
251    private void runDismissKeyguard() throws Exception {
252        mWm.dismissKeyguard();
253    }
254
255    private int parseDimension(String s) throws NumberFormatException {
256        if (s.endsWith("px")) {
257            return Integer.parseInt(s.substring(0, s.length() - 2));
258        }
259        if (s.endsWith("dp")) {
260            int density;
261            try {
262                density = mWm.getBaseDisplayDensity(Display.DEFAULT_DISPLAY);
263            } catch (RemoteException e) {
264                density = DisplayMetrics.DENSITY_DEFAULT;
265            }
266            return Integer.parseInt(s.substring(0, s.length() - 2)) * density /
267                    DisplayMetrics.DENSITY_DEFAULT;
268        }
269        return Integer.parseInt(s);
270    }
271}

根据上述源码以wm size 为例,解析下源码:

1.wm 命令的逻辑非常的简单,它实际上是和 WindowManagerService 进行交互,通过 WMS 来修改屏幕相关的一些参数。

这里就不介绍完整的 wm 源码了,就以一个方法举例来看看 wm 的逻辑。这里就以 wm size 命令举例好了。

首先,看看 wm 命令的入口onRun()


2.这里会初始化 mWm ,并且根据输入的参数,调用不同的方法,如果输入的是 size ,则会调用 runDisplaySize() 方法。


3. runDisplaySize() 方法中,会先判断 size 命令后面有没有跟其它参数,如果没有,则认为是一次查询操作,会将查询到的结果输出。

而如果是 reset 方法的话,就将 w h 这两个代表宽高的值,设置为 -1,最终会通过 mWm.clearForcedDisplaySize() 方法,将屏幕的 size 还原。

否者就从输入的参数中,通过 x 进行分割,拿到我们输入的宽高。最终通过 mWm.setForcedDisplaySize() 方法,将当前屏幕的 size 修改成我们输入的结果。

在设置size 的时候,还会通过 parseDimens() 方法,重新计算一下输入的尺寸。


4.从这里可以看出,它支持两个尺寸,px dp ,如果如果不指定尺寸,则默认认为是 px

到这里就完成了一次通过 wm size 命令,修改设备屏幕参数的全过程


操作注意事项:

1.手机连接电脑并打开UBS调试;


2.运行自己的app;


3.打开电脑命令行进行上述命令设置,即可看到手机不同分辨率。


常用到的手机分辨率及尺寸,仅供参考:

手机型号       density           size

 一加5              420          1080x1920


红米NOTE.         320             720x1280


华为MATE7.       480
             1080x1812


MOTO-G5          
480             1080x1920


魅族MX3            440             1080x1800


Nexus5x             420             1080x1794


Nexus6p             560             1440x2392


奇酷360              460             1080x1920


VivoX5                320               720x1280




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值