Android自定義View五(繪制文本大小斟薇、多行多列居中)

一停巷、繪制文本

在Canvas中繪制文本耍攘,使用前面文章的坐標(biāo)系

1、drawText的幾種方法

public void drawText (String text, float x, float y, Paint paint)
public void drawText (String text, int start, int end, float x, float y, Paint paint)
public void drawText (CharSequence text, int start, int end, float x, float y, Paint paint)
public void drawText (char[] text, int index, int count, float x, float y, Paint paint)

public void drawText (String text, float x, float y, Paint paint)
x 畔勤、 y軸表示繪制文本左下角到坐標(biāo)

        mPaint.setColor(Color.RED);
        mPaint.setTextSize(50);
        String string="HeDan";
        canvas.drawText(string,0,0,mPaint);
xyText.png

public void drawText (String text, int start, int end, float x, float y, Paint paint)
繪制一部分Text,start表示從第幾個字符開始蕾各,end表示第幾個字符之前結(jié)束

//public void drawText (String text, int start, int end, float x, float y, Paint paint)
        canvas.drawText(string,0,3,0,0,mPaint);
starttext.png

public void drawText (CharSequence text, int start, int end, float x, float y, Paint paint)使用CharSequence繪制,方法庆揪,效果同上
public void drawText (char[] text, int index, int count, float x, float y, Paint paint)使用字符數(shù)組繪制式曲,方法,效果同上

2缸榛、drawPosText

給文本中到每個字符都設(shè)定一個坐標(biāo)吝羞,不推薦使用

3、drawTextOnPath

通過Path進(jìn)行文本繪制内颗,path是一個比較重要且有趣的東西钧排,在之后涉及知識中會進(jìn)行分析。

Path path = new Path();
path.lineTo(0,200);
canvas.drawTextOnPath(string,path,100,100,mPaint);

這里簡單寫一個均澳,path為一條從原點到(0,200)的直線恨溜,水平偏移量、垂直偏移量都設(shè)置為100,效果如下:

pathtext.png

二找前、文本居中

1糟袁、單行文本居中

a、 public void getTextBounds(String text, int start, int end, Rect bounds)

通過Rect獲取文本寬度和高度躺盛,方法如下

Rect rect = new Rect();
mPaint.getTextBounds(string,0,string.length(),rect);
 int width = rect.width();//文本寬度
int height = rect.height();//文本高度
b项戴、getFontMetrics(),getFontMetricsInt()用于返回字符串的測量,而兩個方法的區(qū)別就是返回值得類型颗品。返回值一共五個屬性:
  • Top: baseline到文本頂部的最大的距離
  • Ascent:baseline到文本頂部到推薦距離
  • Descent:baseline到文本底部到推薦距離
  • Bottom:baseline到文本底部到最大距離
  • Leading:兩行文本之間推薦到額外距離肯尺,一般為0(推薦不考慮)
String-Center.png

在Android的坐標(biāo)系中沃缘,向下為Y軸正方向,向上為Y軸負(fù)方向则吟,所部baseling之上到Top與Ascent都是負(fù)數(shù)槐臀,而baselin之下到Descent、Bottom都是正數(shù)氓仲。如果要讓字符串在垂直方向上居中水慨,則需要在縱坐標(biāo)上增加Asecent絕對值與descent的差。

 Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
 float textHeight=(-fontMetrics.ascent-fontMetrics.descent)/2;
 canvas.drawText(string,0,textHeight,mPaint);
ycentent.png
c敬扛、setTextAlign可以設(shè)置畫筆繪制文本到對齊方式晰洒,選擇center即可完成文本到水平居中
 Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
 float textHeight=(-fontMetrics.ascent-fontMetrics.descent)/2;
 mPaint.setTextAlign(Paint.Align.CENTER);
  canvas.drawText(string,0,textHeight,mPaint);
xcentent.png

d、measureText可以測量文本的寬度啥箭,即橫向長度谍珊,這樣也可以來完成居中設(shè)置,但在這之前急侥,需要恢復(fù)文本對齊方式至默認(rèn)設(shè)置(居左)砌滞。

     Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
     float textHeight=(-fontMetrics.ascent-fontMetrics.descent)/2;
    float textWidth = mPaint.measureText(string);
     canvas.drawText(string,-textWidth/2,textHeight,mPaint);

效果同上C。

