AndroidStudio 用户协议对话框

隐私对话框

效果图

android 协议 时移 android 用户协议_android 协议 时移

代码

新建PrivateDialog.java

package com.mi.aquapark.applicationdemo;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.SystemClock;
import android.support.annotation.NonNull;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextPaint;
import android.text.method.LinkMovementMethod;
import android.text.style.ClickableSpan;
import android.view.Display;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.TextView;

import androidx.core.content.ContextCompat;

import com.mi.aquapark.applicationdemo.R;

public class PrivateDialog {

    private static PrivateDialog instace;

    public PrivateDialog() {

    }

    public static PrivateDialog getInstace() {

        if (instace == null) {
            synchronized (PrivateDialog.class) {
                if (instace == null) {
                    instace = new PrivateDialog();
                }
            }
        }
        return instace;
    }


    private String title = "温馨提示";
    private String message;
    private String sure;
    private String cancle;
    private int[] agreementPos=new int[2];//协议文本位置
    private int[] privacyPos=new int[2];//隐私文本内容

    private Dialog tipDialog;

    private float clickTiem = 0;


    /**
     * desc: 提示隐私协议框
     */
    public void showConnectDialog(Context mContext)
    {
        dismiss();
        if ((SystemClock.elapsedRealtime() - clickTiem) < 500)
        {
            return;
        }
        tipDialog = new AlertDialog.Builder(mContext).create();

        tipDialog.setCanceledOnTouchOutside(false);

        View view = LayoutInflater.from(mContext).inflate(R.layout.private_dialog, null, false);
        TextView tvTitle = view.findViewById(R.id.tv_sava_dialog_title);
        TextView dialogTxt = view.findViewById(R.id.tv_sava_dialog_message);
        TextView tvcancle = view.findViewById(R.id.tv_sava_dialog_cancel);
        TextView tvsure = view.findViewById(R.id.tv_sava_dialog_confirg);

        if (!this.title.isEmpty())
        {
            tvTitle.setText(this.title);
        }
        if (!this.message.isEmpty())
        {
            dialogTxt.setText(this.message);
        }
        if (!this.cancle.isEmpty())
        {
            tvcancle.setText(this.cancle);
        }
        if (!this.sure.isEmpty())
        {
            tvsure.setText(this.sure);
        }


        SpannableStringBuilder tvProtocol = new SpannableStringBuilder(dialogTxt.getText().toString());
        tvProtocol.setSpan(new CliclSpan(mContext,1),agreementPos[0],agreementPos[1], Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
        tvProtocol.setSpan(new CliclSpan(mContext,2),privacyPos[0],privacyPos[1],Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
        dialogTxt.setText(tvProtocol);
        dialogTxt.setMovementMethod(LinkMovementMethod.getInstance());


        view.findViewById(R.id.tv_sava_dialog_cancel).setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                clickTiem = SystemClock.elapsedRealtime();
                tipDialog.dismiss();
                if (listener != null)
                {
                    listener.cancleClick();
                }
            }
        });

        tvsure.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                tipDialog.dismiss();
                if (listener != null)
                {
                    listener.sureClick();
                }

            }
        });
        tipDialog.setOnKeyListener(new DialogInterface.OnKeyListener()
        {
            @Override
            public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event)
            {
                if (keyCode == KeyEvent.KEYCODE_SEARCH)
                {
                    return true;
                }
                else
                {
                    return false; //默认返回 false
                }
            }
        });
        tipDialog.getWindow().setBackgroundDrawableResource(android.R.color.transparent);
        tipDialog.show();
        tipDialog.setCancelable(false);
        tipDialog.getWindow().setContentView(view);

        WindowManager windowManager = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
        Display display = windowManager.getDefaultDisplay();
        WindowManager.LayoutParams params = tipDialog.getWindow().getAttributes();
        params.width = (int) (display.getWidth() * 0.8);
        tipDialog.getWindow().setAttributes(params);

    }

    public void dismiss()
    {
        if (tipDialog != null)
        {
            if (tipDialog.isShowing())
            {
                tipDialog.dismiss();
            }
            tipDialog = null;
        }
    }

    public interface OnTipItemClickListener
    {
        void cancleClick();

        void sureClick();

        void userClick();

        void termsClick();
    }

    private OnTipItemClickListener listener;
    //设置协议位置
    public PrivateDialog setAgreementPos(int start,int end)
    {
        agreementPos[0]=start;
        agreementPos[1]=end;
        return this;
    }
    //设置隐私位置
    public PrivateDialog setPrivacyPos(int start,int end)
    {
        privacyPos[0]=start;
        privacyPos[1]=end;
        return this;
    }
    // 按钮时间及协议跳转网页按钮事件
    public PrivateDialog setOnTipItemClickListener(OnTipItemClickListener listener)
    {
        this.listener = listener;
        return this;
    }
    // 设置标题
    public PrivateDialog title(String title)
    {
        this.title = title;
        return this;
    }
    // 协议内容
    public PrivateDialog message(String message)
    {
        this.message = message;
        return this;
    }
    // 右下角 同意按钮
    public PrivateDialog sure(String sure)
    {
        this.sure = sure;
        return this;
    }
    // 左下角 不同意按钮
    public PrivateDialog cancle(String cancle)
    {
        this.cancle = cancle;
        return this;
    }
    //创建并显示对话框
    public void create(Context mContext)
    {
        showConnectDialog(mContext);

    }
    // 隐私和协议文本样式及事件
    class CliclSpan extends ClickableSpan
    {
        Context mContext;
        Integer mNum;
        public CliclSpan() {
            super();
        }
        public CliclSpan(Context context,Integer num)
        {
            mContext = context;
            mNum = num;
        }
        @Override
        public void onClick(@NonNull View widget)
        {
            if (listener != null)
            {
                if(mNum == 1)
                {
                    listener.userClick();
                }else
                {
                    listener.termsClick();
                }
            }
        }

        @Override
        public void updateDrawState(@NonNull TextPaint ds)
        {
            ds.setColor(ContextCompat.getColor(mContext,R.color.red));
            ds.setUnderlineText(false);
        }
    }

}

新建布局private_dialog.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#fff"
        android:orientation="vertical">

        <TextView
            android:id="@+id/tv_sava_dialog_title"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:gravity="center"
            android:text="隐私设置"
            android:textColor="#bababa"
            android:textSize="17sp" />

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                android:id="@+id/ll_read_priavate"
                android:paddingLeft="10dp"
                android:paddingRight="10dp">

                <TextView
                    android:id="@+id/tv_sava_dialog_message"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="欢迎使用XXXXXXXXXX!在您使用前,请您认真阅读《用户服务协议》和《隐私政策》,以了解我们的服务内容和我们在收集和使用您相关个人信息时的处理规则"
                    android:textColor="#bababa"
                    android:layout_marginBottom="10dp"
                    android:textSize="12dp" />
            </LinearLayout>
        </RelativeLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:orientation="horizontal"
            >

            <TextView
                android:id="@+id/tv_sava_dialog_cancel"
                android:layout_width="0dp"
                android:layout_height="50dp"
                android:layout_marginTop="1dp"
                android:layout_weight="1"
                android:background="#a1a1a1"
                android:clickable="true"
                android:foreground="?android:selectableItemBackground"
                android:gravity="center"
                android:text="反对"
                android:textColor="#867575"
                android:textSize="15sp" />


            <TextView
                android:id="@+id/tv_sava_dialog_confirg"
                android:layout_width="0dp"
                android:layout_height="50dp"
                android:layout_marginLeft="1dp"
                android:layout_marginTop="1dp"
                android:layout_weight="1"
                android:background="#a1a1a1"
                android:clickable="true"
                android:foreground="?android:selectableItemBackground"
                android:gravity="center"
                android:text="同意"
                android:textColor="#efebeb"
                android:textSize="15sp" />

        </LinearLayout>
    </LinearLayout>

</LinearLayout>

使用方法

package com.mi.aquapark.applicationdemo;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import java.net.URL;
import java.util.Locale;

