Android 实现一个隐私弹窗

news2025/5/6 0:52:13

效果图如下:

1. 设置同意、退出、点击用户协议、点击隐私协议的函数参数

2. 《用户协议》、《隐私政策》设置成可点击的,且颜色要区分出来

res/layout/dialog_privacy_policy.xml 文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/dialogRoot"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/bg_dialog_rounded"
    android:orientation="vertical"
    android:padding="24dp">

    <TextView
        android:id="@+id/tvTitle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="用户协议和隐私政策"
        android:textColor="#222222"
        android:textSize="18sp"
        android:textStyle="bold"
        android:gravity="center"
        android:layout_marginBottom="16dp"/>

    <TextView
        android:id="@+id/tvContent"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textColor="#444444"
        android:textSize="15sp"
        android:lineSpacingExtra="4dp" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_marginTop="24dp"
        android:gravity="center">

        <androidx.appcompat.widget.AppCompatButton
            android:id="@+id/btnExit"
            android:layout_width="0dp"
            android:layout_height="48dp"
            android:layout_weight="1"
            android:text="退出应用"
            android:textColor="#5E5C3F"
            android:background="@drawable/bg_button_outline"
            android:textSize="16sp" />

        <View
            android:layout_width="16dp"
            android:layout_height="0dp" />

        <androidx.appcompat.widget.AppCompatButton
            android:id="@+id/btnAgree"
            android:layout_width="0dp"
            android:layout_height="48dp"
            android:layout_weight="1.5"
            android:text="已阅读并同意"
            android:textColor="#FFFFFF"
            android:background="@drawable/bg_button_primary"
            android:textSize="16sp" />
    </LinearLayout>
</LinearLayout>

res/drawable/bg_dialog_rounded.xml 文件

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <solid android:color="#FFFFFF"/>
    <corners android:radius="14dp"/>
</shape>

res/drawable/bg_button_outline.xml文件

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <solid android:color="#FFFFFF" />
    <stroke android:width="0.5dp" android:color="#5E5C3F" />
    <corners android:radius="8dp" />
</shape>

res/drawable/bg_button_primary.xml文件

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <solid android:color="#5E5C3F" />
    <corners android:radius="8dp" />
</shape>

PrivacyPolicyDialog.kt 文件
import android.content.Context
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.text.SpannableString
import android.text.Spanned
import android.text.method.LinkMovementMethod
import android.text.style.ClickableSpan
import android.view.LayoutInflater
import android.view.View
import android.widget.Button
import android.widget.TextView
import androidx.appcompat.app.AlertDialog

class PrivacyPolicyDialog(
    private val context: Context,
    private val onAgree: () -> Unit,
    private val onExit: () -> Unit,
    private val onClickUserAgreement: () -> Unit,
    private val onClickPrivacyPolicy: () -> Unit
) {
    fun show() {
        val view = LayoutInflater.from(context).inflate(R.layout.dialog_privacy_policy, null)
        val tvContent = view.findViewById<TextView>(R.id.tvContent)
        val tvTitle = view.findViewById<TextView>(R.id.tvTitle)
        val btnAgree = view.findViewById<Button>(R.id.btnAgree)
        val btnExit = view.findViewById<Button>(R.id.btnExit)

        val content = "在您使用本应用之前,请您务必审慎阅读、充分理解“用户协议”和“隐私政策”各条款内容。详细资料请阅读:《用户协议》和《隐私政策》。"
        val spannable = SpannableString(content)

        val userStart = content.indexOf("《用户协议》")
        val userEnd = userStart + "《用户协议》".length
        val privacyStart = content.indexOf("《隐私政策》")
        val privacyEnd = privacyStart + "《隐私政策》".length

        spannable.setSpan(object : ClickableSpan() {
            override fun onClick(widget: View) {
                onClickUserAgreement()
            }
        }, userStart, userEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)

        spannable.setSpan(object : ClickableSpan() {
            override fun onClick(widget: View) {
                onClickPrivacyPolicy()
            }
        }, privacyStart, privacyEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)

        tvContent.text = spannable
        tvContent.movementMethod = LinkMovementMethod.getInstance()
        tvContent.highlightColor = Color.TRANSPARENT

        val dialog = AlertDialog.Builder(context)
            .setView(view)
            .setCancelable(false)
            .create()

        dialog.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))

        btnAgree.setOnClickListener {
            onAgree()
            dialog.dismiss()
        }

        btnExit.setOnClickListener {
            onExit()
            dialog.dismiss()
        }

        dialog.show()
    }
}

MainActivity.kt
 

