Android项目封装一个登录页隐私协议弹窗工具包(一)
在写andorid原生时, 登录页面一般会显示用户注册服务协议和隐私政策协议. 直接硬编码的话, 感觉不太优雅, 也不利于组件的移植.
例如:
所以想封装一个支持无限添加的各种协议的工具包. 代码如下:
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多个标签.例如下面的:
以上就是该工具包的所有代码, 以及如何使用.
可以修改
ProtocolEnum
类, 添加自己相应的枚举, 使其支持更多的标签