2017-01-21 3 views
7

내 자신의 사용자 정의 TextView을 작성해야하므로 캔버스에 텍스트를 그리는 데 대해 StaticLayout에 대해 학습했습니다. 이것은 Canvas.drawText()을 직접 사용하는 것보다 바람직합니다. 또는 documentation에 말합니다. 그러나 설명서는 어떻게 수행하는지 예제를 제공하지 않습니다. StaticLayout.Builder에 대한 막연한 참조가 더 새로운 방법입니다.Android에서 StaticLayout은 어떻게 사용됩니까?

예제는 here이지만 약간 날짜가 표시됩니다.

마침내 어떻게 작동했는지 아래에서 설명하겠습니다.

답변

40

StaticLayout (similar to DynamicLayout and BoringLayout)은 캔버스에 텍스트를 배치하고 그릴 때 사용됩니다. 이것은 일반적으로 다음 작업에 사용됩니다.

  • 배치 한 후 얼마나 많은 다중 행 텍스트를 측정 할지를 측정합니다.
  • 비트 맵 이미지에 텍스트 그리기.
  • 자체 텍스트 레이아웃을 처리하는 사용자 정의보기 만들기 (TextView이 포함 된 합성보기 만들기와 반대). TextViewStaticLayoutinternally을 사용합니다.

텍스트 크기를 측정

한 줄

만 한 줄의 텍스트가있는 경우, 당신은 Paint 또는 TextPaint으로 측정 할 수 있습니다.

String text = "This is some text." 

TextPaint myTextPaint = new TextPaint(); 
mTextPaint.setAntiAlias(true); 
mTextPaint.setTextSize(16 * getResources().getDisplayMetrics().density); 
mTextPaint.setColor(0xFF000000); 

float width = mTextPaint.measureText(text); 
float height = -mTextPaint.ascent() + mTextPaint.descent(); 

가 줄 바꿈이며 높이를 필요로하는 경우 여러 줄이

그러나, 다음은 StaticLayout를 사용하는 것이 좋습니다. 폭을 입력하면 StaticLayout에서 높이를 얻을 수 있습니다. 이 같은

String text = "This is some text. This is some text. This is some text. This is some text. This is some text. This is some text."; 

TextPaint myTextPaint = new TextPaint(); 
myTextPaint.setAntiAlias(true); 
myTextPaint.setTextSize(16 * getResources().getDisplayMetrics().density); 
myTextPaint.setColor(0xFF000000); 

int width = 200; 
Layout.Alignment alignment = Layout.Alignment.ALIGN_NORMAL; 
float spacingMultiplier = 1; 
float spacingAddition = 0; 
boolean includePadding = false; 

StaticLayout myStaticLayout = new StaticLayout(text, myTextPaint, width, alignment, spacingMultiplier, spacingAddition, includePadding); 

float height = myStaticLayout.getHeight(); 

새로운 API

당신이 새로운 StaticLayout.Builder (API 23에서 사용 가능) 사용하려는 경우, 당신이 얻을 수있는 레이아웃 :

StaticLayout.Builder builder = StaticLayout.Builder.obtain(text, 0, text.length(), myTextPaint, width); 
StaticLayout myStaticLayout = builder.build(); 

당신은 또한에 압정 수 있습니다 점 표기법을 사용하는 설정 :

StaticLayout.Builder builder = StaticLayout.Builder.obtain(text, 0, text.length(), myTextPaint, width) 
     .setAlignment(Layout.Alignment.ALIGN_NORMAL) 
     .setLineSpacing(spacingMultiplier, spacingAddition) 
     .setIncludePad(includePadding) 
     .setMaxLines(5); 
StaticLayout myStaticLayout = builder.build(); 

이미지에 텍스트 쓰기

StaticLayout을 사용하는 방법의 예는 this post을 참조하고 비트 맵을 반환합니다. 사용자 정의 텍스트 처리보기 여기

만들기