2坏怪、多行文本居中

有設(shè)定好的字符串?dāng)?shù)組贝润,畫筆,畫布铝宵,坐標(biāo)點

  • 1打掘、drawText每次只能繪制一行,通過for循環(huán)
  • 2鹏秋、字符串?dāng)?shù)組大于1時尊蚁,每個字符到高度應(yīng)該為-top+bottom,總高度為length*(-top+bottom)
  • 3、偏移量就等于length*(-top+bottom)/2-bottom
  • 4侣夷、如果順序向上(Y負(fù)方向)排列到話枝誊,那么第i個字符串到高度就是-(length-i-1)*(-top+bottom)
  • 5、每個字符串高度減去偏移量惜纸,就應(yīng)該是每個字符串到baseline的y坐標(biāo)
    詳細(xì)代碼
 private void textCenter(String [] strings, Paint paint, Canvas canvas, Point point,Paint.Align aligin){
        paint.setTextAlign(aligin);
        Paint.FontMetrics fontMetrics = paint.getFontMetrics();
        float top=fontMetrics.top;
        float bottom=fontMetrics.bottom;
        int length=strings.length;
        float total=(length-1)*(-top+bottom)+(-fontMetrics.ascent+fontMetrics.descent);
        float offset=total/2-bottom;
        for(int i=0;i<length;i++){
            float yAxis=-(length-i-1)*(-top+bottom)+offset;
            canvas.drawText(strings[i]+"",point.x,point.y+yAxis,paint);
        }
    }

偏移量取值的變化叶撒,是因為在字符串的首尾兩個字符串,需要把top改成ascent耐版,bottom改成descent祠够。通過設(shè)置畫筆來完成橫向的居中,居左粪牲,居右古瓤。

使用代碼

String[] striings={"HeDan","是","一","個","好","學(xué)","生"};
//String[] striings={"床前明月光,","疑是地上霜。","舉頭望明月落君,","低頭思故鄉(xiāng)穿香。"};
Point point=new Point(0,0);
//textCenter(striings,mPaint,canvas,point, Paint.Align.CENTER);
textCenter(striings,mPaint,canvas,point, Paint.Align.LEFT);
ytext.png
ytext1.png
ytext2.png

3、多列文本

  • 1绎速、一個字符串?dāng)?shù)組
  • 2皮获、每個字符數(shù)組中獲取最寬到字符寬度我字符數(shù)組的寬度
  • 3、計算數(shù)組x坐標(biāo)纹冤,再掉用之前多行文本居中到代碼
居右詳細(xì)代碼
  private void textCenter(char[]  strings, Paint paint, Canvas canvas, Point point,Paint.Align aligin){
        paint.setTextAlign(aligin);
        Paint.FontMetrics fontMetrics = paint.getFontMetrics();
        float top=fontMetrics.top;
        float bottom=fontMetrics.bottom;
        int length=strings.length;
        float total=(length-1)*(-top+bottom)+(-fontMetrics.ascent+fontMetrics.descent);
        float offset=total/2-bottom;
        for(int i=0;i<length;i++){
            float yAxis=-(length-i-1)*(-top+bottom)+offset;
            canvas.drawText(strings[i]+"",point.x,point.y+yAxis,paint);
        }
    }

    private void rowTextRight(String[] strings,Paint paint,Canvas canvas,Point point){
        int length = strings.length;
        float len ,newLen;
        float total=0;
        for(int j=0;j<length;j++){
            char[] chars = strings[j].toCharArray();
            len=paint.measureText(chars[0]+"");
            for (int i=1; i<chars.length; i++){
                newLen = mPaint.measureText(chars[i]+"");
                len = Math.max(newLen,len);
            }
            point.x=point.x-(int)total;
            textCenter(chars,paint,canvas,point, Paint.Align.RIGHT);
            point.x = point.x + (int) total;
            total = total+len;
        }
    }

使用代碼

     String[] striings={"鵝歇攻,鵝乌助,鵝缠犀,","曲項向天歌乳讥,","白毛浮綠水,","紅掌撥清波知残,"};
        Point point=new Point(0,0);
        rowTextRight(striings,mPaint,canvas,point);
