现在折叠屏手机出了也有一段时间了,但是除了大厂app,其他app适配折叠屏还是比较少,如果真的想做好折叠屏完全适配,那这个文章可能并不适合,这里只是一个简单适配的思路。
如果原先你的app已经适配了平板,那其实折叠屏和平板差不多,估计你调整一下应用,让活动在折叠、展开时不要重启应该就大差不差了,或者折叠、展开时让app重启,这时会根据屏幕大小选择合适的布局,其实也是一种选择,约摸着也不用花太多功夫。
但是如果好死不死,原先没适配平板,但是老板脑子一热,想适配一下折叠屏,那我这里提供一个权宜之计。(这个是不推荐的做法,如果有能力最好还是照android官方文档和一些对应厂商的开发文档做一下适配)
思路也很简单:监听折叠状态,改变对应布局
首先第一步导依赖,参考官方的文档
WindowManager | Jetpack | Android Developers
在app的build.gradle添加依赖
dependencies {
implementation "androidx.window:window:1.3.0"
implementation "androidx.window:window-java:1.3.0"
}
第二步,在需要根据折叠状态改变布局的活动,设置其改变不重启,AndroidManifest.xml里面找到对应活动,改一下它的configChanegs,这个应该都会
<activity
android:name=".activities.MediaPlayerActivity"
android:configChanges="keyboardHidden|orientation|screenSize|uiMode|
locale|layoutDirection|screenLayout|smallestScreenSize"
android:launchMode="singleTop"
android:hardwareAccelerated="true"
android:screenOrientation="portrait" />
加了screenLayout和smallestScreenSize这两个,后面折叠状态改变时在对应活动的onConfigurationChanged变更布局和一些其他操作
下面说一下如何监听,参考官方文档
让应用具备折叠感知能力 | Jetpack Compose | Android Developers
在活动onCreate时添加折叠状态监听器
WindowInfoTracker windowInfoTracker = WindowInfoTracker.getOrCreate(this);
WindowInfoTrackerCallbackAdapter windowInfoTrackerCallbackAdapter = new
WindowInfoTrackerCallbackAdapter(windowInfoTracker);
//添加折叠屏切换监听
windowInfoTrackerCallbackAdapter.addWindowLayoutInfoListener(this, Runnable::run,
windowLayoutInfo -> {
runOnUiThread(() -> {
List<DisplayFeature> displayFeatures = windowLayoutInfo.getDisplayFeatures();
if(displayFeatures.size() == 0){ //单屏状态(折叠) 或者非折叠屏手机
Log.d(TAG,"单屏/非折叠");
//现在是折叠状态,将折叠状态设置到全局变量,onConfigurationChanged使用
setFoldState(0); //明白意义就行,需要自己实现相关逻辑
}
//展开状态 可能是半折/展开
for(DisplayFeature feature : displayFeatures){
if(feature instanceof FoldingFeature) {
//半折叠
if ( ((FoldingFeature) feature).getState() ==
FoldingFeature.State.HALF_OPENED) {
Log.d(TAG, "半折叠");
//现在是半折叠状态,将折叠状态设置到全局变量,onConfigurationChanged使用
setFoldState(1);
}
//平的(全展开)
else if ( ((FoldingFeature) feature).getState() ==
FoldingFeature.State.FLAT) {
Log.d(TAG, "完全展开");
//现在是完全展开状态,将折叠状态设置到全局变量,onConfigurationChanged使用
setFoldState(2);
}
}
}
});
});
onConfigurationChanged中根据折叠状态实现业务逻辑
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
....
int foldState = getFoldState(); //获取折叠状态
switch(foldState){ //根据折叠状态实现对应逻辑
case 0:
.....
}
}
除此之外,在设备不是折叠屏时我们可以不添加监听,这个判断方法根据不同厂商也会有不同,目前我只验了荣耀magic V2,其他就不确定行不行了。
建议这个判断在应用的application.java里面做,判断后写到全局变量方便后续使用
//判断是否折叠屏手机
Log.d(TAG, "手机品牌= " + Build.MANUFACTURER);
// 华为 "Huawei" 荣耀 "HONOR" 华为NOVA "nova" 小米 "xiaomi" vivo "vivo"
// 魅族 "Meizu" 索尼 "sony" 三星 "samsung" OPPO "OPPO" 乐视 "letv"
// 一加 "OnePlus" LG "lg" 锤子 "smartisan" 联想 "lenovo" HTC "htc"
if (Build.MANUFACTURER.equalsIgnoreCase("HONOR") //荣耀折叠屏
&& getPackageManager() != null
&& getPackageManager().hasSystemFeature("com.hihonor.hardware.sensor.posture")) {
sIsFoldableDevice = true; //全局变量,是否为折叠屏手机,设置true
}
else if (Build.MANUFACTURER.equalsIgnoreCase("VIVO")){ //vivo折叠屏
Class<?> c= null;
try {
c = Class.forName("android.util.FtDeviceInfo");
Method m = c.getMethod("getDeviceType");
Object dType = m.invoke(c);
sIsFoldableDevice = "foldable".equals(dType);
} catch (Exception e) {
Log.d(TAG,e.toString());
}
}
else if(Build.MANUFACTURER.equalsIgnoreCase("xiaomi")){ //小米折叠屏
Class c = null;
try {
c = Class.forName("android.os.SystemProperties");
Method m = c.getMethod("getInt",String.class, int.class);
int type = (int) m.invoke(c,"persist.sys.muiltdisplay_type", 0);
sIsFoldableDevice = (type == 2);
} catch (Exception e) {
Log.d(TAG,e.toString());
}
}
else if (Build.MANUFACTURER.equalsIgnoreCase("OPPO") ){ //oppo折叠屏
try {
Class<?> cls = Class.forName("com.oplus.content.OplusFeatureConfigManager");
Method instance = cls.getMethod("getInstance");
Object configManager = instance.invoke(null);
Method hasFeature = cls.getDeclaredMethod("hasFeature", String.class);
Object object = hasFeature.invoke(configManager, "oplus.hardware.type.fold");
if (object instanceof Boolean) {
sIsFoldableDevice = (boolean) object;
}
} catch (Exception e){
Log.d(TAG,e.toString());
}
}
else if (Build.MANUFACTURER.equalsIgnoreCase("HUAWEI") ) { //华为折叠屏
sIsFoldableDevice = getPackageManager().hasSystemFeature(
"com.huawei.hardware.sensor.posture");
else { //其他厂商
DisplayManager displayManager = (DisplayManager)
getSystemService(Context.DISPLAY_SERVICE);
Display[] displays = displayManager.getDisplays();
for (Display display : displays) {
if (display.getName().contains("Foldable")) {
// 判断为折叠屏
sIsFoldableDevice = true;
break;
}
}
}
Log.d(TAG, sIsFoldableDevice + "");