Android项目封装一个登录页隐私协议弹窗工具包(一)

在写andorid原生时, 登录页面一般会显示用户注册服务协议和隐私政策协议. 直接硬编码的话, 感觉不太优雅, 也不利于组件的移植.
例如:
Android项目封装一个登录页隐私协议弹窗工具包(一)
所以想封装一个支持无限添加的各种协议的工具包. 代码如下:

import android.content.Context; import android.graphics.Color; import android.text.Spannable; import android.text.SpannableStringBuilder; import android.text.TextPaint; import android.text.method.LinkMovementMethod; import android.text.style.ClickableSpan; import android.text.style.ForegroundColorSpan; import android.view.View; import android.widget.TextView;  import androidx.annotation.NonNull;  import java.util.LinkedList;  /**  * 首页隐私政策信息弹窗工具包  */ public class PrivateProtocolUtil {       public static void showDialog(Context context, TextView textView, String baseText, LinkedList<PrivateProtocolInfo> protocolInfos) {         // 要求必须大于0         if (protocolInfos == null || protocolInfos.size() <= 0) {             throw new IndexOutOfBoundsException("协议关键字列表不能为空");         }         // 对显示的文案进行组装,支持无限拼接,未注册手机登录将自动生成账号,且代表您已阅读并同意《xxx注册服务协议》和《xxx隐私政策》         StringBuilder valueTextBuilder = new StringBuilder(baseText);         for (int i = 0; i < protocolInfos.size(); i++) {             valueTextBuilder.append(protocolInfos.get(i).getValueText());             if (i < protocolInfos.size() - 1) {                 valueTextBuilder.append("和");             }         }         // 设置指定位置的文字为可点击的,并修改文字颜色         String valueText = valueTextBuilder.toString();         SpannableStringBuilder style = new SpannableStringBuilder(valueText);         int baseTextLength = baseText.length();         style.setSpan(new ForegroundColorSpan(Color.BLACK), 0, baseTextLength - 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);         for (int i = 0; i < protocolInfos.size(); i++) {             int itemLength = protocolInfos.get(i).getValueText().length();             int temLength = baseTextLength + itemLength;             if (i == 0) {                 style.setSpan(new CliclSpan(context, Color.parseColor(protocolInfos.get(i).getColor()), protocolInfos.get(i).getFlag(), protocolInfos.get(i).getOnTipItemClickListener()), baseTextLength, temLength, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);             } else {                 temLength++;                 style.setSpan(new CliclSpan(context, Color.parseColor(protocolInfos.get(i).getColor()), protocolInfos.get(i).getFlag(), protocolInfos.get(i).getOnTipItemClickListener()), ++baseTextLength, temLength, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);             }             baseTextLength = temLength;         }         textView.setText(style);         // 设置点击后的背景颜色为透明色         textView.setHighlightColor(Color.TRANSPARENT);         // 为指定字符设置链接属性,并激活链接         textView.setMovementMethod(LinkMovementMethod.getInstance());      }       public static class PrivateProtocolInfo {         // 文案内容         private String valueText;         // 标识符,在回调中区分,会返回         private ProtocolEnum flag;         // 文案内容的颜色         private String color;         // 回调监听         private OnTipItemClickListener onTipItemClickListener;          public PrivateProtocolInfo(String valueText, ProtocolEnum flag, String color, OnTipItemClickListener onTipItemClickListener) {             this.valueText = valueText;             this.flag = flag;             this.color = color;             this.onTipItemClickListener = onTipItemClickListener;         }          public String getValueText() {             return valueText;         }          public void setValueText(String valueText) {             this.valueText = valueText;         }          public ProtocolEnum getFlag() {             return flag;         }          public void setFlag(ProtocolEnum flag) {             this.flag = flag;         }          public String getColor() {             return color;         }          public void setColor(String color) {             this.color = color;         }          public OnTipItemClickListener getOnTipItemClickListener() {             return onTipItemClickListener;         }          public void setOnTipItemClickListener(OnTipItemClickListener onTipItemClickListener) {             this.onTipItemClickListener = onTipItemClickListener;         }     }      public enum ProtocolEnum {         USER_PROTOCOL,         PRIVATE_PROTOCOL;     }      public interface OnTipItemClickListener {          // 协议点击事件         void itemClick(ProtocolEnum protocolEnum);     }       private static class CliclSpan extends ClickableSpan {         private ProtocolEnum protocolEnum;         private OnTipItemClickListener onTipItemClickListener;         private int color;         private Context context;          public CliclSpan(Context context, int color, ProtocolEnum protocolEnum, OnTipItemClickListener onTipItemClickListener) {             this.context = context;             this.color = color;             this.protocolEnum = protocolEnum;             this.onTipItemClickListener = onTipItemClickListener;         }          @Override         public void onClick(@NonNull View widget) {             if (onTipItemClickListener == null) {                 return;             }             onTipItemClickListener.itemClick(protocolEnum);         }          @Override         public void updateDrawState(@NonNull TextPaint ds) {             ds.setColor(color);             ds.setUnderlineText(false);         }     } } 

上面封装的就是一个util包, 它支持理论上支持设置无限多个协议标签. 具体的逻辑请看代码中的注释.

下面展示如何使用, 代码如下:

// 用户注册协议 PrivateProtocolUtil.PrivateProtocolInfo userProtocolInfo = new PrivateProtocolUtil.PrivateProtocolInfo("《xxx注册服务协议》", PrivateProtocolUtil.ProtocolEnum.USER_PROTOCOL, "#00be32", new PrivateProtocolUtil.OnTipItemClickListener() {     @Override     public void itemClick(PrivateProtocolUtil.ProtocolEnum protocolEnum) {         if (PrivateProtocolUtil.ProtocolEnum.USER_PROTOCOL.equals(protocolEnum)) {             // 进行用户注册的协议弹出         }     } }); // 隐私政策协议 PrivateProtocolUtil.PrivateProtocolInfo privateProtocolInfo = new PrivateProtocolUtil.PrivateProtocolInfo("《xxx隐私政策》", PrivateProtocolUtil.ProtocolEnum.PRIVATE_PROTOCOL, "#00be32", new PrivateProtocolUtil.OnTipItemClickListener() {     @Override     public void itemClick(PrivateProtocolUtil.ProtocolEnum protocolEnum) {         if (PrivateProtocolUtil.ProtocolEnum.PRIVATE_PROTOCOL.equals(protocolEnum)) {             // 进行隐私政策的协议弹出         }     } }); LinkedList<PrivateProtocolUtil.PrivateProtocolInfo> linkedList = new LinkedList<>(); linkedList.add(userProtocolInfo); linkedList.add(privateProtocolInfo); PrivateProtocolUtil.showDialog(LoginActivity.this, tvAgreement, "未注册手机登录将自动生成账号,且代表您已阅读并同意", linkedList); 

以上就是工具包的使用方法, 可以看到,传入的是一个list, 所以可以设置n多个标签.例如下面的:
Android项目封装一个登录页隐私协议弹窗工具包(一)

以上就是该工具包的所有代码, 以及如何使用.

可以修改ProtocolEnum 类, 添加自己相应的枚举, 使其支持更多的标签