ytext3.png
居左詳細(xì)代碼
  private void rowTextLeft(String[] strings,Paint paint,Canvas canvas,Point point){
        int length = strings.length;
        float len ,newLen;
        float total=0;
        for(int j=0;j<length;j++){
            char[] chars = strings[j].toCharArray();
            len=paint.measureText(chars[0]+"");
            for (int i=1; i<chars.length; i++){
                newLen = mPaint.measureText(chars[i]+"");
                len = Math.max(newLen,len);
            }
            point.x=point.x+(int)total;
            textCenter(chars,paint,canvas,point, Paint.Align.LEFT);
            point.x = point.x - (int) total;
            total = total+len;
        }
    }
ytext.png
居中詳細(xì)代碼
  private void rowTextCenter(String[] strings,Paint paint,Canvas canvas,Point point){
        int length = strings.length;
        float len ,newLen;
        float total=0;
        for(int j=0;j<length;j++){
            char[] chars = strings[j].toCharArray();
            len=paint.measureText(chars[0]+"");
            for (int i=1; i<chars.length; i++){
                newLen = mPaint.measureText(chars[i]+"");
                len = Math.max(newLen,len);
            }
            total = total+len;
        }

        for(int j=0;j<length;j++){
            char[] chars = strings[j].toCharArray();
            len=paint.measureText(chars[0]+"");
            for (int i=1; i<chars.length; i++){
                newLen = mPaint.measureText(chars[i]+"");
                len = Math.max(newLen,len);
            }
            if(j==0){
                point.x=(int)-(total-len)/2;
            }
            textCenter(chars,paint,canvas,point, Paint.Align.CENTER);
            point.x=point.x+(int)len;
        }
    }

