Blankj / AndroidUtilCode

:fire: Android developers should collect the following utils(updating).
https://blankj.com/2016/07/31/android-utils-code/
Apache License 2.0
33.32k stars 10.69k forks source link

屏幕适配问题汇总及解决 #597

Closed Blankj closed 5 years ago

Blankj commented 6 years ago

适配的原理及怎么适配?

Android 屏幕适配从未如斯简单(8月10日最终更新版),由于文章写的较早,请用 1.19.2 版本及以上来完美适配。

如何创建 mdpi 1080 * 1920 设备的预览图?

创建新的模拟器设备,然后修改分辨率和屏幕尺寸使其达到 mdpi 即可。

App 进入后台一段时间再进入导致适配失效?

由于进入后台可能会触发 onDestroy,导致取消了适配,从而再次进入 App 的时候可能会出现适配失效。如果是所有页面都需要适配,那就不需要在 onDestroy 里做取消适配;如果某些页面不需要适配,那就在它 setContentView 之前取消适配即可。

webview 加载后发现 density 复原?

由于 WebView 初始化的时候会还原 density 的值导致适配失效,继承 WebView,重写如下方法:

@Override
public void setOverScrollMode(int mode) {
    super.setOverScrollMode(mode);
    ScreenUtils.restoreAdaptScreen();
}

如何让系统 View 尺寸正常?

后面提到的 Dialog 和 Toast 其实都可以用用这种解决方案,就是在 inflate 相关 View 之前调用 ScreenUtils#cancelAdaptScreenshow 之后调用 ScreenUtils#restoreAdaptScreen 即可,这样就可以让系统 View 显示正常尺寸。

显示 dialog 尺寸有问题?

如果你适配传入的不是 mdpi 下的尺寸,而是 xxhdpi,那么可能会导致 AlertDialog 跑到屏幕外边,所以在文章中我也提到了只用 mdpi 来适配,正常情况的 mdpi 是会呈现比较小的尺寸,如果你要取得和原生一致的效果,那就利用上面提到的「如何让系统 View 尺寸正常」封装下在 Dialog 显示前调用 ScreenUtils#cancelAdaptScreen,Dismiss 后根据需求看是否需要 ScreenUtils#restoreAdaptScreen;或者你也可以给 Dialog 定制统一的 styles 来解决尺寸(<item name="android:windowMinWidthMinor">576dp</item> <!-- 占 80% 屏宽 720 * 0.8 = 576 -->)、字体的问题。当然,如果项目组有封装好的 Dialog,那么统一修改这个 Dialog 库的尺寸即可。

Toast 尺寸有问题?

使用 1.19.1 及以上版本的 ToastUtils 来显示 Toast 不会有这个问题(解决之道就是上面提到的「如何让系统 View 尺寸正常」),当然你也可以自己封装不用我的 ToastUtils;或者参照 CustomToast 来自定义 Toast 布局。

更大尺寸的设备想要显示更多的内容?

可以使用 sw 的方案来解决尺寸更大的设备可以显示更多的内容,本方案和 sw 并没有冲突,所以如果你需要在全面屏或者大屏设备显示更多的内容可以创建新的 dimens 来解决,这样就可以做到在某一尺寸范围内的设备显示效果都一致,解决了某些人总是口口声声说「更大的屏幕就应该获取更多的信息啊」。

zofnk commented 6 years ago

webview 加载后发现 density 复原?这个问题也出现在另外一个使用pt单位适配方案的库,它的解决方案是: https://github.com/Firedamp/Rudeness/issues/14

Power-Android commented 6 years ago

使用后适配后Tosat字体过小的问题

Blankj commented 6 years ago

@Power-Android 已解决,见上面

i11m20n commented 6 years ago

image 问题:界面适配失败 操作流程:进入主页(后台定时刷新TextView)->定时结束前进入任务管理页(预感定时结束)->回到APP内(适配失败)

Blankj commented 6 years ago

@jacksPeak 你要是每个 Activity 都需要适配的话就不需要在 onDestroy 里取消适配了,可能是因为你中途某个 Activity 触发了取消适配,导致进来后布局适配为从前的了。

我推测是这个原因,如果你可以复现的话可以查看相关生命周期,并检测 isAdaptScreen,或者录个 gif 给我看下现象方便我更好地来分析,如果你已经解决了,方便的话烦请你说下解决之道。

