PermissionDialog【权限申请提示对话框】

版权声明:本文为HaiyuKing原创文章,转载请注明出处!

前言

  随着Android6.0的普及,权限申请也变成了我们开发中必写的一段代码。比如sd卡权限、定位权限、拍照权限,这些几乎都是每个app必备的。而一般情况下我们都会在需要权限之前申请,然后各种判断。那既然是一些必备的是权限,我们为何不在我们一次打开app的时候就把这个全部都申请了呢?可是一下申请那么多权限对用户来说显然不是很友好,所以我们不妨在申请权限之前告诉一下用户,好让用户有个心理准备。于是借鉴了饿了么的权限申请界面,封装了一个对话框。
 
  这个对话框只是用来展现应用当中需要用到的权限列表,不具备申请权限的功能,申请权限请搭配相关第三方库,比如《Android6.0运行时权限(基于RxPermission开源库)》;另外,考虑到这个对话框一般在APP首次使用的时候才会弹出来,所以搭配《PreferencesUtils【SharedPreferences操作工具类】》实现保存状态值,用于判断是否需要显示这个对话框。

效果图

代码分析

PermissionDialog:对话框界面,继承AlertDialog

使用步骤

一、项目组织结构图

注意事项:

1、  导入类文件后需要change包名以及重新import R文件路径

2、  Values目录下的文件(strings.xml、dimens.xml、colors.xml等),如果项目中存在,则复制里面的内容,不要整个覆盖

二、导入步骤

1、将PermissionDialog.java文件复制到项目中

package com.why.project.permissiondialog.dialog;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.graphics.Color;
import android.graphics.ColorMatrixColorFilter;
import android.os.Bundle;
import android.support.v4.content.ContextCompat;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TextView;

import com.why.project.permissiondialog.R;

/**
 * Created by HaiyuKing
 * Used 权限申请对话框
 */
public class PermissionDialog extends AlertDialog {

    //上下文
    private Context mContext;

    //内容的父节点,用于内容较多时可以滚动
    private ScrollView mListScroll;
    //内容
    private LinearLayout mListLayout;
    //确认按钮
    private TextView mConfirmBtn;

    public PermissionDialog(Context context) {
        //设置对话框样式
        super(context, R.style.style_permission_dialog);

        //设置为false,按对话框以外的地方不起作用
        setCanceledOnTouchOutside(false);
        //设置为false,按返回键不能退出
        setCancelable(false);

        this.mContext = context;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.permission_dialog_layout);

        initViews();
        initDatas();
        initEvents();
    }

    /**初始化view*/
    private void initViews() {
        mListScroll = findViewById(R.id.permission_dialog_list_scroll);
        mListLayout = findViewById(R.id.layout_list);
        mConfirmBtn = findViewById(R.id.dialog_confirm_btn);
    }

    /**初始化数据*/
    private void initDatas() {

        //获取图标的颜色值
        int mFilterColor = ContextCompat.getColor(mContext,R.color.permission_dialog_img_color);
        int blue = Color.blue(mFilterColor);
        int green = Color.green(mFilterColor);
        int red = Color.red(mFilterColor);
        float[] cm = new float[]{
                1, 0, 0, 0, red,// 红色值
                0, 1, 0, 0, green,// 绿色值
                0, 0, 1, 0, blue,// 蓝色值
                0, 0, 0, 1, 1 // 透明度
        };
        ColorMatrixColorFilter filter = new ColorMatrixColorFilter(cm);

        //初始化权限列表区域
        int[] permissionImgIds = mContext.getResources().getIntArray(R.array.permission_icon);
        String[] permissionTitles = mContext.getResources().getStringArray(R.array.permission_title);
        String[] permissionInfos = mContext.getResources().getStringArray(R.array.permission_info);

        for(int i = 0; i < permissionImgIds.length; i++){
            String title = permissionTitles[i];
            String info = permissionInfos[i];

            View itemView = View.inflate(mContext,R.layout.permission_list_item,null);
            ((ImageView)itemView.findViewById(R.id.item_img)).setImageResource(mContext.getResources().obtainTypedArray(R.array.permission_icon).getResourceId(i, 0));
            ((ImageView)itemView.findViewById(R.id.item_img)).setColorFilter(filter);//设置图标的颜色
            ((TextView)itemView.findViewById(R.id.item_title)).setText(title);
            ((TextView)itemView.findViewById(R.id.item_info)).setText(info);

            mListLayout.addView(itemView);
        }

        //设置内容区域的父节点的高度和内容文本大小
        final DisplayMetrics display = new DisplayMetrics();
        ((Activity)this.mContext).getWindowManager().getDefaultDisplay().getMetrics(display);
        final int screenHeight = display.heightPixels;
        //先设置宽度,然后再调整高度
        mListScroll.setLayoutParams(new LinearLayout.LayoutParams(display.widthPixels - mContext.getResources().getDimensionPixelOffset(R.dimen.permission_dialog_margin) * 2,
                ViewGroup.LayoutParams.WRAP_CONTENT));

        //runnable中的方法会在View的measure、layout等事件后触发
        mListScroll.post(new Runnable() {
            @Override
            public void run() {
                if (mListScroll.getMeasuredHeight() > screenHeight / 2) {
                    mListScroll.setLayoutParams(new LinearLayout.LayoutParams(display.widthPixels - mContext.getResources().getDimensionPixelOffset(R.dimen.permission_dialog_margin) * 2,
                            screenHeight / 2));
                }else{
                    //屏幕宽度减去外边距*2
                    mListScroll.setLayoutParams(new LinearLayout.LayoutParams(display.widthPixels - mContext.getResources().getDimensionPixelOffset(R.dimen.permission_dialog_margin) * 2,
                            ViewGroup.LayoutParams.WRAP_CONTENT));
                }
            }
        });

    }

    /**初始化监听事件*/
    private void initEvents() {
        mConfirmBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(mOnCertainButtonClickListener != null){
                    mOnCertainButtonClickListener.onCertainButtonClick();
                }
                dismiss();
            }
        });
    }

    @Override
    public void dismiss() {
        super.dismiss();
    }

    public static abstract interface OnCertainButtonClickListener
    {
        //确认按钮的点击事件接口
        public abstract void onCertainButtonClick();
    }

    private OnCertainButtonClickListener mOnCertainButtonClickListener;

    public void setOnCertainButtonClickListener(OnCertainButtonClickListener mOnCertainButtonClickListener)
    {
        this.mOnCertainButtonClickListener = mOnCertainButtonClickListener;
    }

}
PermissionDialog.java