StaticLayout를 사용하여 사용자 정의보기의 예입니다. 그것은 단순한 TextView처럼 동작합니다. 텍스트가 너무 길어 화면에 맞지 않으면 자동으로 줄 바꿈을하고 높이를 늘립니다.

enter image description here

코드

MyView.java

public class MyView extends View { 

    String mText = "This is some text."; 
    TextPaint mTextPaint; 
    StaticLayout mStaticLayout; 

    // use this constructor if creating MyView programmatically 
    public MyView(Context context) { 
     super(context); 
     initLabelView(); 
    } 

    // this constructor is used when created from xml 
    public MyView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     initLabelView(); 
    } 

    private void initLabelView() { 
     mTextPaint = new TextPaint(); 
     mTextPaint.setAntiAlias(true); 
     mTextPaint.setTextSize(16 * getResources().getDisplayMetrics().density); 
     mTextPaint.setColor(0xFF000000); 

     // default to a single line of text 
     int width = (int) mTextPaint.measureText(mText); 
     mStaticLayout = new StaticLayout(mText, mTextPaint, (int) width, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0, false); 

     // New API alternate 
     // 
     // StaticLayout.Builder builder = StaticLayout.Builder.obtain(mText, 0, mText.length(), mTextPaint, width) 
     //  .setAlignment(Layout.Alignment.ALIGN_NORMAL) 
     //  .setLineSpacing(1, 0) // multiplier, add 
     //  .setIncludePad(false); 
     // mStaticLayout = builder.build(); 
    } 

    @Override 
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
     // Tell the parent layout how big this view would like to be 
     // but still respect any requirements (measure specs) that are passed down. 

     // determine the width 
     int width; 
     int widthMode = MeasureSpec.getMode(widthMeasureSpec); 
     int widthRequirement = MeasureSpec.getSize(widthMeasureSpec); 
     if (widthMode == MeasureSpec.EXACTLY) { 
      width = widthRequirement; 
     } else { 
      width = mStaticLayout.getWidth() + getPaddingLeft() + getPaddingRight(); 
      if (widthMode == MeasureSpec.AT_MOST) { 
       if (width > widthRequirement) { 
        width = widthRequirement; 
        // too long for a single line so relayout as multiline 
        mStaticLayout = new StaticLayout(mText, mTextPaint, width, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0, false); 
       } 
      } 
     } 

     // determine the height 
     int height; 
     int heightMode = MeasureSpec.getMode(heightMeasureSpec); 
     int heightRequirement = MeasureSpec.getSize(heightMeasureSpec); 
     if (heightMode == MeasureSpec.EXACTLY) { 
      height = heightRequirement; 
     } else { 
      height = mStaticLayout.getHeight() + getPaddingTop() + getPaddingBottom(); 
      if (heightMode == MeasureSpec.AT_MOST) { 
       height = Math.min(height, heightRequirement); 
      } 
     } 

     // Required call: set width and height 
     setMeasuredDimension(width, height); 
    } 

    @Override 
    protected void onDraw(Canvas canvas) { 
     super.onDraw(canvas); 
     // do as little as possible inside onDraw to improve performance 

     // draw the text on the canvas after adjusting for padding 
     canvas.save(); 
     canvas.translate(getPaddingLeft(), getPaddingTop()); 
     mStaticLayout.draw(canvas); 
     canvas.restore(); 
    } 
} 

activity_main.xml

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:id="@+id/activity_main" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:padding="@dimen/activity_vertical_margin" 
    tools:context="com.example.layoutpractice.MainActivity"> 

    <com.example.layoutpractice.MyView 
     android:layout_centerHorizontal="true" 
     android:background="@color/colorAccent" 
     android:padding="10dp" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content"/> 
</RelativeLayout> 
,363,210

노트

  • This, thisthis 사용자 정의 텍스트 처리 뷰를 만드는 방법을 학습에 유용했다.

  • 코드 또는 xml에서 설정할 수있는 사용자 지정 특성을 추가하려면 Creating a View Class을 참조하십시오.