您当前的位置: 首页 >  ui

命运之手

暂无认证

  • 1浏览

    0关注

    747博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

【高级UI】【005】利用WindowManager创建自定义的PopupWindow和SystemAlertDialog

命运之手 发布时间:2021-10-11 23:15:44 ,浏览量:1

目标

本篇博客的目标主要有三个

  • 不使用安卓原生控件,比如PopupWindow,Dialog等控件,实现我们的目标
  • PopupWindow用于在Activity中全屏展示,模态,PopupWindow下面的全部内容不可操作,当Activity隐藏时,PopupWindow也随之隐藏
  • SystemAlertDialog用于在整个系统中悬浮展示,非模态,SystemAlertDialog下面的内容仍然可以操作,当Activity隐藏时,SystemAlertDialog并不隐藏,它可以在系统桌面之上显示

注意,桌面悬浮框是需要申请额外权限的,需要在清单里注册"SYSTEM_ALERT_WINDOW"权限,并在应用设置里开启"允许在应用上层显示"功能

另外,默认情况下,Window中的ContentView,是不具备处理按键事件的功能的,如果我们需要监听返回键时关闭Window,需要自己重写一个ContentView

实现代码


	package com.android.architecture;
	
	import android.view.KeyEvent;
	
	public interface IKeyEventDispatcher {
	
	    boolean dispatchKeyEvent(KeyEvent event);
	
	    void setKeyEventListener(KeyEventListener listener);
	
	    interface KeyEventListener {
	        boolean dispatchKeyEvent(KeyEvent event);
	    }
	}


	package com.android.architecture;
	
	import android.content.Context;
	import android.util.AttributeSet;
	import android.view.KeyEvent;
	import android.widget.FrameLayout;
	
	public class KeyEventFrameLayout extends FrameLayout implements IKeyEventDispatcher {
	
	    KeyEventListener listener;
	
	    public KeyEventFrameLayout(Context context) {
	        super(context);
	    }
	
	    public KeyEventFrameLayout(Context context, AttributeSet attrs) {
	        super(context, attrs);
	    }
	
	    public KeyEventFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {
	        super(context, attrs, defStyleAttr);
	    }
	
	    @Override
	    public void setKeyEventListener(KeyEventListener listener) {
	        this.listener = listener;
	    }
	
	    @Override
	    public boolean dispatchKeyEvent(KeyEvent event) {
	        if (listener == null)
	            return super.dispatchKeyEvent(event);
	        return listener.dispatchKeyEvent(event);
	    }
	}


    //显示应用内弹窗
    protected void showPopupWindow() {
        WindowManager windowManager = StartActivity.this.getSystemService(WindowManager.class);
        //设置window大小
        WindowManager.LayoutParams lpContent = new WindowManager.LayoutParams();
        lpContent.height = ViewGroup.LayoutParams.MATCH_PARENT;
        lpContent.width = ViewGroup.LayoutParams.MATCH_PARENT;
        lpContent.format = PixelFormat.RGBA_8888;
        lpContent.gravity = Gravity.CENTER;
        //设置window类型,这个同时也决定了window显示的优先级
        lpContent.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
        //设置窗体特性
        lpContent.flags = 0;
        lpContent.flags = lpContent.flags | WindowManager.LayoutParams.FLAG_DIM_BEHIND;
        lpContent.flags = lpContent.flags | WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
        //设置背景变暗程度
        lpContent.dimAmount = 0.6F;
        //创建ContentView
        KeyEventFrameLayout contentView = new KeyEventFrameLayout(StartActivity.this);
        //添加内容
        TextView textView = new TextView(StartActivity.this);
        textView.setText("Popup Window");
        textView.setTextColor(Color.WHITE);
        textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 30);
        FrameLayout.LayoutParams lpChild = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        lpChild.gravity = Gravity.CENTER;
        textView.setLayoutParams(lpChild);
        contentView.addView(textView);
        //监听返回事件
        contentView.setKeyEventListener(event -> {
            if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
                windowManager.removeView(contentView);
                return true;
            }
            return false;
        });
        //监听点击事件
        contentView.setOnClickListener(v -> {
            windowManager.removeView(contentView);
        });
        //显示window
        windowManager.addView(contentView, lpContent);
    }

    //显示系统悬浮框
    //注意,这个操作需要注册"SYSTEM_ALERT_WINDOW"权限,并开启"允许在应用上层显示"功能
    protected void showSystemAlertDialog() {
        WindowManager windowManager = StartActivity.this.getSystemService(WindowManager.class);
        //设置window大小
        WindowManager.LayoutParams lpContent = new WindowManager.LayoutParams();
        lpContent.height = 400;
        lpContent.width = 400;
        lpContent.format = PixelFormat.RGBA_8888;
        lpContent.gravity = Gravity.TOP | Gravity.RIGHT;
        //设置window类型,这个同时也决定了window显示的优先级
        lpContent.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
        //设置窗体特性
        lpContent.flags = 0;
        lpContent.flags = lpContent.flags | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
        //创建ContentView
        //由于原生的FrameLayout不能监听返回键,我们必须重写一个自己的FrameLayout
        KeyEventFrameLayout contentView = new KeyEventFrameLayout(StartActivity.this);
        //添加内容
        TextView textView = new TextView(StartActivity.this);
        textView.setText("System Alert Dialog");
        textView.setTextColor(Color.WHITE);
        textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 30);
        FrameLayout.LayoutParams lpChild = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        lpChild.gravity = Gravity.CENTER;
        textView.setLayoutParams(lpChild);
        contentView.addView(textView);
        //监听返回事件
        contentView.setKeyEventListener(event -> {
            if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
                windowManager.removeView(contentView);
                return true;
            }
            return false;
        });
        //显示window
        windowManager.addView(contentView, lpContent);
    }

WindowManager中常见Flag的作用


	//无法获得焦点,即无法接收到任何KeyEvent事件
	WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
	//无法触摸,即无法接收到任何MotionEvent
	WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
	//非模态,即不阻挡底部内容
	WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
	//背景变暗
	WindowManager.LayoutParams.FLAG_DIM_BEHIND;
	//全屏,即不显示状态栏和导航栏背景
	WindowManager.LayoutParams.FLAG_FULLSCREEN;
	//绘制状态栏和导航栏,如果不绘制,可能会出现导航栏空白现象
	WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;

关注
打赏
1654938663
查看更多评论
立即登录/注册

微信扫码登录

0.0430s