public class MainActivity extends AppCompatActivity
{
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        String msg="欢迎使用XXXXXXXXXX!在您使用前,请您认真阅读《用户服务协议》和《隐私政策》,以了解我们的服务内容和我们在收集和使用您相关个人信息时的处理规则";



        PrivateDialog.getInstace().message(msg).sure("同意").cancle("退出应用").setAgreementPos(27,35).setPrivacyPos(36,42)
                .setOnTipItemClickListener(new PrivateDialog.OnTipItemClickListener()
                {
                    @Override
                    public void cancleClick()
                    {
                        // 取消按钮-》退出应用
                        finishAffinity();
                    }

                    @Override
                    public void sureClick()
                    {
                        //同意按钮-》进入app
                    }

                    @Override
                    public void userClick()
                    {
                        //跳转网页至 用户服务协议
                        Intent intent=new Intent(Intent.ACTION_VIEW, Uri.parse(""));
                        startActivity(intent);
                    }

                    @Override
                    public void termsClick()
                    {

                        //跳转网页至 隐私政策
                        Intent intent=new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.voodoo.io/privacy-ch/"));
                        startActivity(intent);
                    }
                }).create(this);

    }

}

升级版

效果图

android 协议 时移 android 用户协议_ide_02

代码

创建Java PrivacyWindow

package com.unity3d.player;

import android.app.Dialog;
import android.content.Context;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextPaint;
import android.text.method.LinkMovementMethod;
import android.text.style.ClickableSpan;
import android.view.Display;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.core.content.ContextCompat;

public class PrivacyWindow {
    //region 属性
    String title = "温馨提示";
    String privacy = "欢迎使用XXXXXXXXXX!在您使用前,请您认真阅读《用户服务协议》和《隐私政策》,以了解我们的服务内容和我们在收集和使用您相关个人信息时的处理规则";
    String cancelBtn = "取消";
    String confirmBtn = "确认";
    private int[] agreementPos = new int[2];//协议文本位置
    private int[] privacyPos = new int[2];//隐私文本内容位置
    private EventListener listener;//处理事件
    private AlertDialog alert = null;           // 对话框

    //endregion
    //region 接口 隐私按钮事件
    public interface EventListener {
        void cancleClick();//取消按钮点击

        void ConfirmClick();//确认按钮点击

        void agreementClick();//协议文本点击

        void privacyClick();//隐私文本点击
    }

    //endregion
    //region 方法
    public PrivacyWindow setTitle(String str)//设置标题
    {
        title = str;
        return this;
    }

    public PrivacyWindow setPrivacy(String str)//设置隐私内容
    {
        privacy = str;
        return this;
    }

    public PrivacyWindow setCancel(String str)//设置取消按钮
    {
        cancelBtn = str;
        return this;
    }

    public PrivacyWindow setConfirm(String str)//设置确认按钮
    {
        confirmBtn = str;
        return this;
    }

    public  PrivacyWindow setAgreementPos(int start, int end)//设置协议文本位置
    {
        agreementPos[0] = start;
        agreementPos[1] = end;
        return this;
    }

    public  PrivacyWindow setPrivacyPos(int start, int end)//隐私文本内容位置
    {
        privacyPos[0] = start;
        privacyPos[1] = end;
        return this;
    }

    public  PrivacyWindow setPrivacyEvent(EventListener listener)//事件
    {
        this.listener = listener;
        return this;
    }

