Android屏幕适配

屏幕适配

原因:Android设备碎片化,导致APP的界面元素在不同的屏幕尺寸上显示不一致。

目的:让布局,布局组件,资源,用户界面流程,匹配不同的屏幕尺寸。

屏幕适配常见方式

  • 布局适配

1、避免写死控件尺寸,使用match_parent,wrap_content。

2、LinearLayout使用android:layout_weight=“1”,android:weightSum="4"等等。

3、RelativeLayout的android:layout_centerInParent=“true”,

android:layout_centerVertical=“true”,android:layout_centerHorizontal=“true”

4、ConstraintLayout(RelativeLayout的加强版,更强大的功能)

5、百分比库

  • 图片资源适配

1、使用.9或者svg图实现缩放

2、使用多套位图匹配不同的屏幕分辨率

  • 用户流程适配

1、根据业务逻辑执行不同的跳转逻辑

2、根据别名展示不同的界面

  • 限定符适配

1、分辨率限定符mipmap-hdpi,drawable-hdpi等等

2、尺寸限定符:layout-small,layout-large等

3、最小宽度限定符:values-sw360dp,values-sw480dp等

4、屏幕方向限定符:layout-land,layout-port等

  • 刘海屏适配

Android 9.0官方适配

华为、OPPO、VIVO,、小米等等

一、像素适配

自定义像素适配,自定义View来适配

以一个特定宽度尺寸的设备为参考,在View的加载过程中,根据当前设备的实际像素换算出目标像素,再作用在控件上。

  • 工具类,计算屏幕宽高,求出目标View和参考图的缩放比

STANDARD_WIDTH

STANDARD_HEIGHT

mScreenWidth

mScreenHeight

mInstance

context

mInstance

mInstance

mInstance context

mInstance

context

mScreenHeight mScreenWidth

wm contextWINDOW_SERVICE

wm

metrics

wmmetrics

metricswidthPixels metricsheightPixels

mScreenWidth metricsheightPixels

mScreenHeight metricswidthPixels

mScreenWidth metricswidthPixels

mScreenHeight metricsheightPixels context

context

resId context

resId

contextresId

mScreenWidth STANDARD_WIDTH

mScreenHeight STANDARD_HEIGHT

  • 适配的ViewGroup,在onMeasure中根据缩放比,重新去计算目标View的宽高

* 是否被测量

isMeasure

context

context

context attrs

context attrs

context attrs defStyleAttr

context attrs defStyleAttr

widthMeasureSpec heightMeasureSpec

isMeasure

horizontalScale

verticalScale

childCount

i i childCount i

child i

params child

paramswidth paramswidth horizontalScale

paramsheight paramsheight horizontalScale

paramsleftMargin paramsleftMargin horizontalScale

paramsrightMargin paramsrightMargin horizontalScale

paramstopMargin paramstopMargin verticalScale

paramsbottomMargin paramsbottomMargin verticalScale

widthMeasureSpec heightMeasureSpec

布局文件

xmlnsandroid

androidorientation

androidlayout_width

androidlayout_height

androidlayout_width

androidlayout_height

androidbackground

自定义View像素适配,不能穿透适配,也就是当前容器是像素适配容器,它其中如果还有容器需要适配,也依然要使用像素适配容器。造成的结果就是如果需求更改,会改的很惨。O(∩_∩)O哈哈~。

二、百分比布局适配

自定义百分比适配,继承对应的ViewGroup,在使用百分比适配的情况下,不影响ViewGroup本身的属性的使用。

Google本身提供了百分比库,我们正常情况下需要使用直接导入Google的百分比库就好。

以下例子我们直接继承RelativeLayout,在

  • onMeasure()中去重新计算我们的宽高。

  • 继承RelativeLayout的LayoutParams,实现以下构造方法LayoutParams(Context c, AttributeSet attrs),在构造方法中去获取我们自定义属性,这个可以参考RelativeLayout本身的实现。

  • 实现generateLayoutParams,将我们自己的LayoutParams返回

context

context

context attrs

context attrs

context attrs defStyleAttr

context attrs defStyleAttr

widthMeasureSpec heightMeasureSpec

parentWidth widthMeasureSpec

parentHeight heightMeasureSpec

childCount

i i childCount i

child i

layoutParams child

layoutParams

params layoutParams

widthPercent paramswidthPercent

heightPercent paramsheightPercent

marginLeftPercent paramsmarginLeftPercent

marginRightPercent paramsmarginRightPercent

marginTopPercent paramsmarginTopPercent

marginBottomPercent paramsmarginBottomPercent

widthPercent

paramswidth parentWidth widthPercent

heightPercent

paramsheight parentHeight heightPercent

marginLeftPercent

paramsleftMargin parentWidth marginLeftPercent

marginRightPercent

paramsrightMargin parentWidth marginRightPercent

marginTopPercent

paramstopMargin parentHeight marginTopPercent

marginBottomPercent

paramsbottomMargin parentHeight marginBottomPercent

