Android弹窗总结

一.全局弹窗

方式一:通过申请特殊权限来弹出全局弹窗

1.先在清单文件里面进行配置权限(兼容低版本):

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

2.动态申请权限(兼容高版本)

 if (Build.VERSION.SDK_INT >= 23) {
                    //android6.0及以上需要去申请特殊权限
                    if (!Settings.canDrawOverlays(SecondActivity.this)) {
                        Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
                        startActivity(intent);
                        return;
                    } else {
                        AlertDialog alertDialog = new AlertDialog.Builder(getApplicationContext()).create();
                        alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
                        alertDialog.show();
                    }
                } else {
                    //Android6.0以下,不用动态声明权限
                  AlertDialog alertDialog = new AlertDialog.Builder(getApplicationContext()).create();
                      alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
                        alertDialog.show();
                }

也可以制作悬浮窗:

 // 获取应用的Context
                Context mContext = getApplicationContext();
                // 获取WindowManager
                WindowManager mWindowManager = (WindowManager) mContext
                        .getSystemService(Context.WINDOW_SERVICE);
                View view = getLayoutInflater().from(mContext).inflate(R.layout.popupwindow, null);
                final WindowManager.LayoutParams params = new WindowManager.LayoutParams();
                // 类型
                params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
                // WindowManager.LayoutParams.TYPE_SYSTEM_ALERT
                // 设置flag
                int flags = WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
                // | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
                // 如果设置了WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,弹出的View收不到Back键的事件
                params.flags = flags;
                // 不设置这个弹出框的透明遮罩显示为黑色
                params.format = PixelFormat.TRANSLUCENT;
                // FLAG_NOT_TOUCH_MODAL不阻塞事件传递到后面的窗口
                // 设置 FLAG_NOT_FOCUSABLE 悬浮窗口较小时,后面的应用图标由不可长按变为可长按
                // 不设置这个flag的话,home页的划屏会有问题
                params.width = WindowManager.LayoutParams.MATCH_PARENT;
                params.height = WindowManager.LayoutParams.MATCH_PARENT;
                params.gravity = Gravity.CENTER;
                mWindowManager.addView(view, params);

方式二:创建一个样式为dialog的Activity然后弹出窗体.

1.设置activity的样式为Dialog的样子.

<style name="translucent" parent="Theme.AppCompat.Light.Dialog">
    </style>

2.将activity的样式背景颜色设为半透明的即可.

 <style name="translucent" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="android:windowBackground">@color/translucent_background</item>
        <item name="android:windowIsTranslucent">true</item>
    </style>
<color name="translucent_background">#60000000</color>

二.弹窗动画效果。

步骤一:dialog_enter_anim.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <scale
        android:interpolator="@android:anim/accelerate_interpolator"
        android:fromXScale="1.0"
        android:toXScale="1.0"
        android:fromYScale="1.0"
        android:toYScale="0.0"
        android:pivotX="0%"
        android:pivotY="100%"
        android:fillAfter="false"
        android:duration="400"/>
</set>

步骤二:dialog_exit_anim.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <scale
        android:duration="400"
        android:fillAfter="false"
        android:fromXScale="1.0"
        android:fromYScale="0.0"
        android:interpolator="@android:anim/accelerate_interpolator"
        android:pivotX="0%"
        android:pivotY="100%"
        android:toXScale="1.0"
        android:toYScale="1.0"/>
</set>

步骤三:设置style

<style name="mystyle" parent="android:Animation">
    <item name="@android:windowEnterAnimation">@anim/dialog_enter</item>  //进入时的动画
    <item name="@android:windowExitAnimation">@anim/dialog_exit</item>    //退出时的动画
</style>

步骤四:初始化弹窗

   AlertDialog dialog = new AlertDialog.Builder(MainActivity.this)
        .setTitle("title").setMessage("message").create();
Window window = dialog.getWindow();
window.setGravity(Gravity.BOTTOM);  //此处可以设置dialog显示的位置
window.setWindowAnimations(R.style.mystyle);  //添加动画*/
dialog.show();

三.底部弹窗动画。

