持续创作,加速成长!这是我参与「掘金日新计划 · 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的弹框实际用起来还是比较简单的,简单掌握了实现方式就好了。