Android开发-弹框-Window弹框

382 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第15天,点击查看活动详情

前面我们已经介绍了安卓开发中用到的弹框中的2种,今天我们来介绍第三种,Window弹框,这种实现方式类似于Dialog的实现,但是它不同于Dialog,因为它是完全使用系统级的window窗口设置,通过WindowManager获取系统服务,所以这里在实现上需要注意系统的兼容性,比如今天就会说到权限问题。

Window弹框的定义

Window弹框本身在开发过程中使用的不是特别多,但是是一个需要了解的知识点,因为在后期开发其他类似系统弹框也好,浮窗也好都是需要用到WindowManager这个服务的,也是这里我想拿出来说的一个原因。下面就简单介绍下window窗口的实现。

public class MainActivity extends Activity {

 
    private WindowManager windowManager;
    private static final int REQUEST_CODE = 0x001;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
        btn_dialog.setOnClickListener{ ->
          initWindowDialog(); 
        }
    }

    private void initWindowDialog(){
       //获取当前窗口的布局参数,主要勇于设置窗口大小
       WindowManager.LayoutParams params= new WindowManager.LayoutParams();
       //设置窗口布局参数属性,设置窗口大小       
       params.width=WindowManager.LayoutParams.MATCH_PARENT;
       params.height=WindowManager.LayoutParams.MATCH_PARENT;
       params.flags=WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
       |WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
       params.format= PixelFormat.TRANSLUCENT;
       params.type=WindowManager.LayoutParams.TYPE_PHONE;
       View windowView=View.inflate(this,R.layout.layout_window,null);
       windowManager.addView(windowView,params);
    }
}

上面代码运行后,在6.0系统之前是没有问题的,但是6.0以后引入了权限系统,所以需要添加权限判断。

1、首先需要在manifest中添加系统弹框权限

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

2、改造下上面点击事件的处理

btn_dialog.setOnClickListener{ ->
          
          if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.M)
                {
                    //版本大于6.0则需要判断是否获取了overlays权限
                    if (!Settings.canDrawOverlays(MainActivity.this))
                    {
                        startActivityForResult(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                                Uri.parse("package:"+getPackageName())),REQUEST_CODE);
                    }
                    else
                    {
                        initWindowDialog();
                    }
                }
          
          
}

3、在Activity的result回调中处理相关逻辑

@Override
protected void onActivityResult(int requestCode,  int resultCode, Intent data){
    switch(requestCode){
        case REQUEST_CODE:   
        if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.M){
            if(Settings.canDrawOverlays(this)){
                //若用户开启了overlay权限,则打开window
                initWindowDialog();
            }else{
                Toast.makeText(this,"需要开启系统权限",Toast.LENGTH_SHORT).show();
            }
            break;
        }
    }
}

这样全部的代码都完成了,运行下就可以实现弹框的显示了,这里有几个设置项,简单介绍下 params.flags:这个主要是设置window的显示特性;它有很多属性,这里用到的是FLAG_WATCH_OUTSIDE_TOUCH,它的主要用处是当触屏事件发生在窗,可以触发MotionEvent.ACTION_OUTSIDE事件。

params.format:设置窗口的类型,这里设置窗口半透明,如果不设置的话,窗口的背景是黑色;

params.type:应用程序窗口的类型,这个有很多种,简单介绍几个常用的

  应用程序窗口。
  public static final int FIRST_APPLICATION_WINDOW = 1;    
  
  普通应用功能程序窗口。token必须设置为Activity的token,以指出该窗口属谁。
  public static final int TYPE_APPLICATION = 2;

  媒体信息。显示在媒体层和程序窗口之间,需要实现透明(半透明)效果。(例如显示字幕)
  public static final int TYPE_APPLICATION_MEDIA_OVERLAY  = FIRST_SUB_WINDOW +4;

  系统窗口。非应用程序创建。
  public static final int FIRST_SYSTEM_WINDOW    = 2000;

  电话窗口。它用于电话交互(特别是呼入)。它置于所有应用程序之上,状态栏之下。
  public static final int TYPE_PHONE            = FIRST_SYSTEM_WINDOW+2;

  系统提示。它总是出现在应用程序窗口之上。
  public static final int TYPE_SYSTEM_ALERT      =  FIRST_SYSTEM_WINDOW +3;

  锁屏窗口。
  public static final int TYPE_KEYGUARD          = FIRST_SYSTEM_WINDOW +4;

  信息窗口。用于显示toast。
  public static final int TYPE_TOAST            = FIRST_SYSTEM_WINDOW +5;

  系统顶层窗口。显示在其他一切内容之上。此窗口不能获得输入焦点,否则影响锁屏。
  public static final int TYPE_SYSTEM_OVERLAY    =  FIRST_SYSTEM_WINDOW +6;

  系统对话框。(例如音量调节框)。
  public static final int TYPE_SYSTEM_DIALOG     =  FIRST_SYSTEM_WINDOW +8;

这个是网上找来的,具体的说明都很详细,我们这里设置的是TYPE_PHONE,上面也有介绍,还有其他的笔记常用的:TYPE_SYSTEM_ALERT,TYPE_SYSTEM_OVERLAY,在系统浮框上用的比较多,比如锁屏情况下载home显示一个应用浮框这样的业务。

Window的弹框实际用起来还是比较简单的,简单掌握了实现方式就好了。