android开发之自定义TextView设置字间距以及通过TextView控件属性设置行间距

众所周知,我们的TextView控件是没有设置字间距的属性滴!为了现实这一梦想,我玩起来了自定义TextView,从而来设置字间距:

自定义TextView设置字间距

第一步:创建自定义TextView:

package com.zanelove.ZaneTextView;

import android.content.Context;
import android.graphics.*;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.Display;
import android.view.WindowManager;
import android.widget.TextView;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 自定义TextView
 * Created by Zane on 2015/3/3.
 */
public class MyTextView extends TextView {
    private String content;
    private int width;
    private Paint paint;
    private int xPadding;
    private int yPadding;
    private int textHeight;
    private int xPaddingMin;
    int count;
    //记录每个字的二维数组
    int[][] position;

    public MyTextView(Context context) {
        super(context);
        init();
    }

    public MyTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public MyTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init() {
        paint = new Paint();
        //TODO 设置画笔颜色,也就是字体颜色
        paint.setColor(Color.parseColor("#000000"));
        paint.setTypeface(Typeface.DEFAULT);
        //TODO 设置画笔大小,也就是字体大小
        paint.setTextSize(dip2px(this.getContext(), 14f));
        Paint.FontMetrics fm = paint.getFontMetrics();// 得到系统默认字体属性
        // TODO 设置字体高度
        textHeight = (int) (Math.ceil(fm.descent - fm.top) + 2);
        //TODO 设置字间距
        xPadding = dip2px(this.getContext(), 4f);
        //TODO 设置行间距
        yPadding = dip2px(this.getContext(), 5f);
        //TODO 设置比较小的字间距(字母和数字应紧凑)
        xPaddingMin = dip2px(this.getContext(), 2f);
    }

    public void setText(String str) {
        //获得设备的宽
        WindowManager windowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
        Display display = windowManager.getDefaultDisplay();
        width = display.getWidth();
        getPositions(str);
        //重新画控件,将会调用onDraw方法
        this.invalidate();
    }

    @Override
    protected 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 = 0;
        //当前行数
        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();

            //TODO 对有些标点做些处理
            if (str.equals("《") || str.equals("(") || str.equals(",") || str.equals("。")) {
                strwidth += xPaddingMin * 2;
            }
            //当前行的宽度
            float textWith = strwidth;
            //没画字前预判看是否会出界
            x += textWith;
            //TODO 出界就换行(能满足Android下TextView中文换行需求)
            if (x > width) {
                lineNum++;// 真实的行数加一
                x = 0;
            } else {
                //回到预判前的位置
                x -= textWith;
            }
            //记录每一个字的位置
            position[i][0]=x;
            position[i][1]=textHeight * lineNum + yPadding * (lineNum - 1);
            //判断是否是数字还是字母 (数字和字母应该紧凑点)
            //每次输入完毕 进入下一个输入位置准备就绪
            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);
    }
}

PS:凡是标记为TODO的,你都可以进行修改,从而到达你所需要的效果!

第二步:在布局文件中,引用自定义TextView控件:


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent"
              android:background="#ffffff"
        >
    <com.zanelove.ZaneTextView.MyTextView
            android:id="@+id/myTextView"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            />
LinearLayout>

第三步:在代码中得到自定义TextView控件,从而设置文本:

public class MyActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        MyTextView textView = (MyTextView) this.findViewById(R.id.myTextView);
        textView.setText(getResources().getString(R.string.textview_src));
    }
}

第四步:最终效果!

android开发之自定义TextView设置字间距以及通过TextView控件属性设置行间距_第1张图片


通过TextView控件属性设置行间距

<TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:lineSpacingExtra="3dp"
        android:lineSpacingMultiplier="1.2"
        />

1、android:lineSpacingExtra=”xxdp” // 设置行间距,如“3dp”.
2、android:lineSpacingMultiplier=”xx” // 设置行间距的倍数,如“1.2”.

示例代码戳Here

你可能感兴趣的:(@android开发经验)