最近负责了项目中平板适配工作,总结了一些相关方法记录下来
方法介绍
1、判断是否是平板设备
官方给出的方法如下
public static boolean isTabletDevice(Context context) {
return (context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >=
Configuration.SCREENLAYOUT_SIZE_LARGE;
}
但是这个方法在极少机型上也有不准确的时候,另一种方法是根据屏幕的尺寸判断
public static boolean isPadDevice(Context context) {
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
DisplayMetrics dm = new DisplayMetrics();
display.getMetrics(dm);
double x = Math.pow(dm.widthPixels / dm.xdpi, 2);
double y = Math.pow(dm.heightPixels / dm.ydpi, 2);
double screenInches = Math.sqrt(x + y); // 屏幕尺寸
return screenInches >= 7.0;
}
但是随着手机屏幕越来越大,这个方法也可能不准确了。
2、判断是否在平行视界(平行窗口)
有时候我们需要判断当前的横竖屏状态来决定使用哪种布局,但是有些平板设备横屏使用时,是平行视界模式,这是应该使用的是竖屏布局,所以也要判断一下是否在平行世界模式
public static boolean isMagicWindow(Context context){
String confString = context.getResources().getConfiguration().toString();
return confString.contains("hwMultiwindow-magic") || confString.contains("miui-magic-windows") || confString.contains("hw-magic-windows");
}
上面仅仅是华为和小米平板,为了普遍性,可以改成
public static boolean isMagicWindow(Context context){
String confString = context.getResources().getConfiguration().toString();
// return confString.contains("hwMultiwindow-magic") || confString.contains("miui-magic-windows") || confString.contains("hw-magic-windows");
// 上面的两种方法只能判断小米和华为,下面这种写法应该更普遍一些
return confString.contains("magic-window") || confString.contains("window-magic");
}
小米平行世界提供了关闭的方法,让程序默认横屏进入
<!-- 小米不进入平行视窗模式-->
<meta-data
android:name="LandscapeForPad"
android:value="true" />
3、获取窗口和设备大小
只有一个应用显示时,应用所在的窗口大小和屏幕大小是一样的,但是在分屏或者平行视界模式下,应用窗口的大小和设备的大小不一致。
-
获取窗口大小
int widthPixels = context.getApplicationContext() .getResources().getDisplayMetrics().widthPixels; int heightPixels = context.getApplicationContext() .getResources().getDisplayMetrics().heightPixels;
-
获取设备大小
平行视界种该方法不准确,得到的还是应用窗口大小
/** * 获取设备的物理宽 * @param context * @return */ public static int getPhysicsWidth(Context context){ WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); Display display; if (Build.VERSION.SDK_INT >= 30){ display = context.getDisplay(); } else { display = windowManager.getDefaultDisplay(); } DisplayMetrics mMetrics = new DisplayMetrics(); display.getRealMetrics(mMetrics); return mMetrics.widthPixels; }
4、是否处于分屏模式
在activity中,重写onMultiWindowModeChanged方法,在进入分屏模式时会被回调到
@Override
public void onMultiWindowModeChanged(boolean isInMultiWindowMode) {
super.onMultiWindowModeChanged(isInMultiWindowMode);
}
或者还可以直接通过mActivity.isInMultiWindowMode()方法判断是否处于多窗口模式。
5、旋转时不重建activity
很多时候旋转屏幕我们都不希望重建activity,通过在AndroidManifest.xml中可以配置为
android:name=".module.course.flutter.FCourseDetailActivity"
android:configChanges="keyboardHidden|orientation|screenSize|screenLayout"
同样重写onConfigChanges方法可以接收到回调。
7、手机禁止旋转,pad允许旋转
很多页面禁止手机旋转,但是允许pad旋转到横屏展示更多的内容,要让我们的应用满足这种要求,就必须去先掉原先的横竖屏配置
<activity
android:name=".commonview.activity.TransparentActivity"
android:screenOrientation="portrait"
android:theme="@style/transparent_activity" />
因为在manifest中,我们是没法判断当前是pad还是手机的,也不能说创建两个配置文件分别给平板和手机使用。
-
方法一
Activity提供了一个方法setRequestedOrientation()来控制屏幕旋转,如果当前是竖屏,我们再次调用setRequestedOrientation()旋转到竖屏的话,屏幕不会变化,也不会闪屏,但是相当于告诉了系统,我这个界面要始终保持竖屏,以后就忽略重力感应吧,只有调用setRequestedOrientation()才会发生旋转。于是我们可以进入界面时判断一下如果是手机的话就将其旋转到竖屏。
-
方法二
配置screenOrientation所有可选参数如下
unspecified,默认值,由系统决定,不同手机可能不一致
landscape,强制横屏显示
portrait,强制竖屏显
behind,与前一个activity方向相同
sensor,根据物理传感器方向转动,用户90度、180度、270度旋转手机方向,activity都更着变化
sensorLandscape,横屏旋转,一般横屏游戏会这样设置
sensorPortrait,竖屏旋转
nosensor,旋转设备时候,界面不会跟着旋转。初始化界面方向由系统控制
user,用户当前设置的方向
这里也可以设置为behind来保持和上一个activity相同,从而禁止旋转,但是这种方式可能达不到我们的需要。
实例分享
1、手机和平板如何设置不同的封面
app启动页如果不设置背景,会有一个白屏的效果,通常我们会在启动页的主题中配置上的背景图片,例如
<style name="AppWindowBackgroudSplash" parent="android:Theme.NoTitleBar">
<item name="android:windowBackground">@drawable/starting_bkg</item>
<item name="android:windowAnimationStyle">@style/noAnimation</item>
<item name="android:windowFullscreen">true</item>
</style>
通过设置windowBackground属性可以设置背景图片,文字等显示效果,这里我们使用一个layer-list来实现文字和图片重叠显示
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<solid android:color="@color/white"/>
</shape>
</item>
<item
android:bottom="128dp">
<bitmap android:src="@drawable/launch_bg" />
</item>
<item
android:gravity="top"
android:top="123dp">
<bitmap
android:gravity="center_horizontal|top"
android:src="@drawable/launch_title" />
</item>
<item
android:bottom="44dp"
android:gravity="bottom">
<bitmap
android:gravity="center_horizontal|bottom"
android:src="@drawable/launch_bottom" />
</item>
</layer-list>
问题来了,横屏进入时,封面会被拉伸,如何为横屏单独配置一张背景图呢?很简单,创建一个drawable-land目录,创建一个同名文件starting_bkg.xml,里面配置横屏图片,从而启动的时候会根据横竖屏自动选择。