标题带"精""热"。ReplacementSpan实践
来源:互联网 发布:免费电子期刊制作软件 编辑:程序博客网 时间:2024/06/03 14:53
今天看博客看到一篇TextView里画世界——ReplacementSpan实践
就是标题带小图片的这种
以前讨论群里也有人问过几次,群里的大神总是点到为止用SpannableString。
确实SpannableString能用图片替代字符实现该效果。
而这篇文章使用了ReplacementSpan自定义span达到实现效果 兴趣使然还没用过ReplacementSpan就开始试试
结果我水平不够看的云里雾里,在原基础上修改字体大小高度还会出现整个span失效
然后我就自己搞一个
首先自定义span要继承ReplacementSpan重写两个方法
第一个
public int getSize(Paint paint, CharSequence charSequence, intstart, intend, Paint.FontMetricsInt fontMetricsInt){
return 整个自定义长度;
}
也就是返回值就是自定义span的长度(这个返回长度不够会显示不全)
参数有 paint画笔 文字信息charSequence 开始和结束位置start,end Paint.FontMetricsInt包含文字的属性值 top,ascent等
第二个
public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint){
//绘制
}
参数有 画布,文字,span开始结束位置,上下左位置,y是文字基准线位置,画笔
感觉过去和自定义view有点像 好像比自定义view简单。
要实现效果就是背景绘制方块然后往其中写字 .java文件名是IconTextSpan.java
在构造函数中传入context和文本text
public IconTextSpan ( Context context,String text){ this.mContext = context; this.mText = text; initPaint(); }initPaint()初始化背景画笔和文字画笔
public void initPaint(){ mPaint = new Paint(); mPaint.setStyle(Paint.Style.FILL); mPaint.setColor(mContext.getResources().getColor(android.R.color.holo_blue_light)); mPaint.setAntiAlias(true); textPaint = new TextPaint(); textPaint.setColor(mContext.getApplicationContext().getResources().getColor(android.R.color.white)); mTextSize = changeintTopx(20); textPaint.setTextSize(mTextSize); textPaint.setAntiAlias(true); }
changeintTopx()是提出来的函数 吧字体大小sp转成px
public float changeintTopx( int i){ float pxsize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, i, mContext.getResources().getDisplayMetrics()); return pxsize; }
准备工作做完来重写getSize()
这里通过Paint.getTextBounds(字符串文本,诠释开始,诠释结束,矩形边界)和Rect.width
得到字体大小在mTextSize时mText的长度px
public int getSize(@NonNull Paint paint, CharSequence charSequence, int i, int i1, @Nullable Paint.FontMetricsInt fontMetricsInt) { Rect textRect = new Rect(); Paint apaint = new Paint(); apaint.setTextSize(mTextSize); apaint.getTextBounds(mText, 0, mText.length(), textRect); float padding = changeintTopx(4); return mWidth = (int)(textRect.width() + padding * 2); }如此一来span影响的文字必定会占据mwidth像素长度的位置,后续的没被影响的文字将会被往后推
然后来画draw()
public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) { Paint.FontMetrics metrics = paint.getFontMetrics(); float textHeight = metrics.descent - metrics.ascent; RectF bgRect = new RectF(x, top, x + mWidth, bottom); canvas.drawRoundRect(bgRect, changeintTopx(3), changeintTopx(3), mPaint);//圆角背景图 canvas.drawText(mText, x+changeintTopx(4), (y-(bottom-top-textHeight)/2), textPaint);//文字 }这里做了一个小处理 本来draw()只要写出
RectF bgRect = new RectF(x, top, x + mWidth, bottom);
canvas.drawRoundRect(bgRect, changeintTopx(3), changeintTopx(3), mPaint);//圆角背景图
canvas.drawText(mText, x, y, textPaint);//文字
就已经能看出效果了
恩就是文字靠在最角落 所以使用
Paint.FontMetrics metrics = paint.getFontMetrics();
float textHeight
来计算drawText()的绘制位置 为了让他能居中
FontMetrics 是文字测量属性集合,文字的绘制居然有这么多小内容
这里主要要看
基准点是baseline
Ascent是baseline之上至字符最高处的距离
Descent是baseline之下至字符最低处的距离
FontMetrics 文字测量集合以baseline的位置是y=0
metrics.descent得到正数 metrics.ascent等于负数
由图可知textHeight = metrics.descent - metrics.ascent;
然后推出canvas.drawText(mText, x+changeintTopx(4), (y-(bottom-top-textHeight)/2), textPaint);//文字
x轴位置设为x+changeintTopx(4)是因为
前面getsize()时多返回了2*changeintTopx(4)做圆角缓冲
这样自定义span基本完成
然后就是在文件中使用
String content = "Android是一种基于Linux的自由及开放源代码的操作系统,主要使用于移动设备,如智能手机和平板电脑,由Google公司和开放手机联盟领导及开发。尚未有统一中文名称,中国大陆地区较多人使用“安卓”或“安致”。";
StringBuilder stringBuilder = new StringBuilder();
IconTextSpan iconTextSpan = new IconTextSpan(activity.getApplication(),"热");
iconTextSpan.setbackgroudcolor(R.color.colorPrimaryDark);//主动更改span背景颜色
stringBuilder.append(" ");
stringBuilder.append(content);
SpannableString spannableString = new SpannableString(stringBuilder.toString());
spannableString.setSpan(iconTextSpan,0,1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
最后分粗糙的长这样
另外可以自己补充方法函数进去如设置字体大小背景颜色等(我就添加setbackgroudcolor,settextcolor,settextsize)
在setSpan()调用之前自定义span不会调用getsize()和draw() 所以在此之前都能更改
附点另一个大神展示的好几种自定义span样式
和我的整个代码
import android.content.Context;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.Rect;import android.graphics.RectF;import android.support.annotation.NonNull;import android.support.annotation.Nullable;import android.text.TextPaint;import android.text.style.ReplacementSpan;import android.util.TypedValue;/** * Created by ssh on 2017/11/27. */public class IconTextSpan extends ReplacementSpan { private Context mContext; private String mText; //Icon内文字 private float mTextSize; //文字大小 private Paint mPaint; private int mWidth; private float mRightMargin; private TextPaint textPaint; public IconTextSpan ( Context context,String text){ this.mContext = context; this.mText = text; initPaint(); } public void initPaint(){ mPaint = new Paint(); mPaint.setStyle(Paint.Style.FILL); mPaint.setColor(mContext.getResources().getColor(android.R.color.holo_blue_light)); mPaint.setAntiAlias(true); textPaint = new TextPaint(); textPaint.setColor(mContext.getApplicationContext().getResources().getColor(android.R.color.white)); mTextSize = changeintTopx(20); textPaint.setTextSize(mTextSize); textPaint.setAntiAlias(true); } /** * 设置背景颜色 * @param backgroudcolor */ public void setbackgroudcolor(int backgroudcolor){ mPaint.setColor(mContext.getResources().getColor(backgroudcolor)); } /** * 设置字体颜色 * @param textcolor */ public void settextcolor(int textcolor){ textPaint.setColor(mContext.getResources().getColor(textcolor)); } /** * 设置右边距 * * @param rightMarginDpValue */ public void setRightMarginDpValue(int rightMarginDpValue) { this.mRightMargin = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, rightMarginDpValue, mContext.getResources().getDisplayMetrics()); } /** * 设置字体大小 * @param textSize */ public void setTextSize(int textSize){ this.mTextSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, textSize, mContext.getResources().getDisplayMetrics()); textPaint.setTextSize(mTextSize); } @Override public int getSize(@NonNull Paint paint, CharSequence charSequence, int i, int i1, @Nullable Paint.FontMetricsInt fontMetricsInt) { Rect textRect = new Rect(); Paint apaint = new Paint(); apaint.setTextSize(mTextSize); apaint.getTextBounds(mText, 0, mText.length(), textRect); float padding = changeintTopx(4); return mWidth = (int)(textRect.width() + padding * 2); } @Override public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) { Paint.FontMetrics metrics = paint.getFontMetrics(); float textHeight = metrics.descent - metrics.ascent; RectF bgRect = new RectF(x, top, x + mWidth, bottom); canvas.drawRoundRect(bgRect, changeintTopx(3), changeintTopx(3), mPaint); canvas.drawText(mText, x+changeintTopx(4), (y-(bottom-top-textHeight)/2), textPaint); } public float changeintTopx( int i){ float pxsize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, i, mContext.getResources().getDisplayMetrics()); return pxsize; }}
- 标题带"精""热"。ReplacementSpan实践
- TextView里画世界——ReplacementSpan实践
- Oracle 热备份实践
- Sophix热修复实践
- Tinker实践:一步步带你集成Tinker,让你的APP也用上热修复,告别重复性更新
- 带标题的表格
- 带标题的RecyclerViewAdapter
- Android ReplacementSpan 文字对齐问题
- 标题:Struts 上机实践
- Golang热加载配置实践
- android热修复实践-andfix
- AJAX应用带标题更新
- AJAX应用带标题更新
- 图片切换,带标题文字
- android自带标题样式
- 实现带标题的ListView
- swing带标题的边框
- 网页标题带小图标
- jquery获取,改变页面内容
- visibilitychange事件判断当前页面——可见性的状态
- Mysql ubuntu 定时备份
- 使用guest用户远程连接RabbitMQ用户名密码错误
- SSM项目从零开始到入门003-maven集中定义依赖版本号
- 标题带"精""热"。ReplacementSpan实践
- 两年Java开发工作经验面试总结
- linux下,用终端打开软件,例如matlab,如何解除终端占用
- Android 手势检测---GestureDetector
- MVC框架集成
- Solve the android adb connect problem(Linux)
- 1014. 福尔摩斯的约会 (20)
- 设计模式-java工厂模式1(简单工厂模式+工厂方法模式)
- ise使用