package com.example.poemapp

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.ViewGroup
import android.widget.Button
import android.widget.Toast
import androidx.appcompat.app.AlertDialog

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        PrivacyPolicyDialog(
            context = this,
            onAgree = {
                Toast.makeText(this, "用户已同意", Toast.LENGTH_SHORT).show()
                // TODO: 记录已同意状态
            },
            onExit = {
                finish()
            },
            onClickUserAgreement = {
                // TODO: 跳转用户协议页面
            },
            onClickPrivacyPolicy = {
                // TODO: 跳转隐私政策页面
            }
        ).show()

    }


}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2356690.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[学成在线]22-自动部署项目

自动部署 实战流程 下边使用jenkins实现CI/CD的流程。 1、将代码使用Git托管 2、在jenkins创建任务&#xff0c;从Git拉取代码。 3、拉取代码后进行自动构建&#xff1a;测试、打包、部署。 首先将代码打成镜像包上传到docker私服。 自动创建容器、启动容器。 4、当有代…

Golang|使用函数作为参数和使用接口的联系

函数作为数据类型的一种&#xff0c;可以成为其他函数的参数。在 Go&#xff08;Golang&#xff09; 中&#xff0c;函数作为参数 和 接口&#xff08;interface&#xff09;&#xff0c;本质上都和抽象、灵活调用有关 —— 都是让代码更灵活、更可扩展的手段。不过它们各有侧重…

MATLAB技巧——norm和vecnorm两个函数讲解与辨析

在 MATLAB 中,norm 和 vecnorm 是两个用于计算向量或矩阵范数的函数,虽然它们的功能相似,但在使用场景和适用性上存在一些区别。本文将详细解释这两个函数的用途、功能以及如何选择合适的函数。 文章目录 norm函数用法范数类型vecnorm函数用法范数类型选择合适的函数示例对比…

ubuntu的libc 库被我 sudo apt-get --reinstall install libc6搞没了

我系统的libc 没了 今天为了运行一个开源的yuv 播放器&#xff0c;在运行的时候提醒 Inconsistency detected by ld.so: dl-call-libc-early-init.c: 37: _dl_call_libc_early_init: Assertion sym ! NULL failed!然后听从AI 的建议 当我去执行ls 时&#xff0c;系统提示 就这…

Ubuntu搭建Conda+Python开发环境

目录 一、环境说明 1、测试环境为ubuntu24.04.1 2、更新系统环境 3、安装wget工具 4、下载miniconda安装脚本 二、安装步骤 1、安装miniconda 2、source conda 3、验证版本 4、配置pip源 三、conda用法 1、常用指令 一、环境说明 1、测试环境为ubuntu24.04.1 2、更…

Python全流程开发实战:基于IMAP协议安全下载个人Gmail邮箱内所有PDF附件

在日常办公场景中&#xff0c;面对成百上千封携带PDF附件的邮件&#xff0c;手动逐一下载往往耗时耗力&#xff0c;成为效率瓶颈。如何通过代码实现“一键批量下载”&#xff1f;本文将以**“Gmail全量PDF附件下载工具”**开发为例&#xff0c;完整拆解从需求分析到落地交付的P…

Pytest-mark使用详解(跳过、标记、参数 化)

1.前言 在工作中我们经常使用pytest.mark.XXXX进行装饰器修饰&#xff0c;后面的XXX的不同&#xff0c;在pytest中有不同的作 用&#xff0c;其整体使用相对复杂&#xff0c;我们单独将其抽取出来做详细的讲解。 2.pytest.mark.skip()/skipif()跳过用例 import pytest #无条…

【浅尝Java】Java简介第一个Java程序(含JDK、JRE与JVM关系、javcdoc的使用)

&#x1f35e;自我激励&#xff1a;每天努力一点点&#xff0c;技术变化看得见 文章目录 Java语言概述Java是什么Java语言的重要性Java语言发展简史Java语言特性 第一个Java程序main方法示例运行Java程序JDK、JRE、JVM之间的关系注释基本规则注释规范 标识符关键字 Java语言概述…

项目三 - 任务2:创建笔记本电脑类(一爹多叔)

在本次实战中&#xff0c;我们通过Java的单根继承和多接口实现特性&#xff0c;设计了一个笔记本电脑类。首先创建了Computer抽象类&#xff0c;提供计算的抽象方法&#xff0c;模拟电脑的基本功能。接着定义了NetCard和USB两个接口&#xff0c;分别包含连接网络和USB设备的抽象…

Electron学习+打包