2、将permission_dialog_bg.xml、permission_dialog_one_btn_bg.xml复制到drawable目录下

3、将图片资源复制到drawable-xxhdpi目录下

4、将permission_dialog_layout.xml、permission_list_item.xml布局文件复制到项目中

5、在arrays.xml中添加以下代码【根据实际情况,通过注释控制图标的个数,标题、说明数组需要和图标数组一一对应

<?xml version="1.0" encoding="utf-8"?>
<resources>
    
    <!-- 权限图标【可根据实际情况修改】 -->
    <integer-array name="permission_icon">
        <item>@drawable/permission_ic_storage</item>
        <item>@drawable/permission_ic_camera</item>
        <item>@drawable/permission_ic_location</item>
        <item>@drawable/permission_ic_phone</item>
        <item>@drawable/permission_ic_micro_phone</item>
        <item>@drawable/permission_ic_calendar</item>
        <item>@drawable/permission_ic_contacts</item>
        <item>@drawable/permission_ic_sms</item>
        <item>@drawable/permission_ic_sensors</item>
    </integer-array>

    <!-- 权限标题【可根据实际情况修改】 -->
    <string-array name="permission_title">
        <item>文件存储</item>
        <item>相机相册</item>
        <item>位置信息</item>
        <item>电话状态</item>
        <item>录制声音</item>
        <item>日程信息</item>
        <item>通讯录</item>
        <item>短信信息</item>
        <item>传感器</item>
    </string-array>

    <!-- 权限说明(这里应该是根据项目的实际情况,简要说明下该权限主要用于什么场景或者功能)【可根据实际情况修改】 -->
    <string-array name="permission_info">
        <item>允许应用读取、写入外部存储</item>
        <item>允许应用访问摄像头进行拍照</item>
        <item>允许应用获取定位信息</item>
        <item>允许应用访问电话状态</item>
        <item>允许应用通过手机或耳机的麦克录制声音</item>
        <item>允许应用读取用户的日程信息</item>
        <item>允许应用访问联系人通讯录信息</item>
        <item>允许应用获取短信信息</item>
        <item>允许应用获取传感器信息</item>
    </string-array>
    
