前言
首先对于这个控件博主真的不知道取一个什么样的中文名字来解释,所以标题只能把控件的名字直接拎上来了,控件主要实现的功能就是显示一个可以配置大小和颜色的前置文本和后置文本,可能说的不太理解,没事,先看看效果图
从效果图上可以看到中间是一个正常文本,两边可以显示不同大小和颜色的文本,这有什么用呢?不知道大家有没有见过这样子的效果
这个效果自己使用SpannableString然后配合RelativeSizeSpan是完全可以做出来的,但是如果一个项目中很多地方都是需要使用的,复制粘贴代码不是一个好办法吧?
所以博主对这一点进行了抽取,就是为了显示一个可以配置大小和颜色的前置文本和后置文本
先看一个使用方法
<com.move.widget.RelativeSizeTextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5dp"
android:text="我是正常文本20sp"
android:textSize="20sp"
app:endText="我是蓝色后置文本为正常大小的150%"
app:end_proportion="1.5"
app:end_text_color="#0000FF"
app:start_proportion="0.8"
app:startText="我是前置红色文本为正常大小的80%"
app:start_text_color="#FF0000" />
使用方法是很清晰的,就是配置前置文本和后置文本的颜色和大小百分比
下面带大家来实现一下这个自定义控件
撸代码
其实我们唯一能够想到的就是通过继承TextView来拓展功能
定义出控件的属性
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="RelativeSizeTextView">
<!--开头和结束的文本-->
<attr name="startText" format="string" />
<attr name="endText" format="string" />
<!--统一设置开头和结束的tag的比例-->
<attr name="proportion" format="float" />
<!--开头的文本的比例-->
<attr name="start_proportion" format="float" />
<!--结束的文本的比例-->
<attr name="end_proportion" format="float" />
<!--开始文本和结束文本的颜色-->
<attr name="start_end_text_color" format="color" />
<attr name="start_text_color" format="color" />
<attr name="end_text_color" format="color" />
</declare-styleable>
</resources>
那我们的代码中肯定就有相对应的属性,并且在控件初始化的时候读取
/**
* 开头的文本
*/
private String startText;
/**
* 开始文本的颜色
*/
private int startTextColor = 0;
/**
* 结束的文本
*/
private String endText;
/**
* 结束文本的颜色
*/
private int endTextColor = 0;
/**
* 开始的比例
*/
private float startProportion;
/**
* 结束文本的比例
*/
private float endProportion;
读取自定义属性
public class RelativeSizeTextView extends AppCompatTextView {
public RelativeSizeTextView(Context context) {
this(context, null);
}
public RelativeSizeTextView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public RelativeSizeTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
// 开始读取自定义属性
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RelativeSizeTextView);
startText = a.getString(R.styleable.RelativeSizeTextView_startText);
endText = a.getString(R.styleable.RelativeSizeTextView_endText);
startProportion = a.getFloat(R.styleable.RelativeSizeTextView_proportion, 1f);
endProportion = a.getFloat(R.styleable.RelativeSizeTextView_proportion, 1f);
startProportion = a.getFloat(R.styleable.RelativeSizeTextView_start_proportion, startProportion);
endProportion = a.getFloat(R.styleable.RelativeSizeTextView_end_proportion, endProportion);
startTextColor = a.getColor(R.styleable.RelativeSizeTextView_start_end_text_color, startTextColor);
endTextColor = a.getColor(R.styleable.RelativeSizeTextView_start_end_text_color, endTextColor);
startTextColor = a.getColor(R.styleable.RelativeSizeTextView_start_text_color, startTextColor);
endTextColor = a.getColor(R.styleable.RelativeSizeTextView_end_text_color, endTextColor);
a.recycle();
setTagText(getText());
}
/**
* 开头的文本
*/
private String startText;
/**
* 开始文本的颜色
*/
private int startTextColor = 0;
/**
* 结束的文本
*/
private String endText;
/**
* 结束文本的颜色
*/
private int endTextColor = 0;
/**
* 开始的比例
*/
private float startProportion;
/**
* 结束文本的比例
*/
private float endProportion;
}
差最后一个根据这些属性值显示出效果的方法啦
上面提过,如果要实现可以使用SpannableString然后配合RelativeSizeSpan做出效果,那么内部就是这样子实现的,SpannableString不会使用可以自行搜索
/**
* 设置文本,调用的时候不要调用{@link android.widget.TextView#setText(CharSequence)}方法
* 而是调用此方法,不然没有效果
* 比如setTagText("hello") 输出效果为加上前置文本和后置文本:<前置文本>hello<后置文本>
*
* @param text
*/
public void setTagText(CharSequence text) {
if (!TextUtils.isEmpty(startText)) {
text = startText + text;
}
if (!TextUtils.isEmpty(endText)) {
text = text + endText;
}
SpannableString ss = new SpannableString(text);
RelativeSizeSpan startSpan = new RelativeSizeSpan(startProportion);
RelativeSizeSpan endSpan = new RelativeSizeSpan(endProportion);
if (!TextUtils.isEmpty(startText)) {
ss.setSpan(startSpan, 0, startText.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
if (startTextColor != 0) {
ForegroundColorSpan fcs = new ForegroundColorSpan(startTextColor);
ss.setSpan(fcs, 0, startText.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
}
}
if (!TextUtils.isEmpty(endText)) {
ss.setSpan(endSpan, text.length() - endText.length(), text.length(),
Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
if (endTextColor != 0) {
ForegroundColorSpan fcs = new ForegroundColorSpan(endTextColor);
ss.setSpan(fcs, text.length() - endText.length(), text.length(),
Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
}
}
super.setText(ss);
}
上面有一点很重要,就是我们在读取了自定义属性之后,就需要调用一次setTagText方法
因为这时候文本内部显示的是原文本,并没有加上我们的前后缀,所以我们在读取完毕自定义属性之后会获取当前的文本然后调用setTagText方法那么就可以在使用者不调用setTagText方法下默认显示出效果
源码下载
具体使用方法可以参考我的github地址: