Android 自定义圆角TextView控件
在开发中遇到圆角背景大多都是shape资源文件 这样是最简单的方式之一,但是如果很多的圆角,资源文件要不断地创建不同的drawable,最终对打包Apk也不太友好,自定义一个控件来实现View多用
先来看下效果
自定义一个RectgleTextView
public class RectgleTextView extends AppCompatTextView {
private static final String EMPTY_SPACE = "\u3000";
private final Context mContext;
private int type = RECTANGLE;
private float mRadius;
private float mTopLeftRadius, mTopRightRadius, mBottomLeftRadius, mBottomRightRadius;
private int mStrokeColor;
private int mStrokeWidth;
private int mSoild;
private float mTextPadding;
private CharSequence mTextLeft;
private CharSequence mTextRight;
private ColorStateList mIconColor = null;
private int mCurIconColor;
private CharSequence iconString;
private ColorStateList mLeftColor = null;
private int mCurLeftColor;
private ColorStateList mRightColor = null;
private int mCurRightColor;
private float mLeftSize;
private float mRightSize;
private List<SpanContainer> leftContainer;
private List<SpanContainer> rightContainer;
private int mTextLeftStyle;
private int mTextRightStyle;
private int mTextCenterStyle;
//icon的index
private int iconIndex = 0;
//是否开启计算文字边界,开启后会以最大文字大小为View高度,并且会增加部分文字高度,防止部分英文类型y,g由于基线的原因无法显示完全
private boolean autoMaxHeight;
//渐变色
private ColorStateList startColor = null;
private ColorStateList centerColor = null;
private ColorStateList endColor = null;
//渐变方向
GradientDrawable.Orientation orientation;
public RectgleTextView(Context context) {
this(context, null);
}
public RectgleTextView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public RectgleTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.mContext = context;
initAttr(context, attrs);
init();
}
private void init() {
initIconFont();
initShape();
}
private void initIconFont() {
iconString = getText().toString();
int centerSize = iconString.length();
SpannableStringBuilder stringBuilder = new SpannableStringBuilder(getText());
if (!TextUtils.isEmpty(mTextLeft) || !TextUtils.isEmpty(mTextRight)) {
//增加空格
if (!TextUtils.isEmpty(mTextLeft)) {
if (mTextPadding != 0) {
stringBuilder.insert(0, EMPTY_SPACE);
iconIndex++;
}
stringBuilder.insert(0, mTextLeft);
iconIndex += mTextLeft.length();
}
if (!TextUtils.isEmpty(mTextRight)) {
if (mTextPadding != 0) {
stringBuilder.append(EMPTY_SPACE);
}
stringBuilder.append(mTextRight);
}
/*
* ==============
* 设置字和icon间距
* ==============
*/
if (mTextPadding != 0) {
//设置字和icon间距
if (!TextUtils.isEmpty(mTextLeft)) {
AbsoluteSizeSpan sizeSpan = new AbsoluteSizeSpan((int) mTextPadding);
stringBuilder.setSpan(sizeSpan, iconIndex - 1, iconIndex, Spanned
.SPAN_EXCLUSIVE_EXCLUSIVE);
}
if (!TextUtils.isEmpty(mTextRight)) {
AbsoluteSizeSpan sizeSpan = new AbsoluteSizeSpan((int) mTextPadding);
stringBuilder.setSpan(sizeSpan, iconIndex + centerSize, iconIndex +
centerSize + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
/*
* ==============
* 设置左边文字样式
* ==============
*/
setLeftTextAttr(stringBuilder);
/*
* ==============
* 设置右边文字样式
* ==============
*/
setRightTextAttr(centerSize, stringBuilder);
}
/*
* ==============
* 设置icon和字的颜色
* ==============
*/
if (mIconColor != null) {
int color = mIconColor.getColorForState(getDrawableState(), 0);
if (color != mCurIconColor) {
mCurIconColor = color;
}
ForegroundColorSpan foregroundColorSpan = new ForegroundColorSpan(mCurIconColor);
stringBuilder.setSpan(foregroundColorSpan, iconIndex, iconIndex + centerSize, Spanned
.SPAN_EXCLUSIVE_EXCLUSIVE);
} else {
mCurIconColor = getCurrentTextColor();
}
/*
* ==============
* 设置icon的字的样式
* ==============
*/
initTextStyle(mTextCenterStyle, stringBuilder, iconIndex, iconIndex + centerSize);
/*
* ==============
* 设置左右Span,记得调用前在**所有方法**前先clearSpan(),不然直接build,上一次的span任然保留着
* ==============
*/
if (leftContainer != null) {
for (SpanContainer container : leftContainer) {
for (Object o : container.spans) {
try {
stringBuilder.setSpan(o, container.start, container.end, container.flag);
} catch (Exception e) {
//please check invoke clearSpan() method first
}
}
}
}
if (rightContainer != null) {
int start = mTextPadding == 0 ? iconIndex + centerSize : iconIndex + centerSize + 1;
for (SpanContainer container : rightContainer) {
for (Object o : container.spans) {
try {
stringBuilder.setSpan(o, start + container.start, start + container.end,
container.flag);
} catch (Exception e) {
//please check invoke clearSpan() method first
}
}
}
}
setText(stringBuilder);
}
private void setRightTextAttr(int centerSize, SpannableStringBuilder stringBuilder) {
if (!TextUtils.isEmpty(mTextRight)) {
int start = mTextPadding == 0 ? iconIndex + centerSize : iconIndex + centerSize + 1;
/*
* ==============
* 设置右边字的粗体和斜体
* ==============
*/
initTextStyle(mTextRightStyle, stringBuilder, start, stringBuilder.length());
/*
* ==============
* 设置右边字的颜色
* ==============
*/
initTextRightColor(stringBuilder, start);
/*
* ==============
* 设置右边字的大小
* ==============
*/
initTextSize(stringBuilder, start, stringBuilder.length(), mRightSize, mCurRightColor);
}
}
private void initTextRightColor(SpannableStringBuilder stringBuilder, int start) {
if (mRightColor != null) {
int color = mRightColor.getColorForState(getDrawableState(), 0);
if (color != mCurRightColor) {
mCurRightColor = color;
}
ForegroundColorSpan foregroundRightColor = new ForegroundColorSpan(mCurRightColor);
stringBuilder.setSpan(foregroundRightColor, start, stringBuilder.length()
, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
} else {
mCurRightColor = getCurrentTextColor();
}
}
private void setLeftTextAttr(SpannableStringBuilder stringBuilder) {
if (!TextUtils.isEmpty(mTextLeft)) {
int end = mTextPadding == 0 ? iconIndex : iconIndex - 1;
/*
* ==============
* 设置左边字的粗体和斜体
* ==============
*/
initTextStyle(mTextLeftStyle, stringBuilder, 0, end);
/*
* ==============
* 设置左边字的颜色
* ==============
*/
initTextLeftColor(stringBuilder, end);
/*
* ==============
* 设置左边字的大小
* ==============
*/
initTextSize(stringBuilder, 0, end, mLeftSize, mCurLeftColor);
}
}
private void initTextSize(SpannableStringBuilder stringBuilder, int start, int end, float
textSize, int mCurColor) {
if (textSize != 0) {
CharacterStyle sizeSpan;
final int gravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK;
if (gravity == Gravity.CENTER_VERTICAL) {
sizeSpan = new EasyVerticalCenterSpan(textSize, mCurColor);
} else {
sizeSpan = new AbsoluteSizeSpan((int) textSize);
}
stringBuilder.setSpan(sizeSpan, start, end, Spanned
.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
private void initTextLeftColor(SpannableStringBuilder stringBuilder, int end) {
if (mLeftColor != null) {
int color = mLeftColor.getColorForState(getDrawableState(