widthMeasureSpec heightMeasureSpec

attrs

attrs

p

p

widthPercent

heightPercent

marginLeftPercent

marginRightPercent

marginTopPercent

marginBottomPercent

c attrs

c attrs

typedArray cattrs styleablePercentRelativeLayout

widthPercent typedArraystyleablePercentRelativeLayout_widthPercent

heightPercent typedArraystyleablePercentRelativeLayout_heightPercent

marginLeftPercent typedArraystyleablePercentRelativeLayout_marginLeftPercent

marginRightPercent typedArraystyleablePercentRelativeLayout_marginRightPercent

marginTopPercent typedArraystyleablePercentRelativeLayout_marginTopPercent

marginBottomPercent typedArraystyleablePercentRelativeLayout_marginBottomPercent

typedArray

具体使用

xmlnsandroid

xmlnstools

xmlnsapp

androidorientation

androidlayout_width

androidlayout_height

androidlayout_width

androidlayout_height

androidbackground

androidtextSize

androidtext

appwidthPercent

appheightPercent

androidgravity

我们设置的百分比都是相对于父容器的,相对于父容器的宽度百分比,高度百分比

在这里插入图片描述

三、修改像素密度

我最早知道是今日头条开放出来的,具体可以参考

字节跳动:一种极低成本的Android屏幕适配方式

修改density(屏幕密度),scaleDensity(一般用于字体,通常情况下与density相等),densityDpi(屏幕上每一英寸的像素点)的值,直接更改系统内部对于目标尺寸而言的像素密度。


android中的dp在渲染前会将dp转为px,计算公式:

  • px = density * dp;
  • density = dpi / 160;
  • px = dp * (dpi / 160);

而dpi是根据屏幕真实的分辨率和尺寸来计算的,每个设备都可能不一样的。


具体工具类

就是根据设计稿去修改目标Activity的Density等值

* 设计稿宽度(dp)

DEFAULT_WIDTH

appDensity

appScaleDensity

application activity

displayMetrics application

appDensity

appDensity displayMetricsdensity

appScaleDensity displayMetricsscaledDensity

application

newConfig

newConfig newConfigfontScale

appScaleDensity applicationscaledDensity

targetDensity displayMetricswidthPixels DEFAULT_WIDTH

targetScaleDensity targetDensity appScaleDensity appDensity

targetDensityDpi targetDensity

dm activity

dmdensity targetDensity

dmscaledDensity targetScaleDensity

dmdensityDpi targetDensityDpi

工具类具体调用在Activity的onCreate()的setContentView()方法之前。可以在每个Activity单独设置,也可以在BaseActivity中设置,或者在Application实现Activity的监听。

Application的onCreate()中监听,自己实现一个BaseApplication继承Application。

activity savedInstanceState

activity

activity

activity

activity

activity

activity outState

activity

布局文件,我们适配稿给的360dp的宽度,所以我们分别对两个控件设置180dp,实际适配之后结果应该是平分屏幕宽度。

xmlnsandroid

xmlnstools

xmlnsapp

androidlayout_width

androidlayout_height

androidid

androidlayout_width

androidlayout_height

androidbackground

androidtextSize

androidtext

applayout_constraintTop_toTopOf

applayout_constraintStart_toStartOf

androidgravity

androidid

androidlayout_width

androidlayout_height

androidbackground

androidtextSize

androidtext

applayout_constraintTop_toBottomOf

applayout_constraintStart_toEndOf

androidgravity

效果对比,适配前和适配后:

在这里插入图片描述

最后,各种适配方式没有什么是最好的,合适的才是最好的,有句话怎么说的(不适配就是最好的适配),哈哈。平时的适配根据具体项目具体选择采用什么样的适配方式。还有我们可以选择对整体界面适配也可以对单独的某一块进行适配。

四、刘海屏适配

Android 9.0官方适配方式

  • 如果非全屏模式(有状态栏),则APP不受刘海屏影响,刘海屏的高度就是状态栏的高度。
  • 如果是全屏模式,APP未适配刘海屏,系统会对界面做特殊处理,竖屏向下移动,横屏向右移动。

其他手机厂商的适配:

官方适配方案

日常适配刘海屏,我们需要对厂商的版本单独处理,很多厂商都有他们自己的适配方式。比如华为,小米,OPPO等。

1、取消标题栏,设置全屏

2、判断手机厂商

3、判断手机是否有刘海

4、设置是否让内容区域延伸进刘海

5、设置控件是否避开刘海区域

6、获取刘海的高度(一般就是状态栏的高度)

设置全屏,设置内容延伸至刘海等操作都是在setContentView()方法之前

override fun savedInstanceState

savedInstanceState

FEATURE_NO_TITLE

window

FLAG_FULLSCREEN

FLAG_FULLSCREEN

window

val attributes windowattributes

* LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT 全屏模式,内容下移,非全屏不受影响

* LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES 允许内容去延伸进刘海区

* LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER 不允许内容延伸进刘海区

