Android Canvas drawText 텍스트 가운데 에 있 는 일 들(도해)

18587 단어 androidcanvasdrawtext
1.앞 에 쓴다
사용자 정의 컨트롤 을 실현 하 는 과정 에서 중간 문 자 를 그 리 는 수요 가 많 기 때문에 인터넷 에서 관련 블 로 그 를 찾 아 보 았 습 니 다.항상 어 리 석 은 얼굴 로 자신 이 분석 해 보 겠 다 고 생각 했 습 니 다.여기 서 기록 하면 도움 이 되 었 으 면 좋 겠 습 니 다.
2.텍스트 그리 기
먼저 좌표 원점 을 컨트롤 센터 로 이동 합 니 다(기본 좌표 원점 은 화면 왼쪽 상단 에 있 습 니 다).이렇게 하면 직관 적 으로 보 이 는 다음 에 x,y 축 을 그립 니 다.이때 원점 은 위로 y 를 마이너스 로 하고 아래 y 를 플러스 로 하 며 왼쪽 x 를 마이너스 로 하고 오른쪽 x 를 플러스 로 하 며(0,0)좌표 로 텍스트 를 그립 니 다.

@Override
public void draw(Canvas canvas) {
 super.draw(canvas);
 //            
 canvas.translate(getWidth() / 2, getHeight() / 2);
 // x 
 canvas.drawLine(-getWidth() / 2, 0, getWidth() / 2, 0, paint);
 // y 
 canvas.drawLine(0, -getHeight() / 2, 0, getHeight() / 2, paint);

 //     
 paint.setTextSize(sp2px(50));
 canvas.drawText("YangLe", 0, 0, paint);
}
그림%1 개의 캡 션 을 편 집 했 습 니 다.

텍스트 그리 기
어,왜 그 려 진 텍스트 가 첫 번 째 상한 선 에 있 습 니까?y 좌 표 는 지정 한 0 이 아 닙 니까?왜 텍스트 는 x 축의 위 나 아래 가 아니 라 x 축 을 통과 하고 이런 의문 을 가지 고 계속 아래 를 보 았 습 니까?
우선 중요 한 종 류 를 보 세 요.

public static class FontMetrics {
 /**
 * The maximum distance above the baseline for the tallest glyph in
 * the font at a given text size.
 */
 public float top;
 /**
 * The recommended distance above the baseline for singled spaced text.
 */
 public float ascent;
 /**
 * The recommended distance below the baseline for singled spaced text.
 */
 public float descent;
 /**
 * The maximum distance below the baseline for the lowest glyph in
 * the font at a given text size.
 */
 public float bottom;
 /**
 * The recommended additional space to add between lines of text.
 */
 public float leading;
}
FontMetrics 클래스 는 Paint 의 내부 클래스 로 텍스트 를 그 릴 때의 관건 적 인 좌표 위 치 를 정의 합 니 다.이 값 들 이 무엇 을 대표 하 는 지 보 세 요.

