Vintage appMaker의 Tech Blog

[flutter] RichText 활용 본문

Source code or Tip/Flutter & Dart

[flutter] RichText 활용

VintageappMaker 2022. 10. 22. 12:03

 

위의 화면에서 "내 연락처에서" 까지는 회색, "불러오기"는 검정색으로 표기해야 할 경우가 많다. 그리고 불러오기를 누르면 반응을 하며 코드를 실행해야 한다. 이럴경우, 대부분 Row(children[...])안에 Text(), SizedBox(), Spacer()를 이용하여 위의 화면을 표기한다. 

 

그러나 좀 더 복잡하게 문자열의 색상, 폰트, 크기 등등을 설정한 문자열을 표기해야 한다면 RichText를 사용해야 한다. 특히 크기에 따라 Wrap이 되어야 한다면 RichText외에는 대안이 없다. 

 

 

RichText class - widgets library - Dart API

A paragraph of rich text. The RichText widget displays text that uses multiple different styles. The text to display is described using a tree of TextSpan objects, each of which has an associated style that is used for that subtree. The text might break ac

api.flutter.dev

RichText는 크게 2가지 장점이 있는데 ,
1. 화면크기에 따른 Wrap

2. 문자열과 함께 각종 Widget을 같이 사용할 수 있음

이다 

 

RichText(
  text: TextSpan(
    text: "문자열"  
    children: [ TextSpan(), ... ],
),

RichText에 text 파라메터로 TextSpan()을 넘겨주면 된다. 그리고 TextSpan()은 text만 처리할 수도 있지만 InlineSpan 형으로 정의된 위젯들을 children에 넘겨주어 여러 개의 자식 위젯으로 표현이 가능하다. 그 때에 넘겨지는 값 중에는  TextSpan()이 아닌 WidgetSpan()도 가능한데 이 값의 child에 일반 Widget을 구현할 수 있다. TextSpan()에는 rerecognizer 필드가 있다. 이 필드는 TapGestureRecognizer()..onTap = (){} 와 같은 코드를 구현하여 문자열을 클릭 시 , 이벤트를 처리할 수 있다. 

 

다음은 예제소스이다. 아래 예제는 GoogleFonts를 사용했다. GoogleFonts 설치 및 예제는 다음과 같다. 

 

[Flutter] Flutter에서 GoogleFonts 사용하기

Flutter에서는 GoogleFonts를 사용할 수 있게 Package로 제공하고 있다. 패키지 설치 방법은 다음과 같다. google_fonts | Flutter Package A Flutter package to use fonts from fonts.google.com. pub.dev Goo..

vintageappmaker.tistory.com

 

[전체소스]

// 소스내에 잘못된 Expanded 사용으로
// 릴리즈로 빌드했을 경우, 화면에 아무것도 나오지 않았다. 
// Expanded 삭제 후 , 릴리즈함.
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.grey,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  final String title;
  const MyHomePage({
    Key? key,
    required this.title,
  }) : super(key: key);

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  bool isLight = true;
  Color plainTextColor = Colors.black;

  @override
  void initState() {
    super.initState();
  }

  void showSnack(String s) {
    var snck = SnackBar(content: Text('$s'));
    ScaffoldMessenger.of(context).showSnackBar(snck);
  }

  @override
  Widget build(BuildContext context) {
    // richText 예제
    List<InlineSpan> buildTextExample() {
      return <InlineSpan>[
        TextSpan(
          text: "RichText 예제입니다. ",
          style: GoogleFonts.doHyeon(color: plainTextColor, fontSize: 18),
        ),
        WidgetSpan(
          child: GestureDetector(
              onTap: () {
                showSnack("알람아이콘");
              },
              child: Icon(
                Icons.access_alarm,
                size: 20,
                color: Colors.red,
              )),
        ),
        WidgetSpan(
            child: Column(
          children: [
            Divider(
              height: 0.5,
              color: Colors.black,
            ),
            SizedBox(
              height: 25,
            )
          ],
        )),
        TextSpan(
          text: "TextSpan 위젯 외에도 ",
          style: GoogleFonts.notoSans(color: plainTextColor, fontSize: 15),
        ),
        WidgetSpan(
            child: Image.network(
          "https://media3.giphy.com/media/G35aZL8nwsBfkhjzQk/giphy.gif",
          width: 30,
          height: 30,
        )),
        TextSpan(
          text: "이나 ",
          style: GoogleFonts.notoSans(color: plainTextColor, fontSize: 15),
        ),
        WidgetSpan(
            child: SizedBox(
          width: 20,
          height: 20,
          child: Checkbox(
            onChanged: (value) {},
            value: true,
          ),
        )),
        TextSpan(
          text: "같은 TextSpan 위젯 외의 다른위젯들을 사용할 수 있습니다\n",
          style: GoogleFonts.notoSans(color: plainTextColor, fontSize: 15),
        ),
        TextSpan(
          text: "테스트입니다. 1234567, abdjflksfjk +3 🎈",
          style: GoogleFonts.poorStory(color: Colors.grey, fontSize: 20),
        ),
        TextSpan(
          text: "여기는",
          style: GoogleFonts.poorStory(color: Colors.grey, fontSize: 20),
        ),
        TextSpan(
          recognizer: TapGestureRecognizer()
            ..onTap = () {
              showSnack("배경변경");
              setState(() {
                isLight = !isLight;
                if (isLight) {
                  plainTextColor = Colors.black;
                } else {
                  plainTextColor = Colors.white;
                }
              });
            },
          text: "클릭😀(배경변경)",
          style: GoogleFonts.poorStory(color: Colors.red, fontSize: 20),
        ),
        TextSpan(
          text: "하면 반응합니다.",
          style: GoogleFonts.poorStory(color: Colors.grey, fontSize: 20),
        ),
      ];
    }

    return Scaffold(
      body: SingleChildScrollView(
        child: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              const Text(
                'RichText Test',
              ),
              SizedBox(
                height: 10,
              ),
              buildRichText(buildTextExample()),
              SizedBox(height: 20),
              Image.network(
                  "https://cdn2.unrealengine.com/egs-godofwar-santamonicastudio-ic1-400x400-5819bbf696c5.png?h=270&resize=1&w=480")
            ],
          ),
        ),
      ),
    );
  }

  Widget buildRichText(List<InlineSpan> richSpan) {
    return Container(
        width: double.infinity,
        margin: EdgeInsets.all(10),
        padding: EdgeInsets.all(5),
        color: isLight ? Color(0xffF0F0F0) : Color(0xff808080),
        child: Column(
          children: [
            RichText(
              text: TextSpan(
                children: richSpan,
              ),
            ),
          ],
        ));
  }
}
Comments