Window与WindowManager
原创
©著作权归作者所有:来自51CTO博客作者wx5ba8dc11102bc的原创作品,请联系作者获取转载授权,否则将追究法律责任
Window
- Window表示窗口,比如可以实现桌面或者锁屏上的类似悬浮窗的效果,Android中所有的视图都是通过Window来呈现的,不管是Activity、Dialog还是Toast,实际上他们都是附加在Window上的,WindowManager提供了对这些Window的统一管理功能
Window与WindowManager的联系
- 为了分析Window的工作机制,需要先了解如何使用WindowManager来添加一个Window
WindowManager manager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(width, height, type, flags, format);
manager.addView(btn, layoutParams);
- WindowManager.LayoutParams的属性中type和flags参数比较重要
flag选项
| 意义
|
FLAG_NOT_FOCUSABLE = 0x00000008
| 表示此Window不需要获取焦点,不接受各种输入事件,此标记会同时启用FLAG_NOT_TOUCH_MODAL,最终事件会直接传递给下层具有焦点的Window
|
FLAG_NOT_TOUCH_MODAL = 0x00000020
| 自己Window区域内的事件自己处理;自己Window区域外的事件传递给底层Window处理,一般这个选项会默认开启,否则其他Window无法接受事件
|
FLAG_SHOW_WHEN_LOCKED
| 让Window无法收到事件
|
- Type参数是int类型的,表示Window的类型,Window有三种类型:应用Window、子Window和系统Window
- 应用Window对应着一个Activity,子Window不能独立存在(要依附在特定的父Window中),系统Window需要权限才能进行创建(Toast和系统状态栏)
Window层级:
- 应用Window的层级范围:1~99
- 子Window的层级范围:1000~1999
- 系统Window的层级范围:2000~2999
- 注意:
- 层级大的Window会覆盖在层级小的Window上
- 使用系统级Window,需要在AndroidMenifest.xml中配置
WindowManager的功能:
public interface WindowManager ectends ViewManager
public interface ViewMananger{
//添加View
public void addView(View view, ViewGroup.LayoutParams params);
//更新View
public void updateViewLayout(View view, ViewGroup.LayoutParams params);
//删除View
public void remoteView(View view);
}
eg:桌面悬浮窗:
public class WindowDemoActivity extends AppCompatActivity implements View.OnTouchListener {
private Button add_btn;
private Button rem_btn;
private CircleImageView imageView;
private WindowManager.LayoutParams layoutParams;
private WindowManager windowManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_window_demo);
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.M){
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
startActivityForResult(intent, 100);
}
add_btn = (Button)findViewById(R.id.add_btn);
rem_btn = (Button)findViewById(R.id.rem_btn);
windowManager = (WindowManager)getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
add_btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
imageView = new CircleImageView(getApplicationContext());
imageView.setImageResource(R.drawable.androidfirst);
layoutParams = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, 2099, WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED, PixelFormat.TRANSPARENT
);
layoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
layoutParams.gravity = Gravity.TOP | Gravity.LEFT;
layoutParams.x = 0;
layoutParams.y = 300;
imageView.setOnTouchListener(WindowDemoActivity.this);
windowManager.addView(imageView, layoutParams);
}
});
rem_btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(imageView != null) {
windowManager.removeView(imageView);
}
}
});
}
@Override
public boolean onTouch(View v, MotionEvent event) {
int rawX = (int) event.getRawX();
int rawY = (int) event.getRawY();
switch (event.getAction()){
case MotionEvent.ACTION_MOVE:{
layoutParams.x = rawX;
layoutParams.y = rawY;
windowManager.updateViewLayout(imageView, layoutParams);
break;
}
default:
break;
}
return false;
}
}