VERSIONSDK_INT

attributeslayoutInDisplayCutoutMode

LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES

windowattributes attributes

val flags

SYSTEM_UI_FLAG_FULLSCREEN or SYSTEM_UI_FLAG_HIDE_NAVIGATION or SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN

systemUiVisibility windowdecorViewsystemUiVisibility

systemUiVisibility systemUiVisibilityflags

windowdecorViewsystemUiVisibility systemUiVisibility

layoutactivity_shaped_screen

val layoutParams

tvShapelayoutParams as

layoutParamstopMargin

tvShapelayoutParams layoutParams

* 判断是否是刘海屏

fun window

val displayCutout

val decorView windowdecorView

VERSIONSDK_INT

val rootWindowInsets decorViewrootWindowInsets

VERSIONSDK_INT rootWindowInsets

displayCutout rootWindowInsetsdisplayCutout

displayCutout

displayCutoutboundingRectssize displayCutoutsafeInsetBottom

* 获取状态栏高度(通常情况下,刘海的高度等于状态栏的高度)

fun

val resId resources

resId

resourcesresId

五、单独适配

对需要适配的布局进行单独适配,相对来说更麻烦,但是效果也是最好的。

  1. 跟屏幕相关的缩放比,水平,竖直高度的工具类

instance

DEFAULT_WIDTH

DEFAULT_HEIGHT

displayMetricsWidth

displayMetricsHeight

mStatusBarHeight

context

wm contextWINDOW_SERVICE

wm

displayMetrics

displayMetricsWidth displayMetricsHeight

wmdisplayMetrics

mStatusBarHeight context

displayMetricswidthPixels displayMetricsheightPixels

displayMetricsWidth displayMetricsheightPixels

displayMetricsHeight displayMetricswidthPixels

displayMetricsWidth displayMetricswidthPixels

displayMetricsHeight displayMetricsheightPixels

context

instance

instance

instance context

instance

instance

instance

* 水平缩放比

*

displayMetricsWidth DEFAULT_WIDTH

* 竖直缩放比

*

displayMetricsHeight DEFAULT_HEIGHT

* 获取宽度

width

width displayMetricsWidth DEFAULT_WIDTH

* 获取高度

height

height displayMetricsHeight DEFAULT_HEIGHT

* 用于得到状态框的高度

context

resourceId context

height contextresourceId

height

height

context

context dimeClass system_bar_height defaultValue

clazz dimeClass

object clazz

field clazzsystem_bar_height

obj fieldobject

obj defaultValue

id obj

contextid

e

e

defaultValue

  1. 对单独布局进行适配的工具类

* 设置字体大小

*

textView size

textViewCOMPLEX_UNIT_PX size

view width height lefMargin topMargin

rightMargin bottomMargin asWidth

layoutParams view

layoutParams

width MATCH_PARENT

width WRAP_CONTENT

layoutParamswidth width

layoutParamswidth width

height MATCH_PARENT

height WRAP_CONTENT

layoutParamsheight asWidth height height

layoutParamsheight height

layoutParamstopMargin asWidth topMargin topMargin

layoutParamsbottomMargin asWidth bottomMargin bottomMargin

layoutParamsleftMargin lefMargin

layoutParamsrightMargin rightMargin

viewlayoutParams

* 设置view的内边距

*

view topPadding bottomPadding leftPadding rightPadding

viewleftPadding

topPadding

rightPadding

bottomPadding

view width height topMargin bottomMargin lefMargin

rightMargin asWidth

layoutParams view

width MATCH_PARENT

width WRAP_CONTENT

layoutParamswidth width

layoutParamswidth width

height MATCH_PARENT

height WRAP_CONTENT

layoutParamsheight asWidth height height

layoutParamsheight height

layoutParamstopMargin asWidth topMargin topMargin

layoutParamsbottomMargin asWidth bottomMargin bottomMargin

layoutParamsleftMargin lefMargin

layoutParamsrightMargin rightMargin

viewlayoutParams

view width height topMargin bottomMargin lefMargin

rightMargin asWidth

layoutParams view

width MATCH_PARENT width WRAP_CONTENT

layoutParamswidth width

layoutParamswidth width

height MATCH_PARENT height WRAP_CONTENT

layoutParamsheight asWidth height height

layoutParamsheight height

layoutParamstopMargin asWidth topMargin topMargin

layoutParamsbottomMargin asWidth bottomMargin bottomMargin

layoutParamsleftMargin lefMargin

layoutParamsrightMargin rightMargin

viewlayoutParams

view width height asWidth

layoutParams view

width MATCH_PARENT width WRAP_CONTENT width FILL_PARENT

layoutParamswidth width

layoutParamswidth width

height MATCH_PARENT height WRAP_CONTENT height FILL_PARENT

layoutParamsheight asWidth height height

layoutParamsheight height

viewlayoutParams

以上是 Android屏幕适配 的全部内容, 来源链接: www.h5w3.com/android/755765.html

回到顶部