```
ytext.png

4靠瞎、文本自動換行居中

自動換行在Android 自定義View 一(初體驗onDraw(),自定義屬性,onMeasue()方法,測量換行)這里在介紹一個系統(tǒng)到方法:
StaticLayout,可以設(shè)置寬度,當(dāng)前行文本超過此寬度后求妹,進(jìn)行自動換行较坛,提供提供ALIGN_CENTER(居中)、ALIGN_NORMAL(標(biāo)準(zhǔn))扒最、ALIGN_OPPOSITE(與標(biāo)準(zhǔn)相反)三種對齊方式
詳細(xì)代碼:

  private void textCenter(String string, TextPaint textPaint, Canvas canvas, Point point, int width, Layout.Alignment align,float spacingmult,float spacingadd,boolean includepad){
        StaticLayout staticLayout = new StaticLayout(string,textPaint,width, align,spacingmult,spacingadd,includepad);
        canvas.save();
        canvas.translate(-staticLayout.getWidth()/2+point.x,-staticLayout.getHeight()/2+point.y);
        staticLayout.draw(canvas);
        canvas.restore();

    }

使用方法

  String mString="HeDan是一個好學(xué)生";
        TextPaint tp = new TextPaint();
        tp.setColor(Color.BLUE);
        tp.setStyle(Paint.Style.FILL);
        Point point=new Point(0,0);
        tp.setTextSize(50);
        textCenter(mString,tp,canvas,point,200,Layout.Alignment.ALIGN_CENTER,1.5f,0,false);
ytext.png

下面貼出學(xué)習(xí)源碼:

public class MultipleText extends View {
    private Paint mPaint;
    private float pWidth;
    private float pHeight;
    private int mWidth;
    private int mHeight;

    public MultipleText(Context context) {
        this(context, null);
    }

    public MultipleText(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MultipleText(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initPaint();
    }

    /**
     * 初始化畫筆
     */
    private void initPaint() {
        mPaint = new Paint();
        mPaint.setStyle(Paint.Style.FILL);//設(shè)置畫筆填充
        mPaint.setAntiAlias(true);//抗鋸齒
        mPaint.setColor(Color.parseColor("#52adff"));//設(shè)置畫筆顏色

    }

    ;

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.translate(mWidth / 2, mHeight / 2);

        mPaint.setStrokeWidth(10);//設(shè)置原點寬度
        canvas.drawPoint(0, 0, mPaint);//繪制原點
        canvas.drawPoints(new float[]{pWidth, 0, 0, pHeight, -pWidth, 0, 0, -pHeight}, mPaint);//繪制邊緣點*/

        mPaint.setStrokeWidth(1);//重新設(shè)置畫筆到寬度
        canvas.drawLine(-pWidth, 0, pWidth, 0, mPaint);//繪制X軸
        canvas.drawLine(0, -pHeight, 0, pHeight, mPaint);//繪制Y軸

        mPaint.setStrokeWidth(3);//設(shè)置箭頭寬度
        canvas.drawLines(new float[]{pWidth, 0, pWidth * 0.95f, -pWidth * 0.05f, pWidth, 0, pWidth * 0.95f, pWidth * 0.05f}, mPaint);//X軸箭頭
        canvas.drawLines(new float[]{0, pHeight, -pHeight * 0.05f, pHeight * 0.95f, 0, pHeight, pHeight * 0.05f, pHeight * 0.95f}, mPaint);//Y軸箭頭

        mPaint.setColor(Color.RED);
        mPaint.setTextSize(50);
        String string="HeDan";
        //public void drawText (String text, float x, float y, Paint paint)
        //canvas.drawText(string,0,0,mPaint);
        //public void drawText (String text, int start, int end, float x, float y, Paint paint)
       // canvas.drawText(string,0,3,0,0,mPaint);
      /*  Path path=new Path();
        path.lineTo(0,200);
        canvas.drawTextOnPath(string,path,100,100,mPaint);
        Rect rect = new Rect();
        mPaint.getTextBounds(string,0,string.length(),rect);
        int width = rect.width();//文本寬度
        int height = rect.height();//文本高度*/
       /* Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
        float textHeight=(-fontMetrics.ascent-fontMetrics.descent)/2;
        float textWidth = mPaint.measureText(string);
        canvas.drawText(string,-textWidth/2,textHeight,mPaint);*/

  /*      String[] striings={"鵝,鵝华嘹,鵝吧趣,","曲項向天歌,","白毛浮綠水耙厚,","紅掌撥清波强挫,"};
        Point point=new Point(0,0);
      textCenter(striings,mPaint,canvas,point, Paint.Align.LEFT);
        rowTextCenter(striings,mPaint,canvas,point);*/

        String mString="HeDan是一個好學(xué)生";
        TextPaint tp = new TextPaint();
        tp.setColor(Color.BLUE);
        tp.setStyle(Paint.Style.FILL);
        Point point=new Point(0,0);
        tp.setTextSize(50);
        textCenter(mString,tp,canvas,point,200,Layout.Alignment.ALIGN_CENTER,1.5f,0,false);



    }
    private void textCenter(String [] strings, Paint paint, Canvas canvas, Point point,Paint.Align aligin){
        paint.setTextAlign(aligin);
        Paint.FontMetrics fontMetrics = paint.getFontMetrics();
        float top=fontMetrics.top;
        float bottom=fontMetrics.bottom;
        int length=strings.length;
        float total=(length-1)*(-top+bottom)+(-fontMetrics.ascent+fontMetrics.descent);
        float offset=total/2-bottom;
        for(int i=0;i<length;i++){
            float yAxis=-(length-i-1)*(-top+bottom)+offset;
            canvas.drawText(strings[i],point.x,point.y+yAxis,paint);
        }
    }

    private void textCenter(char[]  strings, Paint paint, Canvas canvas, Point point,Paint.Align aligin){
        paint.setTextAlign(aligin);
        Paint.FontMetrics fontMetrics = paint.getFontMetrics();
        float top=fontMetrics.top;
        float bottom=fontMetrics.bottom;
        int length=strings.length;
        float total=(length-1)*(-top+bottom)+(-fontMetrics.ascent+fontMetrics.descent);
        float offset=total/2-bottom;
        for(int i=0;i<length;i++){
            float yAxis=-(length-i-1)*(-top+bottom)+offset;
            canvas.drawText(strings[i]+"",point.x,point.y+yAxis,paint);
        }
    }

    private void rowTextRight(String[] strings,Paint paint,Canvas canvas,Point point){
        int length = strings.length;
        float len ,newLen;
        float total=0;
        for(int j=0;j<length;j++){
            char[] chars = strings[j].toCharArray();
            len=paint.measureText(chars[0]+"");
            for (int i=1; i<chars.length; i++){
                newLen = mPaint.measureText(chars[i]+"");
                len = Math.max(newLen,len);
            }
            point.x=point.x-(int)total;
            textCenter(chars,paint,canvas,point, Paint.Align.RIGHT);
            point.x = point.x + (int) total;
            total = total+len;
        }
    }

    private void rowTextLeft(String[] strings,Paint paint,Canvas canvas,Point point){
        int length = strings.length;
        float len ,newLen;
        float total=0;
        for(int j=0;j<length;j++){
            char[] chars = strings[j].toCharArray();
            len=paint.measureText(chars[0]+"");
            for (int i=1; i<chars.length; i++){
                newLen = mPaint.measureText(chars[i]+"");
                len = Math.max(newLen,len);
            }
            point.x=point.x+(int)total;
            textCenter(chars,paint,canvas,point, Paint.Align.LEFT);
            point.x = point.x - (int) total;
            total = total+len;
        }
    }
    private void rowTextCenter(String[] strings,Paint paint,Canvas canvas,Point point){
        int length = strings.length;
        float len ,newLen;
        float total=0;
        for(int j=0;j<length;j++){
            char[] chars = strings[j].toCharArray();
            len=paint.measureText(chars[0]+"");
            for (int i=1; i<chars.length; i++){
                newLen = mPaint.measureText(chars[i]+"");
                len = Math.max(newLen,len);
            }
            total = total+len;
        }

        for(int j=0;j<length;j++){
            char[] chars = strings[j].toCharArray();
            len=paint.measureText(chars[0]+"");
            for (int i=1; i<chars.length; i++){
                newLen = mPaint.measureText(chars[i]+"");
                len = Math.max(newLen,len);
            }
            if(j==0){
                point.x=(int)-(total-len)/2;
            }
            textCenter(chars,paint,canvas,point, Paint.Align.CENTER);
            point.x=point.x+(int)len;
        }
    }

    private void textCenter(String string, TextPaint textPaint, Canvas canvas, Point point, int width, Layout.Alignment align,float spacingmult,float spacingadd,boolean includepad){
        StaticLayout staticLayout = new StaticLayout(string,textPaint,width, align,spacingmult,spacingadd,includepad);
        canvas.save();
        canvas.translate(-staticLayout.getWidth()/2+point.x,-staticLayout.getHeight()/2+point.y);
        staticLayout.draw(canvas);
        canvas.restore();

    }




    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mWidth = w;
        mHeight = h;
        pWidth = mWidth / 2 * 0.8f;//X軸邊緣原點到原點到距離
        pHeight = mHeight / 2 * 0.8f;//Y軸邊緣原點到原點到距離
    }

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市薛躬,隨后出現(xiàn)的幾起案子俯渤,更是在濱河造成了極大的恐慌,老刑警劉巖型宝,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件八匠,死亡現(xiàn)場離奇詭異,居然都是意外死亡趴酣,警方通過查閱死者的電腦和手機(jī)梨树,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來岖寞,“玉大人抡四,你說我怎么就攤上這事。” “怎么了指巡?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵淑履,是天一觀的道長。 經(jīng)常有香客問我藻雪,道長秘噪,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任阔涉,我火速辦了婚禮缆娃,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘瑰排。我一直安慰自己贯要,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布椭住。 她就那樣靜靜地躺著崇渗,像睡著了一般。 火紅的嫁衣襯著肌膚如雪京郑。 梳的紋絲不亂的頭發(fā)上宅广,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天,我揣著相機(jī)與錄音些举,去河邊找鬼跟狱。 笑死,一個胖子當(dāng)著我的面吹牛户魏,可吹牛的內(nèi)容都是我干的驶臊。 我是一名探鬼主播,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼叼丑,長吁一口氣:“原來是場噩夢啊……” “哼关翎!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起鸠信,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤纵寝,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后星立,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體爽茴,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年绰垂,在試婚紗的時候發(fā)現(xiàn)自己被綠了闹啦。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡辕坝,死狀恐怖窍奋,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤琳袄,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布江场,位于F島的核電站,受9級特大地震影響窖逗,放射性物質(zhì)發(fā)生泄漏址否。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一碎紊、第九天 我趴在偏房一處隱蔽的房頂上張望佑附。 院中可真熱鬧,春花似錦仗考、人聲如沸音同。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽权均。三九已至,卻和暖如春锅锨,著一層夾襖步出監(jiān)牢的瞬間叽赊,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工必搞, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留必指,地道東北人。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓恕洲,卻偏偏與公主長得像塔橡,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子研侣,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,762評論 2 345

推薦閱讀更多精彩內(nèi)容