WindowManager嵌入自定义view弹窗笔记

标题今天做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并没有达到自己的要求。接下来就是各种尝试。

  1. 猜测WindowManager.LayoutParams貌似是包裹view的一个布局,那么将LayoutParams的大小设置成全屏,然后想办法移动设置在布局里的位置。得到的结果是view的大小变成了全屏尺寸。这么一看,LayoutParams设置的事view的属性。
  2. 接着给mSelfViewParams加了个属性,mSelfViewParams.gravity = Gravity.CENTER,失败,搞得veiw都不动了。
  3. 省略n多个无厘头的尝试…
  4. 正解:修改mSelfViewParams.gravity = Gravity.LEFT | Gravity.TOP;就可以按x,y的方式改变位置了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值