1. 什么是 Electron&#xff1f; Electron 是⼀个 跨平台桌⾯应⽤ 开发框架&#xff0c;开发者可以使⽤&#xff1a;HTML、CSS、JavaScript 等 Web 技术来构建桌⾯应⽤程序&#xff0c;它的本质是结合了 Chromium 和 Node.js &#xff0c;现在⼴泛⽤于桌⾯应 ⽤程序开发&a…

NumPy线性代数功能全解析:矩阵运算与方程求解实用指南

NumPy 是线性代数领域中高效的工具。它可以帮助完成矩阵运算和方程求解。本文将介绍 NumPy 中用于线性代数的常用函数。 矩阵乘法 矩阵乘法会根据两个矩阵生成一个新矩阵。具体做法是将第一个矩阵的每一行与第二个矩阵的每一列相乘&#xff0c;并将乘积相加&#xff0c;得到新…

《RabbitMQ 全面解析:从原理到实战的高性能消息队列指南》

一、RabbitMQ 核心原理与架构 1. 核心组件与工作流程 RabbitMQ 基于 AMQP 协议&#xff0c;核心组件包括 生产者&#xff08;Producer&#xff09;、交换机&#xff08;Exchange&#xff09;、队列&#xff08;Queue&#xff09; 和 消费者&#xff08;Consumer&#xff09;。…

Android Framework学习二:Activity创建及View绘制流程

文章目录 Window绘制流程Window Manager Service&#xff08;WMS&#xff09;SurfaceSurfaceFlinger 安卓View层次结构ActivityPhoneWindowActivity与PhoneWindow两者之间的关系ViewRootImplDecorViewDecorView 的作用DecorView 的结构总结 Activity创建流程View invalidate调用…

python如何在深度学习框架目标检测算法使用Yolov8训练道路汽车漆面车漆缺陷数据集 建立基于YOLOv8道路汽车漆面缺陷(划痕)检测系统

基于YOLOv8道路汽车漆面缺陷&#xff08;划痕&#xff09;检测系统 文章目录 1. 安装依赖2. 数据集准备与划分3. 数据预处理4. 配置YOLOv85. 训练和评估模型6. 推理与可视化7. 构建GUI应用程序 道路汽车漆面车漆缺陷检测数据集1221张 1类 汽车漆面缺陷检测YOLO数据集 1221张…

高性能、云原生的对象存储服务MinIO 详细介绍与案例应用

什么是MinIO&#xff1f; MinIO是一个高性能、云原生的对象存储服务&#xff0c;采用Apache License v2.0开源协议发布。它与Amazon S3云存储服务API兼容&#xff0c;适合构建高性能、可扩展的存储基础设施。支持大规模非结构化数据的存储&#xff0c;适合图片、视频、日志、备…

Arduino按键开关编程详解

一、按键开关的基本原理与硬件连接 1.1 按键开关的工作原理 按键开关是一种常见的输入设备&#xff0c;其核心原理基于机械触点的闭合与断开。当用户按下按键时&#xff0c;内部的金属片会连接电路两端&#xff0c;形成通路&#xff1b;松开按键后&#xff0c;金属片在弹簧作…

鸢尾花(Iris)数据集的多模型分类与可视化分析工具

该程序是一个鸢尾花(Iris)数据集的多模型分类与可视化分析工具,主要功能如下: 1. 数据加载与预处理 功能说明: 使用sklearn.datasets.load_iris()加载经典的鸢尾花数据集。将数据转为pandas.DataFrame,并将类别数字标签映射为中文类别名(山鸢尾、变色鸢尾、维吉尼亚鸢尾…

[蓝桥杯 2023 国 Python B] 划分 Java

import java.util.*;public class Main {public static void main(String[] args) {Scanner sc new Scanner(System.in);int[] arr new int[41];int sum 0;for (int i 1; i < 40; i) {arr[i] sc.nextInt();sum arr[i];}sc.close();int target sum / 2; // 最接近的两…

25.4.30数据结构|并查集 路径压缩

书接上回 上一节&#xff1a;数据结构|并查集 前言 &#xff08;一&#xff09;理论理解&#xff1a; 1、在QuickUnion快速合并的过程中&#xff0c;每次都要找根ID&#xff0c;而路径压缩让找根ID变得更加迅速直接。 2、路径压缩 针对的是findRootIndex()【查找根ID】进行的压…

MATLAB R2024a安装教程

安装步骤&#xff1a; 软件大小&#xff1a;约12.08G 安装环境&#xff1a;Win10~Win11或更高 下载好安装包&#xff0c;可以在网上找个安装包&#xff0c;比如我用国内镜像matlab地址github.com/futureflsl/matlab-chinese-mirror&#xff0c;这样下载稍微快点 1.开始安装…