관건 좌표
그림 을 보고 말 하기:
  • top:기선(x 축)에서 구역 의 최고점 을 위로 그립 니 다.이 값 은 마이너스
  • 입 니 다.
  • ascent:한 줄 의 텍스트 로 기선(x 축)에서 위로 그 려 진 추천 최고점 입 니 다.이 값 은 마이너스
  • 입 니 다.
  • baseline:기선,이 값 은 0
  • descent:한 줄 의 텍스트 로 기선(x 축)에서 아래로 그 려 진 추천 최저 점 입 니 다.이 값 은 플러스
  • 입 니 다.
  • bottom:기선(x 축)에서 구역 의 최저 점 을 아래로 그립 니 다.이 값 은 플러스
  • 입 니 다.
  • leading:추천 하 는 추가 줄 거 리 는 보통 0
  • 입 니 다.
    다음은 drawText 라 는 방법 을 살 펴 보 겠 습 니 다.
    
    /**
     * Draw the text, with origin at (x,y), using the specified paint. The origin is interpreted
     * based on the Align setting in the paint.
     *
     * @param text The text to be drawn
     * @param x The x-coordinate of the origin of the text being drawn
     * @param y The y-coordinate of the baseline of the text being drawn
     * @param paint The paint used for the text (e.g. color, size, style)
     */
    public void drawText(@NonNull String text, float x, float y, @NonNull Paint paint) {
     super.drawText(text, x, y, paint);
    }
    x,y 매개 변수의 의 미 를 중점적으로 보십시오.
  • x:텍스트 의 시작 x 좌표 그리 기
  • y:텍스트 를 그 리 는 baseline 은 y 축 방향 에 있 는 위치
  • 이해 하기 어렵 습 니 다.밤 을 들 어 보 세 요.위의 x,y 매개 변 수 는(0,0)입 니 다.이때 baseline 은 좌표계 에서 x 축 입 니 다.Y 축 부터 오른쪽으로 그립 니 다.x 축 을 텍스트 로 하 는 baseline 으로 그립 니 다.
    인자 전송(0,10)이 있 으 면 텍스트 를 그 리 는 baseline 은 x 축 에서 10px 를 아래로 이동 합 니 다.즉,y10 을 텍스트 로 하 는 baseline 으로 그립 니 다.y10 은 텍스트 를 그 리 는 baseline 이 y 축 방향 에 있 는 위치 입 니 다.
    메모:baseline 은 텍스트 를 그 리 는 기선 입 니 다.텍스트 영역 을 그 리 는 것 에 비해 x 축 에 해당 합 니 다.위로 마이너스(top,ascent)이 고 아래로 플러스(descent,bottom)입 니 다.그러나 이 x 축 은 컨트롤 의 x 축 이 아 닙 니 다.기억 하 세 요!!
    우리 가 윗글 에서 제기 한 의문 을 기억 하 십 니까?이제 설명 할 수 있 습 니 다.
    왜 그 려 진 텍스트 가 첫 번 째 상한 에 있 습 니까?
    우 리 는 좌표 원점 을 컨트롤 센터 로 옮 겼 기 때문에 텍스트 의 baseline 은 x 축 이 고 top,ascent 값 은 마이너스 이기 때문에 그 려 진 텍스트 는 첫 번 째 상한 에 있 습 니 다.
    y 좌 표 는 지정 한 0 이 아 닙 니까?왜 텍스트 는 x 축의 위 나 아래 가 아니 라 x 축 을 통과 합 니까?
    drawText 방법 은 기본 x 축 방향 을 왼쪽 에서 오른쪽으로 그립 니 다.y 축 방향 은 baseline 을 기준 으로 그립 니 다.글 의 baseline 은 x 축 이 고 baseline 을 기준 으로 텍스트 를 그 리 는 데 아직 거리 가 있 기 때문에 텍스트 는 x 축 을 통과 합 니 다.
    3.가운데 텍스트 그리 기
    앞에서 우 리 는 텍스트 를 어떻게 그 리 는 지,그리고 그 중의 매개 변수 와 좌표 의 의 미 를 배 웠 습 니 다.그 다음 에 본론 에 들 어가 서 가운데 텍스트 를 어떻게 그 릴 수 있 는 지 보 겠 습 니 다.
    먼저 그림 을 보 세 요.이때 텍스트 의 baseline 은 x 축 입 니 다.텍스트 를 가운데 에 표시 하려 면 텍스트 의 너비 와 높이 를 계산 해 야 합 니 다.
  • 너비:Paint 의 measuretext 방법 을 사용 하면 텍스트 의 너비
  • 를 얻 을 수 있 습 니 다.
  • 높이:텍스트 의 높이 는 실제 그리 기 구역 의 높이 입 니 다.(fontMetrics.descent-fontMetrics.ascent)로 얻 을 수 있 습 니 다.ascent 가 마이너스 이기 때문에 최종 적 으로 계산 한 것 은 둘 의 합
  • 입 니 다.
    현재 너비 가 있 습 니 다.텍스트 를 그 리 는 x 좌 표를 왼쪽으로 이동(너비/2)하면 수평 으로 가운데 로 이동 할 수 있 습 니 다.그러나 수직 방향 은 이렇게 할 수 없습니다.우 리 는 텍스트 를 아래 에서 baseline 을 텍스트 중심 으로 이동 하 는 거리,즉(높이/2-fontMetrics.descent)입 니 다.다음 그림 과 같 습 니 다.

    계산 baseLine Y
    현재 의 공식 은:
    
    float baseLineY
    = (fontMetrics.descent - fontMetrics.ascent) / 2 - fontMetrics.descent;
    = -fontMetrics.ascent / 2 - fontMetrics.descent / 2;
    = -(fontMetrics.ascent + fontMetrics.descent) / 2;
    = Math.abs(fontMetrics.ascent + fontMetrics.descent) / 2;
    Paint 에서 도 ascent 와 descent 값 을 얻 는 방법 이 있 기 때문에 공식 은 다음 과 같다.
    float baseLineY = Math.abs(paint.ascent() + paint.descent()) / 2;
    메모:이 공식 은 좌표 원점 에 비해 컨트롤 센터 에서 계산 합 니 다.좌표 원점 이 왼쪽 상단 에 있 으 면 baseLiney 는 컨트롤 높이 의 절반 을 더 해 야 합 니 다.
    float baseLineY = height / 2 + Math.abs(paint.ascent() + paint.descent()) / 2;
    코드 보기:
    
    @Override
    public void draw(Canvas canvas) {
     super.draw(canvas);
     //            
     canvas.translate(getWidth() / 2, getHeight() / 2);
     // x 
     canvas.drawLine(-getWidth() / 2, 0, getWidth() / 2, 0, paint);
     // y 
     canvas.drawLine(0, -getHeight() / 2, 0, getHeight() / 2, paint);
    
     //       
     paint.setTextSize(sp2px(50));
     paint.setColor(Color.GRAY);
     //    
     float textWidth = paint.measureText("YangLe'Blog");
     //   baseline y      
     float baseLineY = Math.abs(paint.ascent() + paint.descent()) / 2;
     canvas.drawText("YangLe'Blog", -textWidth / 2, baseLineY, paint);
    }
    가운데 보 셨 나 요?

    가운데 텍스트 그리 기
    큰 성 과 를 거두다.
    4.여러 줄 가운데 에 있 는 텍스트 그리 기
    메모:drawText 방법 은 여러 줄 의 텍스트 그리 기 를 지원 하지 않 습 니 다.
    4.1 방식 1
    자동 줄 바 꾸 기 를 지원 하 는 StaticLayout 사용 하기:
    
    /**
     *         (  1)
     *
     * @param canvas   
     */
    private void drawCenterMultiText1(Canvas canvas) {
     String text = "ABC";
    
     //   
     TextPaint textPaint = new TextPaint();
     textPaint.setAntiAlias(true);
     textPaint.setColor(Color.GRAY);
    
     //       50dp   
     StaticLayout staticLayout = new StaticLayout(text, textPaint, dp2px(50),
      Layout.Alignment.ALIGN_CENTER, 1f, 0f, false);
     canvas.save();
     // StaticLayout   (0,0)     
     //         ,         Canvas     
     canvas.translate(-staticLayout.getWidth() / 2, -staticLayout.getHeight() / 2);
     staticLayout.draw(canvas);
     canvas.restore();
    }
    Static Layout 의 구조 방법 파라미터 의 의 미 를 보십시오.
    
    public StaticLayout(CharSequence source, TextPaint paint, int width, Alignment align, 
       float spacingmult, float spacingadd, boolean includepad) {
     this(source, 0, source.length(), paint, width, align, spacingmult, spacingadd, includepad);
    }
  • source:줄 이 필요 한 텍스트
  • paint:화필 대상
  • width:layot 의 너비,텍스트 가 폭 을 초과 할 때 자동 으로 줄 바 꾸 기
  • align:layot 의 방식
  • spacingmult:상대 줄 간격,상대 글꼴 크기,1f 는 줄 간격 이 1 배 인 글꼴 높이
  • 를 나타 낸다.
  • spacingad:기본 줄 간격 오프셋 값,실제 줄 간격 은(spacingmult+spacingad)
  • 과 같 습 니 다.
  • includepad:매개 변 수 는 알 수 없 음
  • 효과 보기:

    StaticLayout
    static Layout 를 사용 하면 줄 마다 설정 한 폭 이 같 습 니 다.줄 마다 길이 가 다른 텍스트 를 표시 해 야 할 때 이 방식 은 사용 할 수 없습니다.걱정 하지 마 세 요.이어서 두 번 째 방식 을 살 펴 보 겠 습 니 다.
    4.2 방식 2
    drawText 를 순환 하 는 방식 으로 그립 니 다.그림 을 보고 말 합 니 다.

    계산 baseLine Y
    현재 A,B,C 세 줄 의 텍스트 를 그 려 야 합 니 다.빨간색 A 는 각 줄 의 텍스트 의 기본 적 인 그리 기 위 치 를 대표 합 니 다.녹색 선 은 각 줄 의 텍스트 의 baseline 을 대표 하고 x 축 은 빨간색 A 의 baseline 입 니 다.지금 은 세 가지 상황 으로 나 눌 수 있 습 니 다.
  • 텍스트 는 x 축 위 에 있 습 니 다.빨간색 A 의 baseline 은 a 거 리 를 위로 이동 하고 총 높이 의/2-텍스트 의 top 값(절대 값)
  • 텍스트 는 x 축 중간 에 있 습 니 다.빨간색 A 의 baseline 은 b 거 리 를 아래로 이동 합 니 다.계산 공식 은 한 줄 의 텍스트 가운데 공식
  • 을 참고 하 십시오.
  • 텍스트 는 x 축 아래 에 있 습 니 다.빨간색 A 의 baseline 은 c 거 리 를 아래로 이동 하고 총 높이 의/2-텍스트 의 bottom 값(절대 값)
  • 코드 보기:
    
    /**
     *         (  2)
     *
     * @param canvas   
     */
    private void drawCenterMultiText2(Canvas canvas) {
     String[] texts = {"A", "B", "C"};
    
     Paint.FontMetrics fontMetrics = paint.getFontMetrics();
     // top   
     float top = Math.abs(fontMetrics.top);
     // ascent   
     float ascent = Math.abs(fontMetrics.ascent);
     // descent,  
     float descent = fontMetrics.descent;
     // bottom,  
     float bottom = fontMetrics.bottom;
     //   
     int textLines = texts.length;
     //     
     float textHeight = top + bottom;
     //      
     float textTotalHeight = textHeight * textLines;
     //   
     float basePosition = (textLines - 1) / 2f;
    
     for (int i = 0; i < textLines; i++) {
      //     
      float textWidth = paint.measureText(texts[i]);
      //   baseline y      
      float baselineY;
    
      if (i < basePosition) {
       // x  ,   
       //     /2 -          -    top (   )
       baselineY = -(textTotalHeight / 2 - textHeight * i - top);
    
      } else if (i > basePosition) {
       // x  ,   
       //     /2 -          -    bottom (   )
       baselineY = textTotalHeight / 2 - textHeight * (textLines - i - 1) - bottom;
    
      } else {
       // x  ,   
       //                
       baselineY = (ascent - descent) / 2;
      }
    
      canvas.drawText(texts[i], -textWidth / 2, baselineY, paint);
     }
    }
    위의 그림 을 대조 하고 코드 를 보면 이해 하기 쉽 습 니 다.코드 중의 공식 이 최적화 할 수 있 는 부분 이 있다 고 생각 합 니 다.좋 은 방법 이 있 으 면 메 시 지 를 남 겨 주세요.
    중국어 버 전의 여러 줄 텍스트 를 보 세 요:

    다 중 줄 가운데 텍스트
    5.TextAlign
    Paint 의 TextAlign 속성 은 drawText 방법 에서 x 매개 변수의 상대 적 인 위 치 를 결정 합 니 다.
    밤 을 들다
  • Paint.Align.LEFT:기본 속성,x 좌 표 는 텍스트 를 그 리 는 가장 왼쪽 좌표
  • Paint.Align.CENTER:x 좌 표 는 텍스트 를 그 리 는 수평 중심 좌표
  • Paint.Align.Right:x 좌 표 는 텍스트 를 그 리 는 가장 오른쪽 좌표
  • 그림 을 보고 이해 하 세 요.

    Paint.Align.LEFT

    Paint.Align.CENTER

    Paint.Align.RIGHT
    6.텍스트 가운데 공식
    좌표 원점 은 컨트롤 센터 에 있 습 니 다:
    float baseLineY = Math.abs(paint.ascent() + paint.descent()) / 2;
    좌표 원점 은 컨트롤 왼쪽 상단 에 있 습 니 다:
    float baseLineY = height / 2 + Math.abs(paint.ascent() + paint.descent()) / 2;
    7.마지막 에 쓴다
    소스 코드 가 GitHub 에 올 라 왔 습 니 다.Fork 를 환영 합 니 다.괜 찮 은 것 같 으 면 Start 하 세 요!
    GitHub 전송 문
    본문 Demo 의 Apk 를 눌 러 주세요.
    총결산
    이상 은 이 글 의 전체 내용 입 니 다.본 논문 의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 참고 학습 가치 가 있 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 댓 글 을 남 겨 주 셔 서 저희 에 대한 지지 에 감 사 드 립 니 다.

    좋은 웹페이지 즐겨찾기