i11m20n commented 6 years ago

@Blankj 按照你的方式在onDestroy里删除了取消适配的代码问题已解决,不过正在查找ToolBar显示过小的解决方案..

Blankj commented 6 years ago

@jacksPeak toolbar height 不是可以自己写么

i11m20n commented 6 years ago

@Blankj 是的,自定义的高度没有问题,但若使用?android:attr/actionBarSize就会出问题

Blankj commented 6 years ago

@jacksPeak 你那样写设置的就是系统的高度啊,比如 48dp,可能就会比较小啊,就和你用 toast 也会比较小一样。

MrLeeys commented 6 years ago

进入第三方 横屏Activity界面,退出后,原界面失效

Blankj commented 6 years ago

@MrLeeys 偶现还是必现?你代码里有调用 cancelAdaptScreen 吗?

hjysmi commented 6 years ago

@Blankj 在使用上滑RecyclerView折叠toolbar时,发现toolbar无法适配,而且返回菜单和title会被statusBar遮挡。

Blankj commented 6 years ago

@hjysmi 什么叫 toolbar 无法适配,返回菜单和title会被statusBar遮挡,那么费劲描述还不如上个图不就好了么

hjysmi commented 6 years ago

@Blankj 不好意思,之前不会上传图片。请帮忙check一下

toolbar oncreate ` <android.support.design.widget.AppBarLayout android:id="@+id/appbar" android:layout_width="match_parent" android:layout_height="500dp" android:fitsSystemWindows="true">

    <android.support.design.widget.CollapsingToolbarLayout
        android:id="@+id/collapsing_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true"
        app:contentScrim="@color/white"
        app:expandedTitleMarginEnd="64dp"
        app:expandedTitleMarginStart="48dp"
        app:layout_scrollFlags="scroll|exitUntilCollapsed"
        app:statusBarScrim="@color/white">

        <ImageView
            android:id="@+id/image"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true"
            android:scaleType="centerCrop"
            android:src="@drawable/timg"
            app:layout_collapseMode="parallax" />
        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="90dp"
            app:layout_collapseMode="pin"
            app:navigationIcon="?attr/homeAsUpIndicator" />
    </android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>`
Blankj commented 6 years ago

toolbar 设置:android:minHeight="90dp" 可以使图标居中,自己搜索解决哈

hjysmi commented 6 years ago

@Blankj 发现无法适配android.support.design.widget.TabLayout,经测试3个以及以上可以,2个就会出现这个问题 20180917170649 20180917170346

Chen-Sir commented 6 years ago

@Blankj 看了你的文章,我有一个地方有点疑惑。您文章中以下这段话: 由于 API 26 及以上的 Activity#getResources()#getDisplayMetrics() 和 Application#getResources()#getDisplayMetrics() 是不同的引用,所以在 API 26 及以上适配是没有影响的,但在 API 26 以下 Activity#getResources()#getDisplayMetrics() 和 Application#getResources()#getDisplayMetrics() 是相同的引用,导致适配有问题,这里要感谢 @MirkoWu 提出的问题,后面会有解决方案。 我想问下,在API26以下因为引用相同,适配有问题。是什么问题?

775311653 commented 6 years ago

s80927-160945 2

直接用ToastUtils.showShort("网络异常,请稍后再试!"); 会显示异常。 而如果在代码里面先执行了ScreenUtils.cancelAdaptScreen(); 就正常显示了。 Util版本1.20.3 20180927161541

BradyXs commented 6 years ago

直接用ToastUtils.showShort("你输了,请再接再厉!"); 会显示异常。 而如果在代码里面先执行了ScreenUtils.cancelAdaptScreen(); 就正常显示了。

Blankj commented 6 years ago

@BradyXuBin 因为 toast 布局也被适配了哈,所以要取消掉。这个适配不太好,过两天我会出一种比现在市面上都完美的适配。

Maxitk commented 5 years ago

抱歉打扰一下,我用的版本是1.1.2,有个很奇怪的问题,当我点击桌面的app(已经在第一个Activity做了适配),此时在0.5s以内马上锁屏,再打开,界面全部变形,请问问朋友有没有遇到过这个情况,是如何解决的

Blankj commented 5 years ago

用最新的适配吧,在我 blankj.com 第一篇文章