搜索了一下关于android字间距,文章很多,但是真正能用的很少,刚好今天有这样的需求,参考了一下网上其它人的写法,自己写了一个,顺便开放源代码,供大家参考。

别人写的自定义的textview一般都有问题,少了一步计算textview控件的宽度的方法,少了一个计算文本居中对齐的方法所以写出来的文字是竖向排列的,

网上很多人说textView有一个属性android:textScaleX是调节字间距的,它的值是一个float型。这是错误的。真正的字间距需要自己去继承textview实现。

package com.huifeng.bufu.widget;import java.util.regex.Matcher;import java.util.regex.Pattern;import com.huifeng.bufu.R;import com.huifeng.bufu.tools.Tool;import android.content.Context;import android.graphics.*;import android.graphics.Paint.FontMetrics;import android.text.TextPaint;import android.text.TextUtils;import android.util.AttributeSet;import android.util.Log;import android.widget.TextView;public class MyTextView extends TextView {private Context context;private String content;private int Twidth;private int Lwidth;private int xstart;private TextPaint paint;private int xPadding;private int yPadding;private int textHeight;private int xPaddingMin;private String strr;int count;// 记录每个字的二维数组int[][] position;public MyTextView(Context context) {super(context);this.context = context;init();}public MyTextView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);this.context = context;init();}public MyTextView(Context context, AttributeSet attrs) {super(context, attrs);this.context = context;init();}public void setText(String str) {//拿到你传进来的文本值this.strr=str;}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {// TODO Auto-generated method stubsuper.onMeasure(widthMeasureSpec, heightMeasureSpec);int widthMode = MeasureSpec.getMode(widthMeasureSpec);int widthSize = MeasureSpec.getSize(widthMeasureSpec);if (widthMode == MeasureSpec.EXACTLY|| widthMode == MeasureSpec.AT_MOST) {//获取你textview控件的宽,方便做文字对齐的,如果你的textview控件需要设置宽高,也是在这里设置的Lwidth = widthSize;Twidth = strr.length()*Tool.dpToPx(context, 30);//算出所有文本的总宽度,因为我这里就只有一行字,并且居中对齐xstart = (Lwidth-Twidth)/2;//算出第一个文字的其实位置Log.i("MyTextView", "Lwidth"+Lwidth);getPositions(strr);//获取每一个文字的位置信息this.postInvalidate();//绘制} else {}}public void init() {paint = new TextPaint();paint.setColor(getResources().getColor(R.color.red));paint.setTypeface(Typeface.DEFAULT);paint.setTextSize(Tool.dpToPx(context, 30));FontMetrics fm = paint.getFontMetrics();// 得到系统默认字体属性textHeight = (int) (Math.ceil(fm.descent - fm.top) + 2);// 获得字体高度// 字间距xPadding = dip2px(this.getContext(), 4f);// 行间距yPadding = dip2px(this.getContext(), 10f);// 比较小的字间距(字母和数字应紧凑)xPaddingMin = dip2px(this.getContext(), 2f);}@Overrideprotected void onDraw(Canvas canvas) { super.onDraw(canvas); //画出每一个文字if (!TextUtils.isEmpty(content)) {for (int i = 0; i < count; i++) {canvas.drawText(String.valueOf(content.charAt(i)),position[i][0], position[i][1], paint);}}}public void getPositions(String content) {this.content = content;char ch;// 输入点的 x的坐标int x = xstart+Tool.dpToPx(context, 30)/2;// 当前行数int lineNum = 1;count = content.length();// 初始化字体位置数组position = new int[count][2];for (int i = 0; i < count; i++) {ch = content.charAt(i);String str = String.valueOf(ch);// 根据画笔获得每一个字符的显示的rect 就是包围框(获得字符宽度)Rect rect = new Rect();paint.getTextBounds(str, 0, 1, rect);int strwidth = rect.width();// 对有些标点做些处理if (str.equals("《") || str.equals("(")) {strwidth += xPaddingMin * 2;}// 当前字的宽度float textWith = strwidth+xPadding;// 没画字前预判看是否会出界x += textWith;Log.i("MyTextView", "canvas"+x);// 出界就换行if (x > Lwidth) {lineNum++;// 真实的行数加一x = xstart+Tool.dpToPx(context, 30)/2;} else {// 回到预判前的位置x -= textWith;}// 记录每一个字的位置position[i][0] = x;position[i][1] = textHeight * lineNum + yPadding * (lineNum - 1);Log.i("MyTextView", "position[i][1]"+position[i][0]);// 判断是否是数字还是字母 (数字和字母应该紧凑点)// 每次输入完毕 进入下一个输入位置准备就绪if (isNumOrLetters(str)) {x += textWith + xPaddingMin;} else {x += textWith + xPadding;}}// 根据所画的内容设置控件的高度this.setHeight((textHeight + yPadding) * lineNum);}// 工具类:判断是否是字母或者数字需要的话可以引用public boolean isNumOrLetters(String str) {String regEx = "^[A-Za-z0-9_]+$";Pattern p = Pattern.compile(regEx);Matcher m = p.matcher(str);return m.matches();}// 工具类:在代码中使用dp的方法(因为代码中直接用数字表示的是像素)public static int dip2px(Context context, float dip) {final float scale = context.getResources().getDisplayMetrics().density;return (int) (dip * scale + 0.5f);}}

有一点需要注意,一下,给这个控件setText的时候,一定要调用这个控件的setText(String str),而不是调用textview的setText(CharSequence text)这个方法,否则无法显示自定义的文本间距。


更多相关文章

  1. 自定义android用户控件,使用回调函数实现自定义事件
  2. Android之RemoteViews篇上————通知栏和桌面小控件

随机推荐

  1. Android Intent详解
  2. Android 解决65535的限制 使用android-su
  3. Android(安卓)GPRS的自动打开与关闭。
  4. 【初用Android Studio】快捷键之代码提示
  5. Jollen 的 Android 教學,#17: 樣式設計(St
  6. Android(安卓)开发艺术探索笔记之八 --
  7. <application android:debuggable="false
  8. 单板机上Android通过Modbus RTU操控外设
  9. android的selector-背景选择器
  10. 被谷歌控制的 Android(安卓)不是好 Andro