본문 바로가기
안드로이드 자바

[Android][JAVA] TextView와 DynamicTextView 비교: 텍스트 레이아웃 처리의 차이점

by teamnova 2024. 12. 19.
728x90

안드로이드 텍스트를 화면에 표시 할 때 사용하는 기본적인 뷰는 "TextView" 입니다

그러나 텍스트가 길어질 경우 TextView는 자동으로 줄 바꿈 처리나 텍스트가 화면을 넘어가는 것을 다루지 못 할 경우가 있습니다.

이에 비해 DynamicLayout을 활용한 텍스트뷰는 길이에 맞춰 동적으로 레이아웃을 조정하고 텍스트가 화면 크기에 맞게 자동으로 줄바꿈되는 특징이 있습니다.

 

TextView는 간단한 텍스트 표시용으로 사용되며, 기본적으로 텍스트를 한 줄로만 표시하고, 긴 텍스트에 대한 자동 줄바꿈 처리나 텍스트 크기 조정 기능이 부족합니다. 긴 텍스트를 표시할 때 화면을 벗어나거나, 스크롤을 통해 텍스트를 확인해야 할 수도 있습니다.

  • 장점: 사용이 간단하고 기본적인 텍스트 표시가 가능합니다.
  • 단점: 긴 텍스트에 대해 줄바꿈이나 화면 크기에 맞는 동적 조정이 자동으로 이루어지지 않습니다.

DynamicTextView는 DynamicLayout을 사용하여 텍스트를 동적으로 레이아웃에 맞게 처리합니다. 텍스트가 변경되면 자동으로 레이아웃을 갱신하며, 텍스트가 화면에 맞게 잘리거나 넘치지 않도록 조정됩니다.

  • 장점: 텍스트가 길어질 경우 자동으로 줄바꿈이 되어 화면에 맞게 표시됩니다. 텍스트의 크기나 화면 크기에 따라 레이아웃이 자동으로 조정됩니다.
  • 단점: 기본 TextView보다 설정이 복잡하고, 성능에 영향을 미칠 수 있습니다. 텍스트의 길이나 화면 크기에 따라 성능을 고려해야 할 수도 있습니다.

MainActivity


import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // 메인 레이아웃 생성
        LinearLayout mainLayout = new LinearLayout(this);
        mainLayout.setOrientation(LinearLayout.VERTICAL);
        mainLayout.setLayoutParams(new LinearLayout.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT
        ));

        // EditText 생성 및 설정
        EditText editText = new EditText(this);
        editText.setHint("여기에 텍스트를 입력하세요");
        LinearLayout.LayoutParams editParams = new LinearLayout.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.WRAP_CONTENT
        );
        editParams.setMargins(20, 20, 20, 20);
        editText.setLayoutParams(editParams);
        editText.setPadding(16, 16, 16, 16);

        // 일반 TextView 생성
        TextView normalTextView = new TextView(this);
        LinearLayout.LayoutParams normalParams = new LinearLayout.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.WRAP_CONTENT
        );
        normalParams.setMargins(20, 20, 20, 20);
        normalTextView.setLayoutParams(normalParams);
        normalTextView.setPadding(16, 16, 16, 16);
        normalTextView.setTextSize(20);

        // DynamicTextView 생성
        DynamicTextView dynamicTextView = new DynamicTextView(this);
        LinearLayout.LayoutParams dynamicParams = new LinearLayout.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.WRAP_CONTENT
        );
        dynamicParams.setMargins(20, 20, 20, 20);
        dynamicTextView.setLayoutParams(dynamicParams);

        // EditText의 텍스트 변경 리스너 추가
        editText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {}

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                // 두 뷰 모두 업데이트
                normalTextView.setText("일반 TextView:\n" + s.toString());
                dynamicTextView.updateText("DynamicTextView:\n" + s.toString());
            }

            @Override
            public void afterTextChanged(Editable s) {}
        });

        // 텍스트를 화면에 실시간으로 보여주기 위해 뷰 배치
        mainLayout.addView(editText);
        mainLayout.addView(new TextView(this)); // 텍스트 뷰 사이 구분용 추가
        mainLayout.addView(normalTextView); // 일반 TextView 추가
        mainLayout.addView(new TextView(this)); // 텍스트 뷰 사이 구분용 추가
        mainLayout.addView(dynamicTextView); // DynamicTextView 추가

        // 액티비티에 레이아웃 설정
        setContentView(mainLayout);
    }
}
DynamicTextView
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.text.DynamicLayout;
import android.text.Layout;
import android.text.TextPaint;
import android.view.View;

public class DynamicTextView extends View {
    private TextPaint textPaint;
    private DynamicLayout dynamicLayout;
    private String currentText = "";

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

    private void init() {
        // TextPaint 초기화
        textPaint = new TextPaint();
        textPaint.setAntiAlias(true);
        textPaint.setColor(Color.BLACK);
        textPaint.setTextSize(40);

        // 초기 DynamicLayout 생성
        updateDynamicLayout();
    }

    private void updateDynamicLayout() {
        dynamicLayout = new DynamicLayout(
                currentText,
                textPaint,
                getWidth() > 0 ? getWidth() - 100 : 800, // 여백을 고려한 너비
                Layout.Alignment.ALIGN_NORMAL,
                1.2f,
                0.0f,
                true
        );
        invalidate();
    }

    public void updateText(String newText) {
        currentText = newText;
        updateDynamicLayout();
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        if (w != oldw) {
            updateDynamicLayout();
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = dynamicLayout != null ?
                dynamicLayout.getHeight() + 100 : // 여백 추가
                200; // 기본 높이
        setMeasuredDimension(width, height);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (dynamicLayout != null) {
            canvas.save();
            canvas.translate(50, 50); // 여백 설정
            dynamicLayout.draw(canvas);
            canvas.restore();
        }
    }
}

 

 

시연 영상