标题今天做WindowManager弹窗遇到了点小麻烦,做个笔记记录一下。
第一版
private void showSelfViewWindow(Context context){
mWindowManager = (WindowManager) context.getSystemService(WINDOW_SERVICE);
mSelfView = new SelfView(context);
WindowManager.LayoutParams selfViewParams = new WindowManager.LayoutParams();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
selfViewParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
selfViewParams.type = WindowManager.LayoutParams.TYPE_PHONE;
}
selfViewParams.alpha = 1f;
selfViewParams.flags = FLAG_NOT_FOCUSABLE;
selfViewParams.format = PixelFormat.RGBA_8888;
selfViewParams.width = 200;
selfViewParams.height = 200;
mWindowManager.addView(mSelfView, selfViewParams);
}
mSelfView(自定义view)通过WindowManager,做弹框。以上代码完成了mSelfView的显示功能。
接下来要实现重置mSelfView的位置功能:
改变mSelfView的位置需要通过WindowManager.updateViewLayout(view, params)方法实现。
先来获取mSelfView的WindowManager.LayoutParams。
一顿尝试后,没有找到获取LayoutParams的方法。
接着想到了两个方法:
1.在需要的时候重新定义一个LayoutParams(对已经设置过的属性还需要重新设置)。
2.将selfViewParams给为类内的对象(也可以说成全局变量:mSelfViewParams)。
我选用了第二种方法。
第二版
private void initSelfViewParams(Context context){
mSelfViewParams = new WindowManager.LayoutParams();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mSelfViewParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
mSelfViewParams.type = WindowManager.LayoutParams.TYPE_PHONE;
}
mSelfViewParams.alpha = 1f;
mSelfViewParams.flags = FLAG_NOT_FOCUSABLE;
mSelfViewParams.format = PixelFormat.RGBA_8888;
selfViewParams.width = 200;
selfViewParams.height = 200;
}
private void showSelfViewWindow(Context context){
if(mSelfViewParams == null){
initSelfViewParams(context);
}
mWindowManager = (WindowManager) context.getSystemService(WINDOW_SERVICE);
mSelfView = new SelfView(context);
mWindowManager.addView(mSelfView, mSelfViewParams);
}
代码修改后,就很轻松的获取到WindowManager.LayoutParams,这样避免了对LayoutParams属性的重复设置。
这里隐藏一个小bug,当mSelfView没有show出来时,可能没办法修改它的显示位置。那么就在addview之后加入addOnLayoutChangeListener监听。
...
mWindowManager.addView(mSelfView, mSelfViewParams);
mSelfView.addOnLayoutChangeListener(new View.OnLayoutChangeListener{...});
通过以下方法修改mSelfView的位置
private void moveSelfView(int x, int y){
selfViewParams.x = x;
selfViewParams.y = y;
mWindowManager.updateViewLayout(mSelfView, mSelfViewParams);
}
此时又遇到个问题:OnLayoutChangeListener无限执行。
修正方法,将OnLayoutChangeListener设置成类内对象,在执行一次OnLayoutChangeListener.onLayoutChange回调后,将该监听移除。
第三版
myLayoutChangeListener = new MyLayoutChangeListener();
...
mWindowManager.addView(mSelfView, mSelfViewParams);
mSelfView.addOnLayoutChangeListener(myLayoutChangeListener);
...
class MyLayoutChangeListener implements View.OnLayoutChangeListener{
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft,int oldTop, int oldRight, int oldBottom) {
v.removeOnLayoutChangeListener(myLayoutChangeListener);
// 之后就可以使用view改变的方法了
}
}
接下来继续完成view移动的需求。
使用moveSelfView()方法,缺发现view并没有达到自己的要求。接下来就是各种尝试。
- 猜测WindowManager.LayoutParams貌似是包裹view的一个布局,那么将LayoutParams的大小设置成全屏,然后想办法移动设置在布局里的位置。得到的结果是view的大小变成了全屏尺寸。这么一看,LayoutParams设置的事view的属性。
- 接着给mSelfViewParams加了个属性,mSelfViewParams.gravity = Gravity.CENTER,失败,搞得veiw都不动了。
- 省略n多个无厘头的尝试…
- 正解:修改mSelfViewParams.gravity = Gravity.LEFT | Gravity.TOP;就可以按x,y的方式改变位置了。