본문 바로가기
Language & Framework/Dart & Flutter

[Flutter] Text 길이에 따라 폰트 크기 조절하는 4 가지 방법

by 6cess 2023. 11. 23.

1. MediaQuery.of(context).size

double screenWidth = MediaQuery.of(context).size.width;
double textSize = screenWidth < 390 ? 16.0 : 14.0;

 
 화면 사이즈에 따라 폰트 사이즈가 변하는 방식이다. 조금 투박하다. 모든 상황을 커버할 수는 없지만 넉넉하게 폰트 사이즈를 작게 잡는다면 가장 손쉽게 해결할 수 있는 방법이다.
 

2. FittedBox

내가 선호하는 방식이다. Flutter에서 제공하는 위젯 중 하나로 FittedBox 위젯에 주어지는 제약에 맞춰서 FittedBox 내부의 contents의 크기를 조정해준다. 내가 주로 사용하는 방식은 아래와 같다.

FittedBox(
  fit: BoxFit.scaleDown,
  child: Center(
    child: Text(
      strText,
    )
  ),
)

 
fit 속성에 따라 현재 상태에서 제약에 따라 줄어들게만 할 것인지(scaleDown), 좌우에 맞춰 최대로 커질지, 위아래에 맞춰 최대로 커질지 등등 결정할 수 있다. 문서를 참고하길.
 
https://api.flutter.dev/flutter/widgets/FittedBox-class.html

FittedBox class - widgets library - Dart API

Scales and positions its child within itself according to fit. In this example, the Placeholder is stretched to fill the entire Container. Try changing the fit types to see the effect on the layout of the Placeholder. link To create a local project with th

api.flutter.dev

 

3. TextPainter & LayoutBuilder

특정 테스트의 너비, 높이, 행 수 등을 측정하려는 경우에는 TextPainter를 사용하면 좋다. 텍스트가 화면에 어떻게 그려지는지 미리 계산할 수 있어서 유용하다. 특히 LayoutBuilder 와 함께 사용하면 텍스트가 어떻게 그려지는지 계산한 후 위젯 크기의 제약사항을 고려하여 텍스트를 수정할 수 있어서 유용한 조합이다.
 
우선 LayoutBuilder를 통해 텍스트 위젯의 위치의 제약 조건을 구한다.

LayoutBuilder(
  builder: (context, constraints) {
  	double maxWidth = constraints.maxWidth;
    
    return Text(
     
     ...
     
    );
  }
)

 
그 다음 작성하고 싶은 텍스트와 그 텍스트 정보를 TextPainter에 넣어 사이즈를 구한다.

LayoutBuilder(
  builder: (context, constraints) {
  	double maxWidth = constraints.maxWidth;
    
    // 원하는 텍스트 생성
    String text = 'This is a long text that needs to be responsive.';
    double fontSize = 16.0;

    // TextPainter를 사용하여 텍스트의 길이 측정
    TextPainter textPainter = TextPainter(
      text: TextSpan(
        text: text,
        style: TextStyle(fontSize: fontSize),
      ),
      maxLines: 1, // 1줄로 설정
      textDirection: TextDirection.ltr,
    )..layout();
    
    return Text( 
    
    ...

 
그 다음 적절한 폰트 사이즈를 구한다.

double calculateFontSize(TextPainter textPainter, double maxWidth, double fontSize) {
  // 텍스트가 너비 제약을 벗어나지 않도록 적절한 폰트 크기 계산
  double scaleFactor = 1.0;
	
    
  //텍스트 페인터로 측정한 텍스트의 너비 > 레이아웃의 최대 너비 일 경우
  if (textPainter.width > maxWidth) {
   //
   scaleFactor = maxWidth / textPainter.width;
  }

  return fontSize * scaleFactor;
}

 
전체 코드다.

LayoutBuilder(
  builder: (context, constraints) {
    // 텍스트의 최대 너비를 제한
    double maxWidth = constraints.maxWidth;

    // 원하는 텍스트 생성
    String text = 'This is a long text that needs to be responsive.';
    double fontSize = 16.0;

    // TextPainter를 사용하여 텍스트의 길이 측정
    TextPainter textPainter = TextPainter(
      text: TextSpan(
        text: text,
        style: TextStyle(fontSize: fontSize),
      ),
      maxLines: 1, // 1줄로 설정
      textDirection: TextDirection.ltr,
    )..layout();

    // 적절한 폰트 크기 계산
    fontSize = calculateFontSize(textPainter, maxWidth, fontSize);

    return Text(
      text,
      style: TextStyle(fontSize: fontSize),
      overflow: TextOverflow.ellipsis,
    );
  },
);
}

  double calculateFontSize(TextPainter textPainter, double maxWidth, double fontSize) {
    // 텍스트가 너비 제약을 벗어나지 않도록 적절한 폰트 크기 계산
    double scaleFactor = 1.0;

    if (textPainter.width > maxWidth) {
      scaleFactor = maxWidth / textPainter.width;
    }

    return fontSize * scaleFactor;
  }

 

 4. …

그냥...
Text 위젯의 overflow: ellipsis 속성을 쓰는 건 어떨까...