1.写好样式.弹出动画文件

 <style name="BottomDialog" parent="@style/Base.V7.Theme.AppCompat.Light.Dialog">
        <item name="android:windowNoTitle">true</item>
        <item name="android:windowBackground">@android:color/transparent</item>
    </style>
    
<style name="BottomDialog.Animation" parent="Animation.AppCompat.Dialog">
        <item name="android:windowEnterAnimation">@anim/translate_dialog_in</item>
        <item name="android:windowExitAnimation">@anim/translate_dialog_out</item>
    </style>    
    
<!--translate_dialog_in-->
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
           android:duration="300"
           android:fromXDelta="0"
           android:fromYDelta="100%"
           android:toXDelta="0"
           android:toYDelta="0">
</translate>
<!--translate_dialog_out-->
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
           android:duration="300"
           android:fromXDelta="0"
           android:fromYDelta="0"
           android:toXDelta="0"
           android:toYDelta="100%">
</translate>

2弹出窗体.

  Dialog bottomDialog = new Dialog(this, R.style.BottomDialog);
        View contentView = LayoutInflater.from(this).inflate(R.layout.dialog_content_normal, null);
        bottomDialog.setContentView(contentView);
        ViewGroup.LayoutParams layoutParams = contentView.getLayoutParams();
        layoutParams.width = getResources().getDisplayMetrics().widthPixels;
        contentView.setLayoutParams(layoutParams);
        bottomDialog.getWindow().setGravity(Gravity.BOTTOM);
        bottomDialog.setCanceledOnTouchOutside(true);
        bottomDialog.getWindow().setWindowAnimations(R.style.BottomDialog_Animation);
        bottomDialog.show();

<!--带有间隙的dialog--> 

 Dialog bottomDialog = new Dialog(this, R.style.BottomDialog);
        View contentView = LayoutInflater.from(this).inflate(R.layout.dialog_content_circle, null);
        bottomDialog.setContentView(contentView);
        ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) contentView.getLayoutParams();
        params.width = getResources().getDisplayMetrics().widthPixels - DensityUtil.dp2px(this, 16f);
        params.bottomMargin = DensityUtil.dp2px(this, 8f);
        contentView.setLayoutParams(params);
        bottomDialog.setCanceledOnTouchOutside(true);
        bottomDialog.getWindow().setGravity(Gravity.BOTTOM);
        bottomDialog.getWindow().setWindowAnimations(R.style.BottomDialog_Animation);
        bottomDialog.show();

四.PopuWindow相关.

1 showAtLocation(相对于组件parent屏幕)

 public void showAtLocation(View parent, int gravity, int x, int y)

1. parent可以为Activity中的任意一个View(最终的效果一样),会通过这个View找到其父Window,也就是Activity的Window。

2. gravity,默认为Gravity.NO_GRAVITY,等效于Gravity.LEFT | Gravity.TOP

3. x, y,边距。这里的x,y表示距离Window边缘的距离,方向由Gravity决定。例如:设置了Gravity.TOP,则y表示与Window上边缘的距离;而如果设置了Gravity.BOTTOM,则y表示与下边缘的距离。

4. 如果弹窗位置超出了Window的范围,会自动处理使其处于Window中

5. 相对于屏幕(左上角0,0),窗位置超出了Window的范围,会自动处理使其处于Window中,显示范围是顶部和底部

2 showAsDropDown(相对于组件)

public void showAsDropDown(View anchor, int xoff, int yoff)

1. 弹窗会显示在anchor控件的正下方。

2. 如果指定了xoff和yoff,则会在原有位置向右偏移xoff,向下偏移yoff。

3. 如果指定gravity为Gravity.RIGHT,则弹窗和控件右对齐;否则左对齐。注意,计算右对齐时使用了- PopupWindow的宽度,如果指定的宽度不是固定值,则计算会失效(可以从源码中看出来)。

4. 如果弹窗位置超出了Window的范围,会自动处理使其处于Window中。

5. 如果anchor可以滚动,则滚动过程中,PopupWindow可以自动更新位置,跟随anchor控件。

6. 相对于组件(左下角 0,屏幕高度)

 总结: showAtLocation 和showAsDropDown主要区别于显示位置相对于屏幕还是组件

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值