精华内容
下载资源
问答
  • Android中有一个类:DisplayMetrics,官方文档在此:https://developer.android.google.cn/reference/android/util/DisplayMetrics?hl=en ...属性并不多,对于屏幕密度官方描述不够详细,所以这里记录

    context.getResources().getDisplayMetrics()

    Android中有一个类:DisplayMetrics,官方文档在此:https://developer.android.google.cn/reference/android/util/DisplayMetrics?hl=en

    DisplayMetrics类描述有关显示器的一般信息的结构,例如其大小,密度和字体缩放。

    DisplayMetrics实例对象的获取方式:context.getResources().getDisplayMetrics();

    属性并不多,对于屏幕密度官方描述不够详细,所以这里记录一下,描述详细一点。DisplayMetrics常用属性如下:

    • widthPixels 屏幕宽。当手机发生旋转时,之前的宽会变成高。
    • heightPixels 屏幕高。当手机发生旋转时,之前的高会变成宽。
    • densityDpi 屏幕密度,即每英寸的屏幕中包含的像素数量,英寸为国外的长度单位,它换算为国内的单位为:1英寸 = 2.54厘米,所以每英寸屏幕,就是说每2.54厘米屏幕。比如densityDpi为160,则表示每英寸屏幕中的像素点有160个,也就是说真实手机屏幕上,你可以拿尺去量一量,屏幕上,每2.54厘米就包含有160个像素点在里面,当然了,你量一量长度还可以,像素点你是看不见的,因为像素点非常非常的小。dpi为480的手机,理论是要比dpi为160的手机清晰很多很多的,因为同样的1英寸的屏幕大小,一个手机可以使用480个像素点来显示图像,一个只能用160个像素点来显示图像,效果肯定是差很多的。
    • density 官方称它为显示的逻辑密度,这不太好理解,我把它理解为密度的比例,也可以理解为dp换算为像素的比例(即1个dp等于几个像素)。标准的屏幕密度为160,它的密度比例就是1,即1个dp就等于1个像素。如果你手机的densityDpi为320,则它是标准屏幕密度的两倍(320 / 160 = 2),则density = 2,表示1个dp就等于2个像素。举个例子,比如你手机的densityDpi为320,然后你设置了一个控件的宽为60dp,则它显示到屏幕上的实际宽度为120像素,因为density = 2,所以60 * 2px = 120px。
    • scaledDensity 字体比例。它的默认值也是densityDpi / 160,也就是说默认和density值是一样的,但是我们在手机上是可以设置字体大小的,这时候的scaledDensity就会发生改变。举个例子,假设densityDpi = 320,则density = 2,默认的scaledDensity也为2,这时我们在手机设置中修改字体大小,设置为最大号,则scaledDensity的值肯定大于2,我假设此时scaledDensity = 3,然后我们在布局中添加两个TextView,一个TextView的大小设置为10dp,另一个TextView的大小设置为10sp,则它们显示到手机上时,真实大小为:一个是20像素(10dp x 2px = 20px),另一个是30像素(10sp x 3px = 30px),所以平时我们说,在设置字体大小时应该使用sp,而不是dp,了解到这里之后,我们就有了自己的了解了,字体大小并不一定要设置为sp的,设置为dp也可以,如何选择呢?就看需求了,比如,有一个地方的TextView,我希望它的大小是固定不变的,因为如果设置的太大了会影响到我其它控件的显示,界面就不美观了,则此时应该使用dp,这样的话,用户在设置里面不论如何设置字体大小都不会影响到我的这个TextView的大小了。而一些文章类的页面,我们为了照顾视力不好的用户,应该使用sp,这样,视力不好的用户,它觉得我界面上的字体太小了,但是我界面上又没有增加设置字体大小的功能,则此时用户可以自己到系统的设置里面去修改字体大小,这样我的界面上使用sp为单位的字体大小就会随之改变。

    一般我们在xml中写布局控件的大小时,直接使用dp或sp即可,但是如果在代码中,设置控件大小,它默认单位是px,此时就需要动手把dp转换为px,比如在代码中想把20dp换算为对应的像素值,则:

    val dpCount = 20 // 表示20dp
    val pxCount = context.getResources().getDisplayMetrics().density * dpCount // dp换算为像素
    mButton.setWidth(pxCount) // 设置按钮的宽为20dp
    

    在代码中设置TextView或Button等控件的字体大小时,默认单位就是sp的,所以不需要在换算处理,如:mTextView.setTextSize(10),即表示设置字体大小为10sp。

    所以,其实平时开发中,常用到的是desity属性,而densityDpi和scaledDensity很少会使用。

    之前,我还写过一篇有点相关屏幕密度的文章,可以了解一下:getDimension与getDimensionPixelOffset与getDimensionPixelSize的区别

    Android Jetpack组件中的Compose用于写UI,以后应该会成为主流,它里面有一个类叫Dp,官方文档在此:https://developer.android.google.cn/reference/kotlin/androidx/compose/ui/unit/Dp?hl=en
    添加了Compose依赖之后,在代码中想要表示20dp,可以这样:val width = 20.dp,它其实就是Kotlin的扩展函数,给Int添加了扩展,自动把20转换为对应的像素。

    后来,有发现手机的dpi是可以改变的,这就神奇了,这不应该是固定不变的吗?比如,你手机显示器分辨率为1080 x 1920,dpi为480,然后我在手机设置的开发者选项里面,修改一个叫“最小宽度”的设置,默认最小宽度为360dp,为什么是360dp呢?因为dpi为480,则密度的比例desity = 480 / 160 = 3,所以1dp = 3px,所以1080px就相当于360dp(1080 / 3 = 360dp),我把最小宽度设置为1080dp,此时的dpi会变成120,密度比例就是1,所以此时看到的桌面图标会非常小,因为此时1dp = 1px,就像电脑一样了,你可以想像把1920 x 1080的电脑屏幕放到手机上显示,内容看起来肯定小啊。平时我们看手机上的内容不觉得小,是因为我们使用的单位是dp,而1个dp是等于多个px的,所以内容看起来就大,不会觉得小,打个比方,比如手机屏幕宽度为360dp,我们设置一个按钮的宽为300dp,则此时看效果屏幕右边就只有60个dp空闲出现,如果我们把最小宽改为1080dp,则右边就空闲了780dp出来,那按钮看起来肯定比之前小了。理论上说,dpi应该是固定的,比如dpi = 480,分辨率为1920 x 1080,当你dpi变为120时,则密度变低了,则如果你还想分辨率不变的话,理论上你是要扩大显示屏的真实大小,因为你密度小了,屏幕需要更多的尺寸才能有和原来一样的分辨率啊! 至于为什么能修改dpi我就不深究了,我们只要记得dpi是可以修改的就行了,当你修改了最小宽度的时候,dpi就会发生变化,最小宽度可以通过分辨率的宽和dpi算出来,dpi也可以通过分辨率和最小宽度算出来,如下:

    最小宽度(单位dp)= 分辨率宽 / (dpi / 160)
    dpi = 分辨率宽 / 最小宽度 * 160
    

    比如,宽是1080px,dpi是480,则最小宽为360dp,1080 / (480 / 160) = 360dp
    比如,宽是1080px,最小宽度为360dp,则dpi为480,1080 / 360 * 160 = 480

    后来想了一下,修改dpi可以这样理解,默认的dpi是真实的dpi,也就是代表1英寸有多少个像素的,当你修改屏幕最小宽度后,其实1英寸有多少个像素是固定了不可能再变了的,修改只是模拟而已,是模拟的行为,比如宽为1080,标准密度是480,1dp = 3px,则宽度为360dp,现在把最小宽度改为1080dp,则1dp = 1px,密度为160,此时的1英寸中包含有160个像素,这是不可能的,因为真实的话是包含有480个,所以这里密度为160的1英寸是模拟的1英寸,是比原来小3倍的1英寸,所以,最小宽度改为1080dp后,可以理解为手机的英寸变多了(手机尺寸变大了),当然了,这只是模拟的或者想像的变大了,其实并没有变大,此时的1英寸并不是真实物理上的1英寸了,它是物理1英寸的三分之一大小,因为物理1英寸是装有480像素的,而它只有160,480 / 160 = 3。

    所以,当你在两台分辨率相同的手机上运行同一个app时,如果发现显示效果不一样,则你要想到应该是它们的dpi不相同导致的,你可以到设置里面修改最小宽度,改成一样的,这样效果肯定就一样了。

    如果是分辨率一样,密度也一样,但是字体大小看起来不一样,则你要想到应该是字体密度比例不相同导致的,你可以到设置里面修改字体大小,调到安慰体密度比例一样时,效果肯定就一样了。

    在公司的一台定制机上,分辨率是1080P的,默认最小宽度是360dp,可以改到160dp,但是在小米6和华为mate30上,相同的分辨率,默认最小宽也是360dp,但是修改时最小只能改到320dp。改大时,华为mate30可以改到1080dp没问题,而小米6改1080dp后,直接黑屏重启了,而且再也起不来了,自动进入了Recovery模式,估计要清除数据才能恢复了。所以这个最小宽度不要随便设置,有风险!!

    常见分辨率:
    drawable-xhdpi 文件夹: 超高密度屏幕:dpi = 320dp,scale = 2.0,分辨率:720 x 1280
    drawable-xxhdpi文件夹: 超超高密度屏幕:dpi = 480dp,scale= 3.0,分辨率:1080 x 1920
    为什么按照720 x 1280写的界面,只要单位是dp,就能在1080 x 1920中完美适配呢?这是因为他们的dp数量是一个的:
    720 x 1280
    宽度:720 / 2 = 360dp
    高度:1280 / 2 = 640dp

    1080 x 1920
    宽度:1080 / 3 = 360dp
    高度:1920 / 3 = 640dp

    所以,虽然他们的分辨率不一样,但是只要确保720P的手机密度为320dp,1080P的手机密度为480dp,则他们宽高的dp数是一样的。其实高度的dp数不一样影响不大,因为高度上可以增加垂直滚动,上下滚动就好了,关键宽度的dp数,如果宽度上dp数一样,则适配就是完美的,所以对于适配,一般看看手机设置里的最小宽度的dp数量是不是一样的就知道了,比如在720P或1080P手机上,最小宽度dp为360dp,而在我的另一台小米手机,它的宽度最小dp为411dp,假如美工给你的图是以720P设计的,在宽度上往了各种控件,放满宽度最多也就使用360个dp,假设用的是线性布局水平排序,当运行到411dp的手机上时,你会发现手机右侧多了很多空白,因为你的空间总共的宽最多360dp,而手机有411dp。所以在做开发时,尽量不要写这种太绝对的布局,比如标题栏,标题在中间,左右两侧有图标,使用相对布局就比较好,运行到360dp和411dp上,能保证标题栏各位控件的相对位置,只是效果上,411dp的手机标题栏的标题和左右两边的图标距离看着会感觉比较大一些。

    WindowMetrics.getBounds()获取屏幕宽高

    DisplayMetrics dm = new DisplayMetrics();
    activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
    

    通过这种方式也能获取到一个DisplayMetrics对象,但是我们发现getMetrics函数已经过时了,推荐使用WindowMetrics.getBounds()获取应用程序窗口区域的尺寸,使用Configuration.densityDpi获取当前密度。

    于是我就查了WindowMetrics的官方文档,上面推荐了两各方式获取此对象的实例,如下:

    mWindowManager.getCurrentWindowMetrics()
    mWindowManager.getMaximumWindowMetrics()
    

    细看WindowMetrics类的完全形式为:androidx.window.WindowMetrics,这不是SDK里面的类,这是Jetpack组件里面的,所以要想使用这个类,需要引入依赖,如下:

    implementation "androidx.window:window:1.0.0-alpha02"
    

    这两个函数的区别,看不太懂,英文不行。在我的手机上,这两个函数都能获取到屏幕的宽高,代码如下:

    val wm = WindowManager(this)
    val metrics = wm.currentWindowMetrics
    val bounds = metrics.bounds
    val width = bounds.width()
    val height = bounds.height()
    

    哦呵,这里的WindowManager竟然可以直接new出来,真实神奇了!

    getBounds()函数官方文档:https://developer.android.google.cn/reference/kotlin/android/view/WindowMetrics?hl=en#getBounds()
    文档描述说,此方法返回的宽高是包括系统栏区域的,而Display.getSize(Point)获取的宽高不包括。getSize函数获取的宽高也可通过下面的方式获得:

    final WindowMetrics metrics = windowManager.getCurrentWindowMetrics();
      // Gets all excluding insets
      final WindowInsets windowInsets = metrics.getWindowInsets();
      Insets insets = windowInsets.getInsetsIgnoringVisibility(WindowInsets.Type.navigationBars()
              | WindowInsets.Type.displayCutout());
     
      int insetsWidth = insets.right + insets.left;
      int insetsHeight = insets.top + insets.bottom;
     
      // Legacy size that Display#getSize reports
      final Rect bounds = metrics.getBounds();
      final Size legacySize = new Size(bounds.width() - insetsWidth,
              bounds.height() - insetsHeight);
      
    

    注:此windowManager要使用SDK自带的,不能使用jetpack中的。且此insets.width()是在API29才出来的,在低版本无法使用。

    Configuration获取屏幕密度、方向、最小宽度

    Configuration实例获取方式:

    Configuration config = getResources().getConfiguration();
    

    这个类上的一些感觉能用得上的属性如下:

    • densityDpi 屏幕密度
    • fontScale 字体比例,实际上我发现这个并不是我们之前理解的那个字体密度比例,不论我如何在设置中修改字体大小,它的值始终是1。
    • locale 语言环境
    • mcc IMSI MCC(移动国家/地区代码)
    • mnc IMSI MNC(移动网络代码)
    • orientation 屏幕的总体方向
    • screenWidthDp 可用屏幕空间的当前宽度,以dp为单位。
    • screenHeightDp 可用屏幕空间的当前高度,以dp为单位。经实验,我发现这个值并不是屏幕的完整高,应该是扣掉了系统状态栏的高度了。
    • smallestScreenWidthDp 应用程序在正常操作中将看到的最小屏幕尺寸,这是什么意思呢?意思是不管你是横屏还是竖屏显示,它始终是最小的那条边的尺寸,比如1080 x 1920的手机,竖屏时宽是1080,最小宽,1080px为360dp,当横屏时,高为1080px,最小宽的值还是这个1080px对应的360dp。

    代码示例如下:

    resources.configuration.apply {
        Timber.i("densityDpi = ${this.densityDpi}")
        Timber.i("screenWidthDp = ${this.screenWidthDp}")
        Timber.i("screenHeightDp = ${this.screenHeightDp}")
        Timber.i("smallestScreenWidthDp = ${this.smallestScreenWidthDp}")
        Timber.i("orientation = ${if (this.orientation == Configuration.ORIENTATION_LANDSCAPE) "横屏" else "竖屏"}")
    }
    

    Context.getDisplay()

    Display:提供一个逻辑显示的关于大小和密度的信息。

    Display获取方式:

    context.getWindowManager().getDefaultDisplay() // 在API30版本过时
    context.getDisplay() // API30才出来的函数
    DisplayManager.getDisplay(displayId)
    DisplayManager.getDisplays()
    DisplayManager.getDisplays(category)
    

    示例如下:

    windowManager.defaultDisplay?.let {
                    Timber.i("displayId = ${it.displayId}")
                    Timber.i("name = ${it.name}")
                    Timber.i("width = ${it.width}")   // 过时,推荐WindowMetrics.getBounds()
                    Timber.i("height = ${it.height}") // 过时,推荐WindowMetrics.getBounds()
                    val metrics = DisplayMetrics()
                    it.getMetrics(metrics) // 过时,推荐WindowMetrics.getBounds()获取宽高,Configuration.densityDpi获取屏幕密度
                    Timber.i("width2 = ${metrics.widthPixels}")
                    Timber.i("height2 = ${metrics.heightPixels}")
    
                    Timber.i("orientation = ${it.orientation}") // 过时,推荐rotation
                    Timber.i("rotation = ${it.rotation}")
                    Timber.i("state = ${it.state}") // 1-显示器关闭,2-显示器打开
                    Timber.i("supportedRefreshRates = ${it.supportedRefreshRates.contentToString()}")
    
                    val metrics2 = DisplayMetrics()
                    it.getRealMetrics(metrics2)
                    Timber.i("width3 = ${metrics2.widthPixels}")
                    Timber.i("height3 = ${metrics2.heightPixels}")
    
                    val point = Point()
                    it.getRealSize(point)
                    Timber.i("width4 = ${point.x}")
                    Timber.i("height4 = ${point.y}")
    
                    val rect = Rect()
                    it.getRectSize(rect) // 过时,推荐WindowMetrics#getBounds()
                    Timber.i("width5 = ${rect.width()}")
                    Timber.i("height5 = ${rect.height()}")
    
                    val point2 = Point()
                    it.getSize(point2) // 过时,推荐WindowManager#getCurrentWindowMetrics()
                    Timber.i("width6 = ${point2.x}")
                    Timber.i("height6 = ${point2.y}")
                }
    

    打印结果如下:
    displayId = 0
    name = 内置屏幕
    width = 1080
    height = 1920
    width2 = 1080
    height2 = 1920
    orientation = 0
    rotation = 0
    state = 2
    supportedRefreshRates = [55.55]
    width3 = 1080
    height3 = 1920
    width4 = 1080
    height4 = 1920
    width5 = 1080
    height5 = 1920
    width6 = 1080
    height6 = 1920

    展开全文
  • 修改手机屏幕密度

    2015-08-07 18:01:36
    修改安卓手机密度的代码
  • 手机屏幕像素密度是dp与px的换算进制,相当于1dp等于多少px。由于没有手机不同,像素密度也是不一样的,所以我们需要用代码的方式获取当前手机的像素密度。 像素密度的获取方法如下: public static float ...

    手机屏幕像素密度是dp与px的换算进制,相当于1dp等于多少px。由于没有手机不同,像素密度也是不一样的,所以我们需要用代码的方式获取当前手机的像素密度。

    像素密度的获取方法如下:

    public static float getScreenDensity(Context ctx){
        //从系统服务中获取窗口管理器
        WindowManager wm = (WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics dm = new DisplayMetrics();
        //从默认显示器中获取显示参数保存到dm对象中
        wm.getDefaultDisplay().getMetrics(dm);
        return dm.density;//返回屏幕的像素密度数值
    }

    这样就可以获取到像素密度,进一步进行dp和px的转化。另外我有一篇专门的博客讲解dp,sp,px之间的相互转化问题,也可以借鉴。

    展开全文
  • Android开发为适配不同屏幕需要在资源文件中添加多套图片或者多套布局文件,这篇文章讲解多套图片。 ldpi,mdpi,xhdpi,xxhdpi,xxxhdpi分别代表什么?如何使用。 1屏幕大小 智能手机普及,屏幕也随之越来越大,从...

    Android开发为适配不同屏幕需要在资源文件中添加多套图片或者多套布局文件,这篇文章讲解多套图片。
    在这里插入图片描述
    ldpi,mdpi,xhdpi,xxhdpi,xxxhdpi分别代表什么?如何使用。

    1屏幕大小

    智能手机普及,屏幕也随之越来越大,从经典的iPhone 4的3.5英寸到iphone XR 6英寸多,Android手机也逐渐进入了6.x英寸行列。
    屏幕大小定义:手机对角线的物理尺寸,以英寸(inch)为单位,一英寸大约2.54厘米。
    通常的手机尺寸:4英寸,4.5英寸,4.0英寸,5.0英寸,5.2英寸,5.4英寸,5.99英寸,6.0英寸,6.2英寸等
    在这里插入图片描述

    2 屏幕分辨率

    屏幕分辨率:分辨率是手机屏幕的像素点总数,一般用屏幕宽的像素点数乘以屏幕高的像素点数。分辨率越大屏幕越细腻,能够显示的细节就更多。常用的分辨率包括320x240,640x480,1280x720,1280x960,1080x1920,2560x1440这些只是常用分辨率,所以分辨率还有很多其他数值,他们的单位都是像素。类似1080x1920表示屏幕宽度方向上有1080个像素,屏幕高方向上有1920个像素。

    3 像素密度

    像素密度(dpi,dots per inch;或PPI,pixels per inch):每英寸上的像素点数,结合屏幕大小和屏幕分辨率如果5.0英寸的手机的屏幕分辨率为1280x720,那么像素密度为192dpi(计算过程为首先计算对角线上的像素数)。

    屏幕密度:
    像素密度上面已经讲过了,那么什么是屏幕密度呢?
    屏幕密度不知道如何定义,其实屏幕密度就是像素密度的另外一种表示,是以160dpi=1.0为基准的。手机出厂之后屏幕密度,包括X,Y轴方向的像素密度都是固定值。
    android将实际的屏幕密度进行划分(low,medium,high,and extra high,extra extra high)
    一般情况下的普通屏幕:ldpi是120dpi,mdpi是160dpi,hdpi是240dpi,xhdpi是320dpi ,xxhdpi 是480dpi。android以像素密度160dpi为基准对屏幕进行划分,当像素密度为160dpi时屏幕密度为1.0,像素密度为120dpi时屏幕密度为0.75,像素密度为320dpi时屏幕密度为2.0.
    如何获取屏幕分辨率和像素密度,屏幕密度:

     private void getScreenInfo() {
            // 获取屏幕分辨率
            int screenWidth  = getWindowManager().getDefaultDisplay().getWidth();		// 屏幕宽
            int screenHeight = getWindowManager().getDefaultDisplay().getHeight();		// 屏幕高
    
            Log.e( "屏幕分辨率", "screenWidth=" + screenWidth + "; screenHeight=" + screenHeight);
    
            // 获取像素密度和屏幕密度
            DisplayMetrics dm = new DisplayMetrics();
            dm = getResources().getDisplayMetrics();
    
            float density  = dm.density;		// 屏幕密度(像素比例:0.75/1.0/1.5/2.0)
            int densityDPI = dm.densityDpi;		// 像素密度(每寸像素:120/160/240/320)
            float xdpi = dm.xdpi;               //X轴方向的像素密度
            float ydpi = dm.ydpi;                //Y轴方向的像素密度
    
            Log.e("XY轴方向上的像素密度", "xdpi=" + xdpi + "; ydpi=" + ydpi);
            Log.e( " 像素密度和屏幕密度", "density=" + density + "; densityDPI=" + densityDPI);
    
            screenWidth  = dm.widthPixels;		// 屏幕宽
            screenHeight = dm.heightPixels;		// 屏幕高
    
            Log.e("屏幕分辨率", "screenWidth=" + screenWidth + "; screenHeight=" + screenHeight);
    
            // 获取屏幕密度(方法3)
            dm = new DisplayMetrics();
            getWindowManager().getDefaultDisplay().getMetrics(dm);
    
            density  = dm.density;
            densityDPI = dm.densityDpi;
            xdpi = dm.xdpi;
            ydpi = dm.ydpi;
    
            Log.e("屏幕XY轴方向上的像素密度", "xdpi=" + xdpi + "; ydpi=" + ydpi);
            Log.e("屏幕像素密度和屏幕密度", "density=" + density + "; densityDPI=" + densityDPI);
    
            int screenWidthDip = dm.widthPixels;
            int screenHeightDip = dm.heightPixels;
    
            Log.e("屏幕XY轴方向上的像素密度", "screenWidthDip=" + screenWidthDip + "; screenHeightDip=" + screenHeightDip);
    
            screenWidth  = (int)(dm.widthPixels * density + 0.5f);
            screenHeight = (int)(dm.heightPixels * density + 0.5f);
    
            Log.e(" 屏幕分辨率", "screenWidth=" + screenWidth + "; screenHeight=" + screenHeight); 
    }
    

    4 Android手机常见分辨率和drawable适配说明

    手机常见尺寸和对应像素密度
    4:3的尺寸
    VGA :640x480 (Video Graphics Array)
    QVGA :320x240 (Quarter VGA)
    HVGA :480x320 (Half-size VGA)
    SVGA :800x600 (Super VGA)
    5:3的尺寸:
    WVGA :800x480 (Wide VGA)
    16:9的尺寸:
    FWVGA: 854x480 (Full Wide VGA)
    HD :1920x1080 High Definition
    QHD :960x540
    720p :1280x720 标清
    1080p :1920x1080 高清

    一般分辨率对应DPI:
    “HVGA mdpi”
    "WVGA hdpi "
    "FWVGA hdpi "
    "QHD hdpi "
    “720P xhdpi”
    "1080P xxhdpi "
    nodpi里面的资源不会被缩放,无论尺寸是否满足条件。
    此时会有一个疑问,手机的像素密度可以是任何值,Android手机只有mdpi,hdpi,ldpi,xhdpi,xxhdpi,xxxhdpi等有限的几个适配目录,Android手机如何适配呢,所以可以推测,Android中获取的屏幕密度,不是对应屏幕真实的屏幕密度值,类似1280720和1290730都会被认为是720p的手机,屏幕密度都是2.0。
    注意:上面的一般分辨率对应的dpi只代表一般情况,绝大多数厂商都会遵循,这么说的意思是分辨率和像素密度不是上面的对应关系,还跟手机的尺寸相关,这就是我们看到的很多平板比手机大很多,但是它的分辨率依然是1080p,特别是现在很多智能车载比普通的平板还大,它的屏幕分辨率和普通手机一样,适配时可能只会用到mdpi目录。

    各个drawable加载顺序:

    android系统适配Drawable时会首先查找屏幕密度尺寸都满足的drawable,如果没有找到:
    当应用在设备对应dpi目录下没有找到某个资源时,遵循“先高再低”原则,然后按比例缩放图片如果当前为xhdpi设备(项目中只有xxhdpi,xhdpi,xxhdpi,nodpi,mdpi,hdpi),则drawable的寻找顺序为,首先查找xhdpi目录 如果没找到,依然查找xxhdpi,如果还没有找到xxxhdpi,还没有找到查找nodpi,如果还没有查找hdpi,然后查找mdpi,如果在xxhdpi中找到目标图片,则压缩2/3来使用(因为系统认为它找到了一个比合适尺寸大的图片),如果在mdpi中找到图片,则放大2倍来使用(系统认为它找到了一个比适合尺寸小的图片,需要放大才能保证正常)。

    5 为什么2017年以后Android手机适配一般只需要xhdpi和xxhdpi两套资源就可以

    2017年以后的android手机一般大小在5寸以上,分辨率至少720p,1080p,所以对应的dpi分别为:
    720p 1280720 5寸对应dpi 大约 300dpi
    1080p 1920
    1080 5寸对应dpi 大约440 dpi
    xhdpi对应320dpi,xxhdpi对应480dpi,所以手机适配一般只需要xhdpi和xxhdpi两套资源就可以。

    注意:对于平板,只能电视和车载系统的开发,一般xhdpi和xxhdpi用不到,ldpi,mdpi用的比较多

    6 dp 和px的转换

    dp是android中用于适配的尺寸,他能保证在不同尺寸密度屏幕上显示的大小相同,有点类似物理尺寸,相同的dp展示效果相同,它们代表的px是不一样的。
    dp与px的转换
    系统密度为160dpi的中密度手机屏幕为基准屏幕,即320×480的手机屏幕中,1dp=1px。
    而在480×800(hdpi,240dpi)的手机上1dp=1.5px.所以dp和px的换算以屏幕密度为准则而不是屏幕的实际密度。

    展开全文
  • 修改Android手机的分辨率和屏幕密度

    千次阅读 2021-05-18 16:39:16
    修改分辨率和屏幕密度

    不要总想着万全之策,写了就是给自己看的,写错了改就行了。

    原文:https://www.jianshu.com/p/bd91b611b212

    之前一直不知道手机的DPI还可以修改,以前测试我都是用好几个测试机,或者通过修改开发者模式下的最小宽度去看适配的问题。呐,前段时间朋友说可以直接用adb改,赶紧记下来,省的以后忘了。

    工具

    adb 命令

    准备

    adb shell
    

    命令

    $ wm size
    $ wm density
    

    分辨率

    wm size [reset|WxH|WdpxHdp]
    return or override display size. width and height in pixels unless suffixed with ‘dp’.

    查看分辨率:wm size
    修改分辨率:wm size 1440x2560
    还原初设置:wm size reset

    测试机:华为 FRD-DL00

    Microsoft Windows [版本 10.0.18363.1500]
    (c) 2019 Microsoft Corporation。保留所有权利。
    
    C:\Users\BigMoom>adb shell
    HWFRD:/ $ wm size                     // 查看
    Physical size: 1080x1920              // 返回默认值
    
    HWFRD:/ $ wm size 1440x2560           // 设置为 1440x2560
    
    HWFRD:/ $ wm size                     // 重新查看
    Physical size: 1080x1920              // 硬件默认值
    Override size: 1440x2560              // 重写输入的值
    
    HWFRD:/ $ wm size reset               // 还原默认值
    
    HWFRD:/ $ wm size                     // 重新查看
    Physical size: 1080x1920              // 已被还原的硬件默认值
    

    屏幕密度

    wm density [reset|DENSITY]
    查看密度:wm density
    修改密度:wm density 480
    还原设置:wm density reset

    测试机:华为 FRD-DL00

    Microsoft Windows [版本 10.0.18363.1500]
    (c) 2019 Microsoft Corporation。保留所有权利。
    
    C:\Users\BigMoom>adb shell
    HWFRD:/ $ wm density                 // 查看
    Physical density: 480                // 返回默认值
    
    HWFRD:/ $ wm density 320            // 设置为 320
    
    HWFRD:/ $ wm density                // 重新查看
    Physical density: 480               // 硬件默认值
    Override density: 320               // 重写输入的值
    
    HWFRD:/ $ wm density reset          // 还原默认值
    
    HWFRD:/ $ wm density                // 重新查看
    Physical density: 480               // 已被还原的硬件默认值
    

    可能遇到的问题

    1. 换了个小米手机测试,发现报了权限错误。

    Security exception: Must hold permission android.permission.WRITE_SECURE_SETTINGS

    dandelion:/ $ wm density 480
    Security exception: Must hold permission android.permission.WRITE_SECURE_SETTINGS
    
    java.lang.SecurityException: Must hold permission android.permission.WRITE_SECURE_SETTINGS
            at com.android.server.wm.WindowManagerService.clearForcedDisplaySize(WindowManagerService.java:5687)
            at com.android.server.wm.WindowManagerShellCommand.runDisplaySize(WindowManagerShellCommand.java:156)
            at com.android.server.wm.WindowManagerShellCommand.onCommand(WindowManagerShellCommand.java:62)
            at android.os.ShellCommand.exec(ShellCommand.java:111)
            at com.android.server.wm.WindowManagerService.onShellCommand(WindowManagerService.java:1191)
            at android.os.Binder.shellCommand(Binder.java:881)
            at android.os.Binder.onTransact(Binder.java:765)
            at android.view.IWindowManager$Stub.onTransact(IWindowManager.java:2574)
            at com.android.server.wm.WindowManagerService.onTransact(WindowManagerService.java:1432)
            at android.os.Binder.execTransactInternal(Binder.java:1021)
            at android.os.Binder.execTransact(Binder.java:994)
    
    咋搞嘞

    莫慌,打开下开发者选项中的**USB调试(安全设置)**就行了。
    develop.png

    其它命令

    有时间可以都看一下,试一试,蛮好玩的。

    HWFRD:/ $ wm
    usage: wm [subcommand] [options]
           wm size [reset|WxH|WdpxHdp]
           wm density [reset|DENSITY]
           wm overscan [reset|LEFT,TOP,RIGHT,BOTTOM]
           wm scaling [off|auto]
           wm screen-capture [userId] [true|false]
    
    wm size: return or override display size.
             width and height in pixels unless suffixed with 'dp'.
    
    wm density: override display density.
    
    wm overscan: set overscan area for display.
    
    wm scaling: set display scaling mode.
    
    wm screen-capture: enable/disable screen capture.
    
    wm dismiss-keyguard: dismiss the keyguard, prompting the user for auth if necessary.
    
    wm surface-trace: log surface commands to stdout in a binary format.
    

    方式二

    说起来巧了,就像前言说的我不知道手机可以改DPI,之前一直是用的开发者模式下的最小宽度修改来测试。后来发现,这个其实也是修改了DPI,仔细想想density和px还有dp的关系,就突然能明白为啥了。

    工具

    手机开发者模式

    准备

    首先得打开手机的开发者模式,咋打开应该不用说了把。
    不知道的小伙伴可以试着去找到你手机的系统版本那里一顿狂点。
    然后就有惊喜了。
    比如:Redmi 9A
    Redmi9A.png

    操作

    咱就直接进入开发者选项里把。
    找到绘图模块下的最小宽度 栏目。
    点开之后直接输入想要的最小宽度就行了。
    注意:这里是以dp为单位的。
    如果你的UI设计图的宽度跟你的手机不符,开发的时候,可以尝试修改这个达到演示的目的。

    如下:Redmi 9A

    Redmi9A(1).png

    效果

    由于输入的是宽度值,无法直观的看到density的变化,但是咱们可以用方式一去验证下,就可以看到它的变化是改了density的值的。

    机型:Redmi 9A

    Microsoft Windows [版本 10.0.18363.1500]
    (c) 2019 Microsoft Corporation。保留所有权利。
    
    C:\Users\Luffy>adb shell
    
    # 修改最小宽度之前,最小宽度360dp
    dandelion:/ $ wm size
    Physical size: 720x1600
    dandelion:/ $ wm density
    Physical density: 320
    
    # 修改最小宽度之后,最小宽度420dp
    dandelion:/ $ wm size
    Physical size: 720x1600
    dandelion:/ $ wm density
    Physical density: 320
    Override density: 274
    

    结语

    可见,在分辨率不变的前提下,修改了最小宽度之后,设备的density发生了变化。

    Android中的dp在渲染前会将dp转为px,计算公式:
    px = density * dp;
    density = dpi / 160;
    px = dp * (dpi / 160);

    参考文献

    原文:https://blog.csdn.net/CrazyApes/article/details/116994631
    参考:https://developer.android.google.cn/guide/practices/screens_support

    展开全文
  • 我们在做UI时候经常遇到这几个概念,但是就是不知道他们之间的关系,这篇文章将会解惑。 像素:显示图像的基本单元,单位px ...屏幕的像素密度=√(分辨率高² + 分辨率宽²)÷ 屏幕尺寸。 例如: ...
  • 屏幕密度与分辨率

    2013-07-19 10:14:49
    屏幕密度与分辨率的关系,用于应用在多屏幕上的适配
  • 这里要特别注意dip与屏幕密度有关,而屏幕密度又与具体的硬件有关,硬件设置不正确,有可能导致dip不能正常显示。在屏幕密度为160的显示屏上,1dip=1px,有时候可能你的屏幕分辨率很大如480*800,但是屏幕密度没有...
  • Android中屏幕密度和图片大小的关系详解 前言 Android中支持许多资源,包括图片(Bitmap),对应于bitmap的文件夹是drawable,除了drawable,还有drawable-ldpi、drawable-mdpi、drawable-hdpi、drawable-xhdpi、...
  • Android屏幕密度

    千次阅读 2015-09-09 18:03:02
    dp、sp、屏幕大小密度参考原文地址:http://blog.csdn.net/zapperbot/article/details/48268721?ref=myread http://blog.csdn.net/sqk1988/article/details/7040953从上表可以得出如下结论 1. 图片放在drawable中...
  • 下面以480dip*800dip的WVGA(density=240dpi)为例,详细列出不同density下屏幕分辨率信息: density=120时 屏幕实际分辨率为240px*400px (两个点对应一个像素) density=160时 屏幕实际分辨率为320px*533px (三个...
  • 在此做笔记方便查看:原文见 :点击打开链接 http://www.chinaz.com/manage/2015/0902/441624.shtml另:关于屏幕的适配:参考文章点击打开链接 http://www.cocoachina.com/android/20151030/13971.html今天我给...
  • Android屏幕密度计算公式

    千次阅读 2018-06-08 16:35:03
    屏幕分辨率1280*1920 屏幕大小 x*y英寸密度dis = 1280/x = 1920/y = (1280*1280 + 1920*1920)开方 / (x*x + y*y)开方 120上下浮动的都属于ldpi160上下浮动的都属于mdpi240上下浮动的都属于hdpi320上下浮动的都属于...
  • 在代码中获取屏幕密度等参数的例子。这是关于在代码中获取屏幕密度等参数的例子,例子也分析了px和dp转换的方法,也就是px = dp * (dpi / 160)。而且我们需要注意的是Android对屏幕密度是使用了归化。
  • Android修改屏幕密度

    千次阅读 2017-09-13 20:07:39
    diff --git a/device/rockchip/rk3288/system.prop b/device/rockchip/rk3288/system.prop index efeb5d3..0c288a8 100644 --- a/device/rockchip/rk3288/system.prop +++ b/device/rockchip/rk3288/system.prop ...
  • 屏幕密度计算公式

    千次阅读 2017-04-21 14:57:52
    屏幕密度的计算
  • 在Android开发中有时会遇到在不同的手机上界面...屏幕密度与DPI这个概念紧密相连,屏幕密度是对每个像素点的缩放比例,DPI全拼是dots-per-inch,即每英寸显示的像素点数。 有种方式可以解决上述问题,即:smallestWi...
  • 移动设备有大有小,那么如何适应不同屏幕呢,这给我们编程人员造成了很多困惑。我也是突然想到这些问题,然后去网上搜搜相关东西,整理如下。首先,对下面这些长度单位必须了解。 Android中的长度单位详解(dp、sp...
  • + + // 加载屏幕密度值 + loadStringSetting(stmt, Settings.Secure.DISPLAY_DENSITY_FORCED, + R.string.display_density_forced); + + // 加载屏幕分辨率 + loadStringSetting(stmt, Settings.Global.DISPLAY_...
  • Android 屏幕密度等级

    2017-03-21 17:43:59
    Android 屏幕密度等级
  • 常用分辨率、屏幕密度对应关系

    千次阅读 2018-08-16 15:11:22
    像素密度等级 像素密度范围 分辨率(通常) 像素密度与dp转换关系 ldpi —dpi-120dpi 320*240 1dp = 0.75px mdpi 120dpi-160dpi 480*320 (Half-size VGA) 1dp = 1px hdpi 160dpi-240dpi 800*...
  • Android 修改屏幕密度

    千次阅读 2016-07-29 11:11:55
    更改屏幕密度,首先要你的系统允许你更改 步骤: cmd 进入命令行 adb shell (已配置环境变量) wm density 120 (后面是密度值) reboot (重启)如图:
  • 原文链接:点击打开链接===============================================================================================在 android 开发中常常会使用到手机屏幕密度和屏幕逻辑尺寸来进行屏幕适配,这里就列出...
  • (1)图片分辨率、图片像素、图片尺寸、屏幕尺寸、屏幕密度(DPI)、输出分辨率的解释 图片分辨率(PPI): 每英寸图像内有多少个像素点。它是摄影机的表述单位,即摄影机的输入分辨率。它描述的是摄影机拍摄...
  • 获取手机屏幕大小,屏幕分辨率,屏幕密度,导航栏高度,标题栏高度
  • 我们之前了解过屏幕的像素密度 dpi,我们身边有很多种类的手机,它们的dpi各不相同,我们如何去适配这些不同的屏幕呢?单位务必使用dp或者sp;dp 是一种非密度制约像素,其尺寸与 160 dpi 像素的实际尺寸相同,即对应...
  • 这是一个允许为 Android 项目中不同屏幕密度自动创建可绘制资源的工具。 依赖项: 珀尔 图像魔术师 我还建议将此脚本放在 $PATH 中包含的目录中,以便更容易调用。 用法 adg [file] [reference size] [--outname...
  • 图片放在某个特定drawable中,比如drawable-hdpi,如果设备的屏幕密度高于当前drawable目录所代表的密度,则图片会被放大,否则会被缩小,放大或缩小比例 = 设备屏幕密度 / drawable目录所代表的屏幕密度 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 35,842
精华内容 14,336
关键字:

屏幕密度