项目忙先看效果和上代码
Video_20191129_043102_562.gif
/**
* 用户注册协议、用户隐私协议条款控件
*
* @author With You
* @version 5.0.0
* @date 2019/11/29 10:49
* @email 1713397546@qq.com
* @description
*/
public class UrAgreementTextView extends AppCompatTextView {
private final static String AgreementHintTag = "AgreementHintTag";
private SpannableString spannableString = null;
/**
* 协议全内容
*/
private String agreementContext = "我已阅读并同意《注册服务协议》,《用户隐私协议》与《风险揭示书》";
/**
* 协议提示文本
*/
private String agreementHintText = "我已阅读并同意";
/***
* 协议内容
*/
private CharSequence[] agreements = new String[]{"《注册服务协议》", "《用户隐私协议》", "《风险揭示书》"};
/**
* 协议全内容字体颜色
*/
private int agreementContextColor;
/**
* 协议提示文本颜色
*/
private int agreementHintColor;
/**
* 协议字体颜色
*/
private int agreementsColor;
private boolean isChecked = false;
private Drawable agreementCheckDrawable;
private Drawable agreementUnCheckDrawable;
public UrAgreementTextView(Context context) {
super(context);
}
public UrAgreementTextView(Context context, AttributeSet attrs) {
super(context, attrs);
initView(context, attrs);
}
public UrAgreementTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView(context, attrs);
}
private void initView(Context context, AttributeSet attrs) {
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.UrAgreementTextView);
String agreementContext = typedArray.getString(R.styleable.UrAgreementTextView_agreementContext);
String agreementHintText = typedArray.getString(R.styleable.UrAgreementTextView_agreementHintText);
CharSequence[] agreements = typedArray.getTextArray(R.styleable.UrAgreementTextView_agreementsId);
agreementContextColor = typedArray.getColor(R.styleable.UrAgreementTextView_agreementContextColor, 0xFF000000);
agreementHintColor = typedArray.getColor(R.styleable.UrAgreementTextView_agreementHintColor, 0xFF000000);
agreementsColor = typedArray.getColor(R.styleable.UrAgreementTextView_agreementsColor, 0xFFFF0000);
isChecked = typedArray.getBoolean(R.styleable.UrAgreementTextView_isChecked, false);
agreementCheckDrawable = typedArray.getDrawable(R.styleable.UrAgreementTextView_agreementCheckedId);
agreementUnCheckDrawable = typedArray.getDrawable(R.styleable.UrAgreementTextView_agreementUnCheckedId);
typedArray.recycle();
if (!TextUtils.isEmpty(agreementContext))
this.agreementContext = agreementContext;
if (!TextUtils.isEmpty(agreementHintText))
this.agreementHintText = agreementHintText;
if (agreements != null) {
for (int i = 0; i < agreements.length; i++) {
this.agreements[i] = agreements[i].toString();
}
}
this.setHighlightColor(getResources().getColor(android.R.color.transparent));
spannableString = new SpannableString(agreementContext);
setDrawable(isChecked ? agreementCheckDrawable : agreementUnCheckDrawable);
setAgreement();
}
/**
* 设置勾选按钮图片
*
* @param drawable
*/
private void setDrawable(Drawable drawable) {
if (drawable != null) {
drawable.setBounds(0, 0, dip2px(14), dip2px(14));
spannableString.setSpan(new UrImageSpan(drawable), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
setText(spannableString);
}
/**
* 设置协议内容
*/
public void setAgreement() {
//设置协议显示效果
for (int i = 0; i < agreements.length; i++) {
CharSequence agreement = agreements[i];
int firstIndex = agreementContext.indexOf(agreement.toString());
int lastIndex = firstIndex + agreement.length();
spannableString.setSpan(new MyClickableSpan(String.valueOf(i), agreement.toString(), agreementsColor),
firstIndex, lastIndex, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
}
//设置协议提示文本显示及点击效果
int firstHintIndex = agreementContext.indexOf(agreementHintText);
int lastHintIndex = firstHintIndex + agreementHintText.length();
spannableString.setSpan(new MyClickableSpan(AgreementHintTag, agreementHintText, agreementHintColor),
firstHintIndex, lastHintIndex, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
setText(spannableString);
setMovementMethod(LinkMovementMethod.getInstance());
}
private class MyClickableSpan extends ClickableSpan {
private String tag;
private String agreement;
private int color;
public MyClickableSpan(String tag, String agreement, int color) {
this.tag = tag;
this.agreement = agreement;
this.color = color;
}
@Override
public void onClick(View widget) {
if (tag.equals(AgreementHintTag)) //当点击同意协议时,勾选按钮
{
setDrawable(!isChecked ? agreementCheckDrawable : agreementUnCheckDrawable);
isChecked = !isChecked;
}
if (agreementClickListener != null)
agreementClickListener.clickListener(tag, agreement, isChecked);
}
@Override
public void updateDrawState(TextPaint ds) {
ds.setColor(color);
ds.setUnderlineText(false);
}
}
private OnAgreementClickListener agreementClickListener;
public void setAgreementClickListener(OnAgreementClickListener agreementClickListener) {
this.agreementClickListener = agreementClickListener;
}
public interface OnAgreementClickListener {
/**
* @param tag
* @param clickText 点击的文本
* @param isCheck 协议是否勾选
*/
void clickListener(String tag, String clickText, boolean isCheck);
}
/**
* 将dip或dp值转换为px值,保证尺寸大小不变
*
* @param dipValue
* @param dipValue (DisplayMetrics类中属性density)
* @return
*/
public int dip2px(float dipValue) {
final float scale = getResources().getDisplayMetrics().density;
return (int) (dipValue * scale + 0.5f);
}
}
自定义ImageSpan实现TextView中文图混排时文图的居中对齐
/**
* 自定义ImageSpan实现TextView中文图混排时文图的居中对齐
*
* @author With You
* @version 5.0.0
* @date 2019/11/29 14:47
* @email 1713397546@qq.com
* @description
*/
public class UrImageSpan extends ImageSpan {
public UrImageSpan(Context context, Bitmap bitmap) {
super(context, bitmap);
}
public UrImageSpan(Context context, Bitmap bitmap, int verticalAlignment) {
super(context, bitmap, verticalAlignment);
}
public UrImageSpan(Drawable drawable) {
super(drawable);
}
@Override
public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) {
try {
Drawable d = getDrawable();
Rect rect = d.getBounds();
if (fm != null) {
Paint.FontMetricsInt fmPaint = paint.getFontMetricsInt();
int fontHeight = fmPaint.bottom - fmPaint.top;
int drHeight = rect.bottom - rect.top;
int top = drHeight / 2 - fontHeight / 4;
int bottom = drHeight / 2 + fontHeight / 4;
fm.ascent = -bottom;
fm.top = -bottom;
fm.bottom = top;
fm.descent = top;
}
return rect.right;
} catch (Exception e) {
return 20;
}
}
@Override
public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) {
try {
Drawable d = getDrawable();
canvas.save();
int transY = 0;
transY = ((bottom - top) - d.getBounds().bottom) / 2 + top;
canvas.translate(x, transY);
d.draw(canvas);
canvas.restore();
} catch (Exception e) {
}
}
}
attrs.xml 文件
<declare-styleable name="UrAgreementTextView">
<attr name="agreementContext" format="string" />
<attr name="agreementHintText" format="string" />
<attr name="agreementsId" format="integer|reference" />
<attr name="agreementContextColor" format="color|reference" />
<attr name="agreementHintColor" format="color|reference" />
<attr name="agreementsColor" format="color|reference" />
<attr name="isChecked" format="boolean" />
<attr name="agreementCheckedId" format="reference" />
<attr name="agreementUnCheckedId" format="reference" />
</declare-styleable>
xml页面布局中的使用
<com.xx.xx.xx.UrAgreementTextView
android:id="@+id/tv_agreement"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:lineSpacingMultiplier="1.2"
android:padding="14dp"
android:textSize="@dimen/Assign_style_textSize14"
app:agreementCheckedId="@drawable/check_icon"
app:agreementContext="@string/agreement"
app:agreementContextColor="@color/text_color_666"
app:agreementHintColor="@color/text_color_666"
app:agreementUnCheckedId="@drawable/check_false"
app:agreementsColor="@color/blue"
app:agreementsId="@array/agreements"
app:isChecked="false" />
事件监听
mTvAgreement.setAgreementClickListener((tag, clickText, isChecked) -> {
UrUIToast.showText(mContext, clickText + isChecked);
});
网友评论