一部手机做好屏幕适配
一.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
一部手机做好屏幕适配相关推荐
- android做好屏幕适配,android屏幕适配
Android一些尺寸单位的基础概念描述 屏幕尺寸:单位英寸,屏幕对角线的物理尺寸. dp:官方是根据320480为基准指定dp值,即dpi160下,1dp=1px,在dpi320下即分辨率72010 ...
- 【原】android【手机】屏幕适配解决方案,完美适配适配hdpi,xhdpi,xxhdpi的做法。
[原]android[手机]屏幕适配解决方案,完美适配适配hdpi,xhdpi,xxhdpi的做法. 参考文章: (1)[原]android[手机]屏幕适配解决方案,完美适配适配hdpi,xhdpi, ...
- Unity开发游戏中全面屏手机的屏幕适配
很多人可能把全面屏跟曲面屏混淆,其实这是两个不同的概念. 一般手机的屏幕纵横比为16:9,如1080x1920.1440x2560等,其比值为1.777777--,全面屏手机出现之前,Android中 ...
- Unity中全面屏手机的屏幕适配问题
unity打包apk 安装到手机上,在曲面屏手机上 上下会留有黑边,总是不能全面适配手机. 一般手机的屏幕纵横比为16:9,如1080x1920.1440x2560等,其比值为1.7左右,全面屏手机出 ...
- 【原】android【手机】屏幕适配解决方案,完美适配适配hdpi,xhdpi,xxhdpi的做法。...
1.先说要怎么做,后面在慢慢讲解: 2.现在来讲解为什么要放这三套: 这三套其实按内容来说就两种,为什么这两种可以适配hdpi,xhdpi,xxhdpi呢? 那么两种类型的dimens就可以了,为什么 ...
- android 适配2k屏幕分辨率,Android设备兼容处理(二):屏幕适配
前言 要做好屏幕适配最重要的是了解当前市场设备分布,目前主流设备可以分为三类,4.7-5.5英寸的中屏手机,5.5-7.0的大屏手机,以及7.0英寸以上的平板.分辨率则是720P,1080P和2K. ...
- android ui布局适配,Android适配全面总结(一)----屏幕适配
前言 Android适配是一个老生常谈的问题,很多程序员觉得很恶心,不愿意做适配,但是又不得不做.然后老板说,这位兄弟,做好了,今天晚饭给你加个鸡腿,然后程序员开始找各种资料,忙活起来了,最终在苦逼的 ...
- Android适配全面总结(一)----屏幕适配
版权声明:本文为博主原创文章(部分引用他人博文,已加上引用说明),未经博主允许不得转载.https://www.jianshu.com/p/7aa34434ad4d 转载请标明出处: https:// ...
- 小米max android auto,Android屏幕适配的前世今生(二)
前言 上篇文章介绍了在屏幕适配上遇到的问题,采用px或者dp都会与设计稿存在一定的偏差,也详细的介绍了dp和dpi含义和作用,本篇文章着重介绍我们应该如何做好屏幕适配的工作,以及各种屏幕适配方法发展史 ...
最新文章
- 英特尔在移动芯片为何衰败 看完此文豁然开朗
- 洛谷 - P1381 - 单词背诵 - 哈希 - 尺取
- 协程实现爬虫的例子主要优势在于充分利用IO时间去请求其他的url
- hdu 2059(dp)
- 使用Heroku,解决gitment登录失败,报[object ProgressEvent]的错
- C++中默认构造函数使用时的要点
- 未能成功加载扩展程序_【JAVA虚拟机(JVM)精髓】09-几种不同的类加载器
- Direct3D播放RGB(通过Texture)
- 线性表之--队列操作
- 一位全加器Verilog的三种不同的描述
- VGG16和VGG19的理解
- linux pci转can驱动程序,PCI转LPT并口卡驱动程序
- 信息系统项目管理师考试经验和心得
- 如何做一个自动化感应垃圾桶
- Linux下的java运行
- java 动态密码错误_什么是OTP:Java一次动态密码、付款码原理
- Excel一键求得单元格内数值个数的操作!
- “Cache-主存”和“主存和辅存”的区别
- python 输入输出重定向_输入输出重定向_清华尹成python入门教程_少儿编程视频-51CTO学院...
- 怎么监控Linux流量,linux下监控流量
热门文章
- python实现天气数据爬取实现数据可视化和天气查询gui界面设计
- 币信(BXIN)创始人唐仪(Tony Tong):币信(BXIN)坚持合规为主
- 微信小程序开发笔记 支付篇④——基于微信支付SDK实现Java后端接口使用
- 微分matlab程序,数值微分及其matlab程序.doc
- 电脑螺旋丸html,code_editor.html
- B站韩顺平java学习笔记(二十三)-- MYSQL基础篇 章节
- C语言 while语句
- 用腾讯轻联,打通草料二维码与其他应用的连接
- AI外呼机器人的作用
- C语言rand和srand函数的简单介绍和用法