DialogX 平板适配指南暨「给未来写封信」横屏适配方案复盘
引言
首先关于 Android App 如何进行平板适配,推进阅读文章:【Android平板适配】手机/平板二合一应用一站式适配攻略@尼特胡
其中需要注意的点在这里写出来:
1.如何使 Activity 不会因为切换横竖屏自动重启
在 AndroidManifest.xml 中的 Activity 节点增加以下配置:
<activity
...
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation" />
2.如何判断是否为平板及横屏
要判断当前是否为横屏,可以使用以下办法判断:
public static boolean isTablet() {
return (getInstance().getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE;
}
当前是否是横屏可以使用以下办法判断:
private static boolean isLandscape(Activity activity) {
if (activity != null) {
return activity.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
}
return false;
}
给未来写封信是如何进行横屏适配的
基础 UI
对于大部分界面,我们进行了评估,基于开发成本考虑没有专门的为平板方式重新设计 UI,而是采用了“兼容”方案进行适配,具体逻辑是,在竖屏时保证所有 UI 界面均可以动态的对窗口大小进行匹配,而不是“等比缩放”的方案进行显示,即,按照以下逻辑,在横屏时对 UI 进行居中适配:
基于这个方案,只需要对 UI 部分进行最大宽度限制即可,对于内容布局,我们改写了内容布局的外层 ViewGroup,使其支持设置 maxWidth 最大宽度:
/**
* @author: Kongzue
* @github: https://github.com/kongzue/
* @homepage: http://kongzue.com/
* @mail: myzcxhh@live.cn
* @createTime: 2019/9/24 17:34
*/
public class HorizontalScreenAdapterRelativeLayout extends RelativeLayout {
private int maxWidth;
private int maxHeight;
public HorizontalScreenAdapterRelativeLayout(Context context) {
super(context);
}
public HorizontalScreenAdapterRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public HorizontalScreenAdapterRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
maxWidth = Math.min(getDisplayWidth(),getDisplayHeight());
}
public HorizontalScreenAdapterRelativeLayout setMaxHeight(int maxHeight) {
this.maxHeight = maxHeight;
return this;
}
public HorizontalScreenAdapterRelativeLayout setMaxWidth(int maxWidth) {
if (maxWidth > 0) this.maxWidth = maxWidth;
return this;
}
private int preWidth = -1;
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
if (preWidth == -1 && widthSize != 0) {
preWidth = widthSize;
}
if (maxHeight > 0) {
heightSize = Math.min(heightSize, maxHeight);
}
if (maxWidth > 0) {
widthSize = Math.min(widthSize, maxWidth);
}
int maxHeightMeasureSpec = MeasureSpec.makeMeasureSpec(heightSize, heightMode);
int maxWidthMeasureSpec = MeasureSpec.makeMeasureSpec(widthSize, widthMode);
super.onMeasure(maxWidthMeasureSpec, maxHeightMeasureSpec);
}
public int dip2px(float dpValue) {
final float scale = getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
public int getDisplayWidth() {
Display disp = ((Activity)getContext()).getWindowManager().getDefaultDisplay();
Point outP = new Point();
disp.getSize(outP);
return outP.x;
}
public int getDisplayHeight() {
Display disp = ((Activity)getContext()).getWindowManager().getDefaultDisplay();
Point outP = new Point();
disp.getSize(outP);
return outP.y;
}
}
此布局默认会自动根据屏幕宽高的最小值,对另一个最大边进行宽高限制,也可以修改代码进行自定义。
对话框 UI
除此之外,对话框的适配也很重要,给未来写封信在对话框的 UI 上是基于 DialogX 进行开发的,而 DialogX 是自带 maxWidth 限定功能的,可以直接使用:
int maxWidth = Math.min(getDisplayWidth(), getDisplayHeight());
DialogX.dialogMaxWidth = maxWidth;
结语
以上,再次感谢小米 MIUI 团队在 Pad 适配上给与的帮助和技术支持,「给未来写封信」开发组也将继续努力提供更优质的用户体验,愿你我未来可期!