SpanBuilder는 일반 텍스트에서 풍부한 텍스트 스팬을 쉽게 생성할 수 있도록 설계된 Flutter/Dart 패키지입니다. 스타일링된 텍스트, 링크, 상호작용 요소를 간편하게 통합할 수 있습니다. 자동으로 GestureRecognizers의 해제를 관리하여 메모리 누수를 방지하고 성능을 향상시킵니다. 클릭 가능한 해시태그나 언급과 같은 내장된 상호작용이 포함된 동적 텍스트 렌더링에 적합합니다. 복잡한 텍스트 레이아웃을 수동으로 생명주기 관리 없이 깔끔하고 선언적인 구문으로 만들 수 있습니다.
사용 사례
클릭 가능한 요소를 사용하여 상호작용형 레이블 텍스트 만들기
혼합 스타일로 형식화된 텍스트 렌더링
언급 또는 해시태그 파서 만들기
제스처 인식기 정리 자동화
임베디드 작업이 포함된 동적 콘텐츠 표시
주요 기능
자동 GestureRecognizer 해제
순수 텍스트에서 간단한 스팬 생성
풍부한 텍스트 스타일링을 지원합니다
반복 코드를 줄입니다
메모리 누수를 방지합니다
적합한 대상
채팅 인터페이스를 개발하는 개발자
동적 텍스트 콘텐츠를 가진 앱
인터랙티브 텍스트 요소가 필요한 프로젝트
클린 코드와 유지보수를 우선시하는 팀
고려 사항
텍스트 기반 UI 컴포넌트에 한정
복잡한 레이아웃에 대한 내장 지원 없음
TextSpan 구조에 대한 이해가 필요합니다
비텍스트 렌더링 요구 사항에는 적합하지 않습니다
Flutter의 Text 위젯 생태계에 의존합니다
원본 README
연결된 소스 저장소의 README 원문 스냅샷입니다. 최신 내용은 저장소에서 확인하세요.
Facilitates creation of spans from plain text and provides an automated disposal of GestureRecognizers.
Description
Given some plain text, e.g.: "The quick brown fox" allows you to apply multiple spans at multiple positions. Positions can be specified by a matching word (whereText), e.g. "brown" and/or range from=10, to=15. Spans are subclasses of InlineSpan. If the span you are trying to apply is TextSpan you don't need to pass whereText as it will be inferred from text within the provided span.
Once you are done using SpanBuilder, use build() to return calculated list of spans. Spans can't overlap.
Usage:
final spans = SpanBuilder("The quick brown fox")
.apply(TextSpan(text: "brown", style: TextStyle(fontWeight: FontWeight.bold)))
.apply(TextSpan(text: "🦊"), whereText: "fox")
.build()
From there you can use these spans in your RichText, e.g.:
RichText(
text: TextSpan(children: spans)
)
If you plan to make your text "tappable" read on.
Handling GestrueRecognizer (text taps)
If you try passing GestrueRecognizer as a field in TextSpan it will get stripped away - HERE IS WHY.
TL;DR: We don't want to leak GestureRecognizer but TextSpan has no idea about the lifecycle of Widget so you need a stateful widget to keep a reference to the recognizer untill you're done with it. Sounds like a mess, right?
The workaround is to provide a builder for the recognizer like this:
apply(TextSpan(text: "jumps"),
recognizerBuilder: () => TapGestureRecognizer()..onTap = () {
// your code here
})
Then you can use this SpanBuilder together with SpanBuilderWidget which will manage creating and disposing of TapGestrueRecognizer at the right time:
SpanBuilderWidget(
text: SpanBuilder("fox jumps")
..apply(TextSpan(text: "jumps"),
recognizerBuilder: () => TapGestureRecognizer()..onTap = () {
// your code here
})
)
If you care only about onTap interaction you can use this API shortcut:
apply(TextSpan(text: "jumps"),
onTap: () {
// your code here
}
)
Testing:
There are little resources on how to test RichText in general. For this reason there is helper testing library span_builder_test that can help you verify state of your spans in your UI tests.