Window与WindowManager

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参数比较重要
    • 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的功能:
  • 常用功能(定义在ViewManager中):
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;
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wjxbless

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值