</resources>

 6、在colors.xml中添加以下代码【根据实际情况设置图标和按钮的背景颜色值

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#008577</color>
    <color name="colorPrimaryDark">#00574B</color>
    <color name="colorAccent">#D81B60</color>

    <!-- ==================权限申请对话框(alertdialog)================== -->
    <!-- 对话框的填充颜色 -->
    <color name="permission_dialog_solid_color">#ffffffff</color>
    <!-- 对话框的标题颜色 -->
    <color name="permission_dialog_title_color">#000000</color>
    <!-- 对话框的描述颜色 -->
    <color name="permission_dialog_message_color">#87000000</color>
    <!-- 对话框的图标颜色【可根据实际情况修改】 -->
    <color name="permission_dialog_img_color">#000000</color>
    <!-- 对话框的按钮背景颜色【可根据实际情况修改】 -->
    <color name="permission_dialog_btn_bg_color">#07b4a2</color>
    <!-- 对话框的按钮文字颜色 -->
    <color name="permission_dialog_btn_text_color">#FFFFFF</color>

</resources>

 7、在dimens.xml中添加以下代码

<resources>
    <!-- Default screen margins, per the Android Design guidelines. -->
    <dimen name="activity_horizontal_margin">16dp</dimen>
    <dimen name="activity_vertical_margin">16dp</dimen>

    <!-- ==================权限申请对话框(alertdialog)================== -->
    <!-- 对话框的圆角角度 -->
    <dimen name="permission_dialog_corners">8dp</dimen>
    <!-- 对话框的整体外边距 -->
    <dimen name="permission_dialog_margin">30dp</dimen>
    <!-- 对话框的标题内边距 -->
    <dimen name="permission_dialog_title_padding">15dp</dimen>
    <!-- 对话框的标题文本大小 -->
    <dimen name="permission_dialog_title_text_size">22sp</dimen>
    <!-- 对话框的描述文本大小 -->
    <dimen name="permission_dialog_message_text_size">16sp</dimen>
    <!-- 对话框的按钮内边距 -->
    <dimen name="permission_dialog_btn_padding">8dp</dimen>
    <!-- 对话框的按钮大小 -->
    <dimen name="permission_dialog_btn_text_size">16sp</dimen>

</resources>

8、在strings.xml中添加以下代码

<resources>
    <string name="app_name">PermissionDialog</string>

    <!-- ==================权限申请对话框(alertdialog)================== -->
    <string name="permission_dialog_title">权限申请</string>
    <string name="permission_dialog_message">为了您能正常使用,需要以下权限</string>
</resources>

9、在styles.xml中添加以下代码

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

    <!-- ==================权限申请对话框(alertdialog)================== -->
    <style name="style_permission_dialog">
        <!-- Dialog的windowFrame框为无 -->
        <item name="android:windowFrame">@null</item>
        <!-- 是否显示title -->
        <item name="android:windowNoTitle">false</item>
        <!-- 是否浮现在activity之上 -->
        <item name="android:windowIsFloating">true</item>
        <!-- 半透明 -->
        <item name="android:windowIsTranslucent">true</item>
        <!-- 设置dialog的背景:#00000000透明色 -->
        <item name="android:windowBackground">@android:color/transparent</item>
        <!-- 背景变灰:整个屏幕变灰,配合setCanceledOnTouchOutside(false) -->
        <item name="android:backgroundDimEnabled">true</item>
    </style>

</resources>

三、使用方法

在代码中调用如下:

package com.why.project.permissiondialog;

import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;

import com.why.project.permissiondialog.dialog.PermissionDialog;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        findViewById(R.id.btn_showdialog).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                boolean hasShow = PreferencesUtils.getBoolean(MainActivity.this,PreferencesUtils.HAS_SHOW_PREMISSION_DIALOG,false);
                if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && ! hasShow){
                    PermissionDialog permissionDialog = new PermissionDialog(MainActivity.this);
                    permissionDialog.setOnCertainButtonClickListener(new PermissionDialog.OnCertainButtonClickListener() {
                        @Override
                        public void onCertainButtonClick() {
                            //搭配SharedPreferences 将状态值记录下来,实现APP首次打开的时候才会弹出这个对话框
                            PreferencesUtils.putBoolean(MainActivity.this,PreferencesUtils.HAS_SHOW_PREMISSION_DIALOG,true);
                            //调用运行时权限申请框架
                        }
                    });
                    permissionDialog.show();
                }else{
                    //调用运行时权限申请框架
                }
            }
        });
    }
}

 注意:

实际项目中,需要手动调整arrays.xml文件中的权限数组个数,不显示的注释掉,保证三个数组的一一对应;

根据项目的主题颜色,调整colors.xml文件中的图标、按钮的背景颜色值;

混淆配置

参考资料

一行代码搞定漂亮的Android6.0权限申请界面

Android-使用 SetColorFilter 神奇地改变图片的颜色

项目demo下载地址

https://github.com/haiyuKing/PermissionDialog

posted @ 2018-10-04 15:51  HaiyuKing  阅读(8606)  评论(0编辑  收藏  举报