Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 安卓自定義控件之可變字符串大小顏色控件

安卓自定義控件之可變字符串大小顏色控件

編輯:關於Android編程

這裡寫圖片描述“`
 

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

/**
* 創建時間:2016.8.11
* 創建人:王亮
* 功能作用:可變字符串文字大小顏色
* 邏輯:重繪制文字,使用記錄類(MySpannableString)記錄所要修改的區間信息,在使用重繪重新繪制,繪制之前根據用戶給的位置信息計算位置坐標,
* 缺點:只能單行顯示,一行排滿不會切換到下一行顯示
*/
public class MyTextView extends View {
private Paint paint;
private String changeText = “123456”;
private Float defaltTextSize = Float.valueOf(sp2px(10f));
private static Integer defaltTextColor = Color.BLACK;
private MySpannableString mySpannableString;
private static Context context;

public MyTextView(Context context) {
    super(context);
    this.context = context;
}
public MyTextView(Context context, AttributeSet attrs) {
    this(context, attrs,0);
}
public MyTextView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    this.context = context;
    TypedArray attr = context.obtainStyledAttributes(attrs, R.styleable.myText, defStyleAttr, 0);
    defaltTextSize = attr.getDimension(R.styleable.myText_defaltTextSize,defaltTextSize);
    defaltTextColor = attr.getColor(R.styleable.myText_defaltTextColor,defaltTextColor);
}


@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int height = getDefaultSize(getSuggestedMinimumHeight(),
            heightMeasureSpec);
    int width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
    setMeasuredDimension(width, height);

    viewWidth = getWidth();
    viewHeight = getHeight();

    paint = new Paint();
    paint.setColor(defaltTextColor);
    paint.setTextSize(defaltTextSize);
    paint.setAntiAlias(true);
}


@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    if(getHeight() != 0 && mySpannableString != null){

        List list = mySpannableString.getList();

        if(list .size() > 0 && list.get(0).getStart() > 0){//繪制第一個改變的起始點之前的文字
            canvas.drawText(changeText.substring(0,list.get(0).getStart())
                    ,showTextCenterX,showTextBaselineY,paint);
        }
        float showTextWidth = list.size() > 0 ?  paint.measureText(changeText,0,list.get(0).getStart()) : 0;//計算並保存每次已經繪制過得總的寬度,以保證下次繪制的部分在前一部分之後
        //繪制中間部分(不包含起始改變點之前以及最後一個繪制的結束點之後的部分)
        for(int i = 0 ; i < list.size();i++){
            Paint paintChange = new Paint();
            paintChange.setTextSize(list.get(i).getTextSize());
            paintChange.setColor(list.get(i).getTextColor());
            paintChange.setAntiAlias(true);
            canvas.drawText(changeText.substring(list.get(i).getStart(),list.get(i).getStop())
                        ,showTextCenterX + showTextWidth,showTextBaselineY,paintChange);//繪制需要改變的部分

            //計算並保存每次已經繪制過得總的寬度,以保證下次繪制的部分在前一部分之後
            showTextWidth += paintChange.measureText(changeText,list.get(i).getStart(),list.get(i).getStop());

            //繪制兩個要修改的區間的部分
            if(i + 1 != list.size() && list.get(i).getStop() < list.get(i + 1).getStart()){
                canvas.drawText(changeText.substring(list.get(i).getStop(),list.get(i + 1).getStart())
                            ,showTextCenterX + showTextWidth,showTextBaselineY,paint);

                //計算並保存每次已經繪制過得總的寬度,以保證下次繪制的部分在前一部分之後
                showTextWidth += paint.measureText(changeText,list.get(i).getStop(),list.get(i + 1).getStart());
            }
        }
        //繪制最後一個區間的終點之後的部分
        if(list.get(list.size() - 1).getStop() < changeText.length() ) {
            canvas.drawText(changeText.substring(list.get(list.size() - 1).getStop(), changeText.length())
                    , showTextCenterX + showTextWidth, showTextBaselineY, paint);
        }
    }
}

//設置文字以及顯示位置
public void setText(MySpannableString mySpannableString,int showTextAlign){
    this.mySpannableString = mySpannableString;
    this.showTextAlign = showTextAlign;
    this.changeText = mySpannableString.text;
    viewWidth = getWidth();
    viewHeight = getHeight();
}



/** 文字的方位 */
private int showTextAlign;
/** 左上角顯示  */
public static final int TEXT_ALIGN_LEFT_TOP                 = 0x00000001;
/** 左側中間顯示  */
public static final int TEXT_ALIGN_LEFT_CENTER              = 0x00000010;
/** 左側下方顯示  */
public static final int TEXT_ALIGN_LEFT_BOTTOM              = 0x00000100;
/** 右上角顯示  */
public static final int TEXT_ALIGN_RIGHT_TOP                = 0x00001000;
/** 右側中間顯示 */
public static final int TEXT_ALIGN_RIGHT_CENTER             = 0x00010000;
/** 右側下方顯示  */
public static final int TEXT_ALIGN_RIGHT_BOTTOM             = 0x00100000;
/** 中間頂部顯示  */
public static final int TEXT_ALIGN_CENTER_HORIZONTAL_TOP    = 0x00001000|0x00010000;
/** 中間下方顯示  */
public static final int TEXT_ALIGN_CENTER_HORIZONTAL_BOTTOM = 0x10000010;
/** 居中顯示  */
public static final int TEXT_ALIGN_CENTER                   = 0x10000100;
/** 居中靠上顯示  */
public static final int TEXT_ALIGN_CENTER_TOP               = 0x10001000;
/** 居中靠下顯示  */
public static final int TEXT_ALIGN_CENTER_BOTTOM            = 0x10010000;
/** 居中靠左顯示  */
public static final int TEXT_ALIGN_CENTER_LEFT              = 0x10100000;
/** 居中靠右顯示  */
public static final int TEXT_ALIGN_CENTER_RIGHT             = 0x11000000;
/** 居中靠左上顯示  */
public static final int TEXT_ALIGN_CENTER_LEFT_TOP          = 0x11000001;
/** 居中靠左下顯示  */
public static final int TEXT_ALIGN_CENTER_LEFT_BOTTOM       = 0x11000010;
/** 居中靠右上顯示  */
public static final int TEXT_ALIGN_CENTER_RIGHT_TOP         = 0x11000100;
/** 居中靠右下顯示  */
public static final int TEXT_ALIGN_CENTER_RIGHT_BOTTOM      = 0x11001000;
/**   */
/** 文本中軸線X坐標 */
private Float showTextCenterX;
/** 文本baseline線Y坐標 */
private Float showTextBaselineY;
/** 控件的寬度 */
private Integer viewWidth;
/** 控件的高度 */
private Integer viewHeight;
private Paint.FontMetrics fm;

@Override
protected void onLayout(boolean changed, int left, int top, int right,
                        int bottom) {
    viewWidth = getWidth();
    viewHeight = getHeight();
    if(changeText != null) {
        setTextLocation();
        postInvalidate();
    }
    super.onLayout(changed, left, top, right, bottom);
}

/**
 * 定位文本繪制的位置
 */
private void setTextLocation() {
    List list = mySpannableString.getList();
    int maxTextSize = 0;//最大的文字的大小
    float textWidth = 0;  //文本的寬度
    for(int i = 0 ; i < list.size() ; i++){//找出最大的字體的大小
        if(list.get(i).getTextSize() > maxTextSize){
            maxTextSize = list.get(i).getTextSize();
        }
        Paint paint = new Paint();
        paint.setTextSize(list.get(i).getTextSize());
        textWidth += paint.measureText(mySpannableString.text,list.get(i).getStart(),list.get(i).getStop());
    }

    Paint paint1 = new Paint();
    paint1.setTextSize(defaltTextSize);
    textWidth += paint1.measureText(mySpannableString.text,0,mySpannableString.text.length() - mySpannableString.changeCharNum);

    Paint paint = new Paint();
    paint.setTextSize(maxTextSize);
    fm = paint.getFontMetrics();

    float textHeight = fm.descent - fm.ascent;
    float textCenterVerticalBaselineY = viewHeight / 2 - fm.descent + (fm.descent - fm.ascent) / 2;
    switch (showTextAlign) {
        case TEXT_ALIGN_CENTER://居中
            showTextCenterX = (float)viewWidth / 2 - textWidth / 2;
            showTextBaselineY = textCenterVerticalBaselineY;
            break;
        case TEXT_ALIGN_LEFT_CENTER://居中靠最左
            showTextCenterX = 0f;
            showTextBaselineY = textCenterVerticalBaselineY;
            break;
        case TEXT_ALIGN_RIGHT_CENTER://居中靠最右
            showTextCenterX = viewWidth - textWidth;
            showTextBaselineY = textCenterVerticalBaselineY;
            break;
        case TEXT_ALIGN_CENTER_HORIZONTAL_BOTTOM://居中靠最下
            showTextCenterX = Float.valueOf(viewWidth / 2 - textWidth / 2);
            showTextBaselineY = viewHeight - fm.bottom;
            break;
        case TEXT_ALIGN_CENTER_HORIZONTAL_TOP://居中靠最上
            showTextCenterX = Float.valueOf(viewWidth / 2 - textWidth / 2);
            showTextBaselineY = -fm.ascent;
            break;
        case TEXT_ALIGN_LEFT_TOP://左上
            showTextCenterX = 0f;
            showTextBaselineY =  -fm.ascent;
            break;
        case TEXT_ALIGN_LEFT_BOTTOM://左下
            showTextCenterX = 0f;//
            showTextBaselineY = viewHeight - fm.bottom;
            break;
        case TEXT_ALIGN_RIGHT_TOP://右上
            showTextCenterX = viewWidth - textWidth;
            showTextBaselineY = -fm.ascent;
            break;
        case TEXT_ALIGN_RIGHT_BOTTOM://右下
            showTextCenterX = viewWidth - textWidth;
            showTextBaselineY = viewHeight - fm.bottom;
            break;
        case TEXT_ALIGN_CENTER_TOP://居中靠上
            showTextCenterX = (float)viewWidth / 2 - textWidth / 2;
            showTextBaselineY = textCenterVerticalBaselineY - textHeight / 2;
            break;
        case TEXT_ALIGN_CENTER_BOTTOM:/** 居中靠下顯示  */
            showTextCenterX = (float)viewWidth / 2 - textWidth / 2;
            showTextBaselineY = textCenterVerticalBaselineY + textHeight / 2;
            break;
        case TEXT_ALIGN_CENTER_LEFT:/** 居中靠左顯示  */
            showTextCenterX = (float)viewWidth / 2 - textWidth ;
            showTextBaselineY = textCenterVerticalBaselineY;
            break;
        case TEXT_ALIGN_CENTER_RIGHT:/** 居中靠右顯示  */
            showTextCenterX = (float)viewWidth / 2 + textWidth ;
            showTextBaselineY = textCenterVerticalBaselineY;
            break;
        case TEXT_ALIGN_CENTER_LEFT_TOP:/** 居中靠左上顯示  */
            showTextCenterX = (float)viewWidth / 2 - textWidth ;
            showTextBaselineY = textCenterVerticalBaselineY - textHeight ;
            break;
        case TEXT_ALIGN_CENTER_LEFT_BOTTOM:/** 居中靠左下顯示  */
            showTextCenterX = (float)viewWidth / 2 - textWidth ;
            showTextBaselineY = textCenterVerticalBaselineY + textHeight ;
            break;
        case TEXT_ALIGN_CENTER_RIGHT_TOP:/** 居中靠右上顯示  */
            showTextCenterX = (float)viewWidth / 2 + textWidth ;
            showTextBaselineY = textCenterVerticalBaselineY - textHeight ;
            break;
        case TEXT_ALIGN_CENTER_RIGHT_BOTTOM:/** 居中靠右下顯示  */
            showTextCenterX = (float)viewWidth / 2 + textWidth ;
            showTextBaselineY = textCenterVerticalBaselineY + textHeight ;
            break;
    }
}

/**
 * 將sp值轉換為px值,保證文字大小不變
 *
 * @param spValue
 *            (DisplayMetrics類中屬性scaledDensity)
 * @return
 */
public static int sp2px(float spValue) {
    final float fontScale = MyApplication.getContext().getResources().getDisplayMetrics().scaledDensity;
    return (int) (spValue * fontScale + 0.5f);
}


/**
 * 負責存儲要修改的文字以及要修改的區間的參數
 */
public static class MySpannableString{
    private List list = new ArrayList<>();
    private String text;
    private int changeCharNum = 0;

    public MySpannableString(String text) {
        this.text = text;
    }

    protected List getList() {
        return list;
    }

    /**
     *  設置要改變的文字所在的位置以及要改變的文字的大小以及顏色,可以多次設置,多次設置則改變多處位置
     * @param start
     * @param stop
     * @param textSize
     * @param textColor
     */
    public void setMySpans(int start,int stop,int textSize,Integer textColor){
        try {
            for(int i = 0; i < list.size() ; i++){
                if((start >= list.get(i).getStart() && start < list.get(i).getStop())
                        || (stop > list.get(i).getStart() && stop <= list.get(i).getStop())
                        || start > stop){
                    new Exception();
                    return;
                }
            }
        }catch (Exception e){
            Log.e("MySpannableString","End position can not be more than the previous starting point! "
                    +"or"
                    +" Starting position can not exceed the previous end! "
                    +"start > stop");//結束位不能超過以前的起點!或 起始位置不能超過以前的終點!或起點大於終點
        }
        MySpannableStringSetInfoDto dto;
        if(textColor == null){
            dto = new MySpannableStringSetInfoDto(start,stop,sp2px(textSize),defaltTextColor);
        }else {
            dto = new MySpannableStringSetInfoDto(start,stop,sp2px(textSize),textColor);
        }
        changeCharNum += stop - start;
        list.add(dto);
    }

}

/**
 * 修改區間參數類
 */
private static class MySpannableStringSetInfoDto implements Comparator{
    private int start;
    private int stop;
    private int textSize;
    private int textColor;


    protected MySpannableStringSetInfoDto(int start, int stop, int textSize, int textColor) {
        this.start = start;
        this.stop = stop;
        this.textSize = textSize;
        this.textColor = textColor;
    }

    protected int getStart() {
        return start;
    }

    protected int getStop() {
        return stop;
    }

    protected int getTextSize() {
        return textSize;
    }

    protected int getTextColor() {
        return textColor;
    }

    @Override
    public int compare(MySpannableStringSetInfoDto t1, MySpannableStringSetInfoDto t2) {
        if(t1.start > t2.start){
            return -1;
        }else if(t1.start < t2.start){
            return 1;
        }else {
            return 0;
        }
    }
}
}

“`

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved