一、需求:
全屏视频播放器,点击右上角更多按钮,弹出设置菜单,效果参考优酷、西瓜等视频应用。
功能细节:
1.弹窗显示和消失动画
2.沉浸式效果,窗口显示和消失过程中,状态栏不会出现
3.弹窗能够响应物理back按键
二、实现方案
实现方式1
直接上结论:
通过PopupWindow.setAnimationStyles实现动画,
显示时focusable=false,由于View没有焦点,物理按键事件不会自动分发给PopupWindow,Activity重写dispatchKeyEvent或者onBackPressed,判断弹窗显示的时候,拦截back事件,并让弹窗消失。
分析:问题的关键点在于,如果focusable=true,PopupWindow就可以自动响应物理按键,但是此时会破坏沉浸模式,出状态栏,原因是把Activity的焦点给抢走了。所以,只能设置focusable=false,通过Activity来分发事件给弹窗。
总结:正规做法,没有用到任何奇技淫巧,不会有坑,分发事件稍微麻烦,如果多个Activity同时用到该弹窗,都需要向该弹窗分发back事件
其它实现方式
这几种方式大部分都有坑
1. 显示时无焦点,显示完再update设置需要获取焦点(有坑)
参考实现:https://relex.me/show-popupwindow-in-immersive-mode/
原理:显示PopupWindow前,focusable=false,调用show后再focusable=true,update,
问题点:大部分手机ok,三星手机(SM-G9350 android 7.0)会出现动画异常,update方法会触发第二次enter动画,菜单会从右侧一直滑动到屏幕最左侧。
2.监听焦点改变,触发隐藏状态栏(有坑)
设置设置focusable=true,通过onWindowFocusChanged或者view.getViewTreeObserver().addOnWindowFocusChangeListener,
监听到焦点丢失时,重新隐藏状态栏,要求api >= 18
问题点:点击出弹窗时会闪现状态栏,不能保证状态栏一直不出来
3.Dialog方式实现
参考:https://www.jianshu.com/p/d10dd0c1a344
原理:也同其他方式1,显示时无焦点,显示完再update设置View需要获取焦点,
问题点:暂时未验证,如果有问题的话,可能也应该是状态栏闪现的问题。
三、具体实现
1.弹窗关键代码
public class PoppupWindowLandActivity extends AppCompatActivity implements View.OnClickListener {
private ViewGroup mViewGroup;
private ViewGroup mContentView;
private ViewGroup mMainContent;
private PopupWindow mPopupWindow;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_poppup_window_land);
mViewGroup = findViewById(R.id.layout_main);
// 沉浸式
StatusBarUtils.fullScreenImmersive(this);
findViewById(R.id.btn_popup1).setOnClickListener(this);
findViewB