一、为低版本(api<23)的设备优化文本选择的上下文菜单,动态隐藏顶部弹出的条形菜单,并适时恢复,使条形菜单不挤压布局、不覆盖输入框。
低于等于安卓5的系统,选择文本后会在顶部弹出条形菜单,默认会挤压布局,将APP布局往下压。设置 FEATURE_ACTION_MODE_OVERLAY 可以解决挤压问题,将挤压变成覆盖。
requestWindowFeature(Window.FEATURE_ACTION_MODE_OVERLAY);
supportRequestWindowFeature(Window.FEATURE_ACTION_MODE_OVERLAY);
挤压布局的问题解决了,但又引入新的覆盖布局的问题 —— 如果在顶部有输入框,那么选择其中的文本后,条形菜单很有可能覆盖整个输入框。解决方法有两个,其一,将输入框移至布局底部,其二,将条形菜单动态隐藏、然后恢复显示。
方法一需要修改布局,这不是我想要的。只能选方法二,激活输入框选择文本时隐藏条形菜单,退出时恢复显示。
之所以多了恢复这一步,是因为我希望仅仅想屏蔽这一个输入框,而不是连带着连其他输入框或者WebView的上下文菜单也屏蔽了。
那么说说隐藏EditText的上下文菜单的办法。非常简单粗暴,是直接将条形菜单从视图树中剔除,对安卓4、安卓5均有效。
if(Utils.littleCake) {
actionBarRoot = Utils.getNthParentNullable(root, 2);
if (actionBarRoot instanceof ViewGroup && actionBarRoot.getId()==R.id.action_bar_root) {
etSearch.setCustomSelectionActionModeCallback(new ActionMode.Callback() {
View actionModeBar;
Runnable restoreAbility = () -> {
if (actionModeBar!=null) {
Utils.addViewToParent(actionModeBar , (ViewGroup) actionBarRoot, 1);
}
};
@Override public boolean onPrepareActionMode(ActionMode mode, Menu menu) { return false; }
@Override public void onDestroyActionMode(ActionMode mode) {
actionBarRoot.postDelayed(restoreAbility, 800); // 因为动画所以延迟调用 | wait for animation to end
}
@Override public boolean onCreateActionMode(ActionMode mode, Menu menu) {
actionBarRoot.removeCallbacks(restoreAbility);
actionModeBar = actionBarRoot.findViewById(R.id.action_mode_bar);
if (actionModeBar!=null) {
Utils.removeView(actionModeBar);
}
return true;
}
@Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
return false;
}
});
}
}
这个方法简直前无古人,当别人还在用Java反射,反射的时候,我已经开始直接操作视图树了。这个思路,其实是研究Javascript带给我的灵感。
效果如下:
恢复要用postDelayed延迟恢复,因为 action mode bar 消失时有一个动画,需等待其结束再行恢复。延迟的 Runnable 我取名 restoreAbility ,其实是想到鸿蒙OS将安卓的Activity重命名为Ability,恶趣味一下,哈哈,毕竟 restoreRunnable 又长又不好看,还是 Ability 高大上一些。
其他思路:解决条形菜单的覆盖问题,其实只要将条形菜单放到主界面后面就可以,所以 setElevation 应该是可以的,类似于设置渲染的 z-index,强行将主界面显示在前,不过仅仅在安卓5以上可以用。
(代码仅展示片段,省略了一些Utils方法,不过稍后可以在《多聚浏览》开源项目中找到。)
二、适配PC式多窗口
我说的多窗口不是分屏,分屏只能被称作“两窗口”,它哪里可以被唤作“多”窗口了?
PC式多窗口一般会在顶部多出一个标题栏,弹出PopupWindow时需考虑,不然对弹出位置有影响。
星星星 Note5 的多窗口功能,来自2013年:
星星星 S7 的多窗口功能,来自2017年:
相关清单配置,声明支持多窗口:
application { 👇 }
<uses-library android:name="com.sec.android.app.multiwindow" android:required="false" />
<meta-data android:name="com.sec.android.support.multiwindow" android:value="true" />
<meta-data android:name="com.sec.android.multiwindow.DEFAULT_SIZE_W" android:value="632.0dip" />
<meta-data android:name="com.sec.android.multiwindow.DEFAULT_SIZE_H" android:value="598.0dip" />
<meta-data android:name="com.sec.android.multiwindow.MINIMUM_SIZE_W" android:value="632.0dip" />
<meta-data android:name="com.sec.android.multiwindow.MINIMUM_SIZE_H" android:value="598.0dip" />
声明切换多窗口、窗口大小变化等情况时,不重建activity:
activity { 👇 }
android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize|screenLayout|uiMode|locale|layoutDirection|density|fontScale"
题外话,星星星的软件系统真的很厉害,有许多领先的玩意儿,但是当它续航崩了后,就一点儿也不好用了。比如当初高价购入的s7,现在外屏碎,续航崩,bug多,只能当做“特种”调试机偶尔用用罢了,真是特别后悔、一键拉黑、再也不买。
—— 全文完 ——
网友评论