    public void Create(Context context)//创建隐私对话框
    {
        if (alert != null) {
            alert.dismiss();
        }
        View view = LayoutInflater.from(context).inflate(R.layout.view_dialog_custom, null, false);//对话框视图
        ((TextView) view.findViewById(R.id.titile)).setText(title);
        ((TextView) view.findViewById(R.id.cancelBtn)).setText(cancelBtn);
        ((TextView) view.findViewById(R.id.confirmBtn)).setText(confirmBtn);

        AlertDialog.Builder builder = new AlertDialog.Builder(context, R.style.TransparentDialog);
        builder.setView(view);
        builder.setCancelable(false);
        alert = builder.create();
        PrivacyEvent(view,context);
        alert.show();//显示对话框

        //开始代码  设置对话框一般屏幕 (下面代码不写则是默认大小)
        Window window =alert.getWindow();
        window.setGravity(Gravity.CENTER);
        WindowManager windowManager= window.getWindowManager();
        Display display=windowManager.getDefaultDisplay();
        WindowManager.LayoutParams params=alert.getWindow().getAttributes();
        params.width=display.getWidth();
        params.height=display.getHeight()/2;
        alert.getWindow().setAttributes(params);
        // 结束代码
    }
    private void PrivacyEvent(View view,Context context)//对话框点击事件
    {
        ((TextView) view.findViewById(R.id.cancelBtn)).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                alert.dismiss();
                if (listener != null)
                {
                    listener.cancleClick();
                }
            }
        });
        ((TextView) view.findViewById(R.id.confirmBtn)).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                alert.dismiss();
                if (listener != null)
                {
                    listener.ConfirmClick();
                }
            }
        });
        SpannableStringBuilder tvProtocol = new SpannableStringBuilder(privacy);
        tvProtocol.setSpan(new ClickableSpan() {
            @Override
            public void onClick(@NonNull View widget) {
                listener.agreementClick();
            }

            @Override
            public void updateDrawState(@NonNull TextPaint ds) {
                super.updateDrawState(ds);
//                ds.setColor(ContextCompat.getColor(context, R.color.red));
//                ds.setUnderlineText(true);
            }
        }, agreementPos[0], agreementPos[1], Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
        tvProtocol.setSpan(new ClickableSpan() {
            @Override
            public void onClick(@NonNull View widget) {
                listener.privacyClick();
            }
            @Override
            public void updateDrawState(@NonNull TextPaint ds) {
                super.updateDrawState(ds);
//                ds.setColor(ContextCompat.getColor(context, R.color.red));
//                ds.setUnderlineText(true);
            }
        }, privacyPos[0], privacyPos[1], Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
        ((TextView) view.findViewById(R.id.privacy)).setText(tvProtocol);
        ((TextView) view.findViewById(R.id.privacy)).setMovementMethod(LinkMovementMethod.getInstance());
    }
    //endregion
}

创建Layout view_dialog_custom.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/RelativeLayout1"
    android:background="@drawable/rounded_background"
    android:layout_width="match_parent"
    android:layout_height="500dp"
    android:orientation="vertical">
    <!--    标题-->
    <RelativeLayout
        android:id="@+id/titlelayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true">
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/titile"
            android:gravity="center"
            android:textSize="24dp"
            android:padding="10dp"
            android:textStyle="bold"
            android:text="温馨提示"/>
    </RelativeLayout>
    <!--   滚动文本-->
    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_above="@+id/my_buttonPanel"
        android:layout_below="@+id/titlelayout">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <TextView
                android:id="@+id/privacy"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginLeft="5dp"
                android:layout_marginRight="5dp"
                android:text="欢迎使用XXXXXXXXXX!在您使用前,请您认真阅读《用户服务协议》和《隐私政策》,以了解我们的服务内容和我们在收集和使用您相关个人信息时的处理规则"
                android:textSize="18sp"
                android:textStyle="bold" />
        </LinearLayout>
    </ScrollView>
    <!--    按钮-->
    <LinearLayout
        android:id="@+id/my_buttonPanel"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true">

        <TextView
            android:id="@+id/cancelBtn"
            android:layout_width="0dp"
            android:layout_height="50dp"
            android:layout_weight="1"
            android:background="@drawable/button_background_selector"
            android:gravity="center"
            android:text="反对"
            android:textSize="20sp"
            android:textStyle="bold" />

        <TextView
            android:id="@+id/confirmBtn"
            android:layout_width="0dp"
            android:layout_height="50dp"
            android:layout_weight="1"
            android:background="@drawable/button_background_selector"
            android:gravity="center"
            android:text="同意"
            android:textSize="20sp"
            android:textStyle="bold" />
    </LinearLayout>
</RelativeLayout>

