折叠屏为什么需要适配
折叠屏在视觉效果来说就是,屏幕变大了,手机变平板。这样就需要我们的app在可折叠设备展开时,当前应用页面必须无缝延续到另一个屏幕,并可自动调整大小匹配新的布局,也就是说,应用程序需要准备好在多个屏幕(不同分辨率、密度等)之间切换。
折叠屏之所以需要适配,是因为我们的应用有可能在运行的过程中,所在的屏幕尺寸发生了变化,这种情况对现有项目多少都会产生一些问题。
其实这种情况并不是折叠屏出现之后才有的,应用的纵向横向切换也会发生同样的情况,只不过很多应用都强制纵向,不需要处理这种适配了。
折叠屏适配的本质是:当应用运行时,屏幕的尺寸、密度或比例发生了变化,应用能够继续在变化后的屏幕上正常显示和正常运行。
对于开发同学来说,对折叠屏的适配首先要确定一个预期,即要先确定好交互和设计,才能评估工作。因此”折叠屏“的适配先是一个设计问题,然后才是一个适配问题。
<application
android:resizeableActivity="true"//Android7及以上默认开启
折叠屏展开——折叠之后Activity的生命周期,可以发现Activity会销毁后重建
onPause()->onStop()->onDestory()->onCreate()->onStart()->onResume()
如果想禁止Activity销毁重建,则需要在AndroidManifest中对Activity的configChanges进行如下的配置:
<activity
android:configChanges="screenSize|smallestScreenSize|screenLayout"
android:name=".MainActivity"
android:exported="true">
这个时候折叠屏展开——折叠会走Activity#onConfigurationChanged,就不会走activity的生命周期,更新视图布局、重新加载资源。通过此方法既能实现在系统不重启Activity的情况下重置UI。总的来说,折叠屏的适配有点类似平板+旋转屏的综合体,也需要配置文件+多布局。
@Override
public void onConfigurationChanged(@NonNull Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if(FoldableDeviceUtil.INSTANCE.isFold()){//是否有折叠屏
//瀑布流
}
}
package com.example.hilibrary.util
import android.app.Application
import android.os.Build
import android.text.TextUtils
import org.w3c.dom.Text
object FoldableDeviceUtil {
val application: Application? =null
fun isFold():Boolean{
return if(TextUtils.equals(Build.BOARD,"samsung")&&
TextUtils.equals(Build.DEVICE,"Galaxy Z Fold2")){
return HiDisplayUtil.getDisplayWidthInPx(application!!)!=1768
}else if(TextUtils.equals(Build.BOARD,"huawei")&&
TextUtils.equals(Build.DEVICE,"MateX")){
return HiDisplayUtil.getDisplayWidthInPx(application!!)!=2200
}else if(TextUtils.equals(Build.BOARD,"google")&&
TextUtils.equals(Build.DEVICE,"generic_x86")){//模拟器
return HiDisplayUtil.getDisplayWidthInPx(application!!)!=2200
}else{
true
}
}
}
可折叠设备没有android api或回调可以让我们知道当前处于折叠模式还是展开模式。
对于不同尺寸屏幕适配过程中,为了确保在折叠屏各个屏幕形态下获取最佳的布局显示效果,应用界面正确、美观的布局和显示,包含如下:
暗黑模式的适配大概可以分为三部分:
适配的方式也分为三种:自动适配、自定义适配、换肤框架适配
Android 10提供Force Dark功能,此功能可以让开发者快速实现深色主题背景。
<style name="Base.Theme.MyApplication" parent="Theme.Material3.DayNight.NoActionBar">
<!-- Customize your light theme here. -->
<!-- <item name="colorPrimary">@color/my_light_primary</item> -->
<item name="android:forceDarkAllowed" tools:ignore="NewApi" />//添加这句代码即可
</style>
这种方式主要是获取和监听系统深色主题模式的开启状态动态设置主题或皮肤。
App运营者应充分调研并明确业务功能所需的权限,不应申请App不会用到的权限或者一次性申请所有权限,还需要注意区分必要权限和业务所需权限。
App向用户申请权限时未告知目的导致的误会已成为一大痛点,比如,某音乐类App向用户申请存储权限(部分手机在申请该权限会显示是否允许读取照片/视频),用户会疑惑音乐类app为什么要读取照片,而且不同意还不能使用,这不是典型的强制索要无关权限吗?
事实上,此类App申请存储权限是为了音乐下载和离线缓存,和读取照片视频无关,申请权限时做出解释立马真相大白,可见告知申请权限的目的的重要性。
申请权限的弹窗机制在不同手机操作系统上表现不同,比如,在iOS系统中,申请权限的弹窗事实上是可以编辑文字的,如此可很方便地将申请权限的目的在弹窗予以注明。但是Android系统就无法更改,这个是手机厂商写死的。
申请权限弹窗出现前,由App自行以弹窗等形式将需要申请权限的目的予以明确告知
先由系统进行弹窗申请权限,如果用户不理解点击拒绝后,再次弹出提示框向用户告知申请权限的目的
在使用App的过程中,用户选择了“拍照”或“共享位置”功能,App弹窗告知需要获取“拍摄照片和录制视频”等权限,虽未单独再通过弹窗等方式告知申请目的,但完全不影响用户对申请该权限目的的理解。
综上,使用额外弹窗等方式告知申请权限的目的,更多地是针对首次运行App时申请权限的情形,对于用户而言,在首次打开App且未进入主界面前,用户无法看到App的功能界面,无法理解具体的功能需求,因此,在此阶段以增强提示的方式告知申请权限的目的是合规的重点。
从App申请权限的时机来看,通常分为以下三类情形
此外,频繁申请权限(如每次重新打开App便重新索要权限、使用App过程中会反复触发申请权限机制等)造成用户打扰已经成为网友们广泛“诟病”的问题。
新发布的国家标准草案“移动互联网应用 (App)收集个人信息基本规范”给出明确指导性建议,用户明确拒绝使用某服务类型后,App不得频繁 (每48小时不超过一次)征求用户同意使用该类型服务,并保证其他服务类型正常使用。
总之,申请权限的时机和方式,与用户体验紧密相关,建议App运营者全面考虑各种要素,优化App中请权限过程,不要让申请权限过程变得别扭、将就,最终影响的是用户对App的印象和用户的转化率。
权限是手机个人信息的一扇窗户,一旦窗户打开,手机个人信息的行为随时可能发生。而对于用户来讲,调用权限相关函数获取个人信息的过程无法感知,心里没底。这就可能会导致出现以下超出合理频率范畴过度采集个人信息的行为。
在用户未使用某业务功能时,就已经发生调用权限收集与该业务功能相关个人信息的行为。
用户在首次开启App时开启了“通讯录”、“短信”等权限,用户并未使用涉及该权限的功能,仅是浏览主界面,便出现了调用权限相关函数上传个人信息的行为。
调用权限收集个人信息的频次明显超出实现业务功能所需。
比如开启位置权限实现查询当地天气的功能,但实际App每秒都获取并上传用户的精准位置。
当App在静默或后台运行时,仍存在不断调用权限收集个人信息的行为。
事实上,以上不规范的调用权限方式均可以使用技术手段进行监测,建议App运营者详尽分析自身业务功能所需调用权限的具体频率,必要时,还可以在隐私政策等向用户直接说明。
众所周知,手机操作系统自身已经为用户提供了开启、关闭权限的控制机制。但是,从用户体验来看,在安装大量App后,使用该机制查询权限开启情况或改变权限设置等操作变得不太方便。此外,很多平台型APP上存在大量第三方应用或服务也涉及到调用权限的问题,但手机操作系统并未提供额外的控制机制。建议App运营者进一步考虑用户对于权限的控制需要,优化和创新用户对权限的控制机制。比如,某App专门在其"隐私设置”中设置了方便查询权限开启情况的交互式页面,并提供简单易懂可迅速切换至权限控制页面的通道。