一部手机做好屏幕适配

来源:互联网 发布:菜鸟手机助手源码 编辑:程序博客网 时间:2024/04/30 03:29

一.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;2021import 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;3233import java.io.PrintStream;34import java.util.regex.Matcher;35import java.util.regex.Pattern;3637public class Wm extends BaseCommand {3839    private IWindowManager mWm;4041    /**42     * Command-line entry point.43     *44     * @param args The command-line arguments45     */46    public static void main(String[] args) {47        (new Wm()).run(args);48    }4950    @Override51    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    }7576    @Override77    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        }8485        String op = nextArgRequired();8687        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    }104105    private void runSetScreenCapture() throws Exception {106        String userIdStr = nextArg();107        String enableStr = nextArg();108        int userId;109        boolean disable;110111        try {112            userId = Integer.parseInt(userIdStr);113        } catch (NumberFormatException e) {114            System.err.println("Error: bad number " + e);115            return;116        }117118        disable = !Boolean.parseBoolean(enableStr);119120        try {121            mWm.setScreenCaptureDisabled(userId, disable);122        } catch (RemoteException e) {123            System.err.println("Error: Can't set screen capture " + e);124        }125    }126127    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        }161162        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    }172173    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        }201202        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    }214215    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        }233234        try {235            mWm.setOverscan(Display.DEFAULT_DISPLAY, rect.left, rect.top, rect.right, rect.bottom);236        } catch (RemoteException e) {237        }238    }239240    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    }250251    private void runDismissKeyguard() throws Exception {252        mWm.dismissKeyguard();253    }254255    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方法的话,就将 wh这两个代表宽高的值,设置为 -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




原创粉丝点击