在res/values/styles添加 <style ......</style>

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="TransparentDialog" parent="Theme.AppCompat.Dialog">
        <item name="android:windowBackground">#00000000</item>
    </style>
</resources>

在res/drawable 创建一下四个文件
rounded_background.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">

    <!-- 背景颜色 -->
    <solid android:color="#F8F5F5" />

    <!-- 边框的宽度和颜色颜色 -->
    <stroke android:width="2dip" android:color="#615959" />

    <!-- android:radius 弧形的半径 -->
    <corners android:radius="20dp"/>

    <!-- padding:Button里面的文字与Button边界的间隔 -->
    <padding
        android:left="10dp"
        android:top="10dp"
        android:right="10dp"
        android:bottom="10dp"
        />
</shape>

button_background_click.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">

    <!-- 背景颜色 -->
    <solid android:color="#C64A4A" />

    <!-- 边框的宽度和颜色颜色 -->
    <stroke android:width="2dip" android:color="#615959" />

    <!-- android:radius 弧形的半径 -->
    <corners android:radius="20dp"/>

    <!-- padding:Button里面的文字与Button边界的间隔 -->
    <padding
        android:left="10dp"
        android:top="10dp"
        android:right="10dp"
        android:bottom="10dp"
        />
</shape>

button_background_normal.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">

    <!-- 背景颜色 -->
    <solid android:color="#F8F5F5" />

    <!-- 边框的宽度和颜色颜色 -->
    <stroke android:width="2dip" android:color="#615959" />

    <!-- android:radius 弧形的半径 -->
    <corners android:radius="20dp"/>

    <!-- padding:Button里面的文字与Button边界的间隔 -->
    <padding
        android:left="10dp"
        android:top="10dp"
        android:right="10dp"
        android:bottom="10dp"
        />
</shape>

button_background_selector.xml

<?xml version="1.0" encoding="UTF-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:state_pressed  ="false"
        android:drawable="@drawable/button_background_normal"
        />
    <item
        android:state_pressed ="true"
        android:drawable="@drawable/button_background_click"
        />

</selector>

使用方法

package com.test.myapplication;

import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;

import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

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


        new PrivacyWindow().setTitle("温馨提示").setPrivacy("欢迎使用XXXXXXXXXX!在您使用前,请您认真阅读《用户服务协议》和《隐私政策》,以了解我们的服务内容和我们在收集和使用您相关个人信息时的处理规则")
                .setCancel("反对")
                .setConfirm("同意")
                .setAgreementPos(27, 35)
                .setPrivacyPos(36, 42)
                .setPrivacyEvent(new PrivacyWindow.EventListener() {
                    @Override
                    public void cancleClick() {
                        // 取消点击 隐私对话框关闭
                    }

                    @Override
                    public void ConfirmClick() {
                        // 确认点击 隐私对话框关闭
                    }

                    @Override
                    public void agreementClick() {
                        // 协议点击
                        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(""));
                        startActivity(intent);
                    }

                    @Override
                    public void privacyClick() {
                        // 隐私点击
                        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(""));
                        startActivity(intent);
                    }
                }).Create(this);

    }
}

改进描述

添加了圆角背景

修复隐私内容过多,按钮挤出屏幕

超简单的对话框

AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setCancelable(false);
builder.setTitle("重要提示"); 
builder.setMessage("欢迎使用XXXXXXXXXX!在您使用前,请您认真阅读《用户服务协议》和《隐私政策》,以了解我们的服务内容和我们在收集和使用您相关个人信息时的处理规则");
builder.setPositiveButton("同意", (dialog, which) ->
{
    dialog.dismiss();
});
builder.setNegativeButton("拒绝", (dialog, which) ->
{
    dialog.dismiss();
    System.exit(0);
});    
builder.create().show();

简单的显示在最上层视图,可以通过返回键退出。这个很有用!

AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("欢迎使用XXXXXXXXXX!在您使用前,请您认真阅读《用户服务协议》和《隐私政策》,以了解我们的服务内容和我们在收集和使用您相关个人信息时的处理规则");
builder.create().show();