본문 바로가기
프레임워크/Flutter

[Flutter] 해시태그(#) 표현하기

by 연어바케트 2024. 9. 7.
반응형

게시물 작성시 해시태그를 적용하고 싶어서 기록 한다. 

 

기존에는 그냥 Text 위젯을 사용하여 게시물의 내용을 표현하였다. 

하지만 해시태그가 있을 때 이를 강조하기 위해서는 다른 방법이 필요했다. 

 

Text위젯으로는 중간에 특정 부분만 style을 변경할 수 없기 때문이다. 

 

1. TextSpan

  • TextSpan
    text에 여러 스타일을 적용하고 그것을 하나의 text 위젝으로 표시할 때 사용되는 클래스이다.
  • 주요속성 
    • text: 표시할 텍스트 문자열.
    • style: 텍스트 스타일을 지정하는 TextStyle 객체. 폰트 크기, 색상, 굵기 등을 정의할 수 있습니다.
    • children: 또 다른 TextSpan 리스트를 포함하여 중첩된 스타일링을 적용할 수 있습니다.
    • recognizer: 터치 이벤트나 클릭과 같은 사용자 상호작용을 처리하는 GestureRecognizer를 지정할 수 있습니다.

2. 정규표현식

  static final hashTagRegex = RegExp(r'(?<=^|\s)#[a-zA-Z0-9가-힣_]+(?:_[a-zA-Z0-9가-힣_]+)*(?=\s|$)');

해시 태그를 강조하기 위해서 해시태그 부분을 찾아야하는데,  필자는 정규표현식을 사용하였다. 

아래와 같이 적용 될 수 있도록 정규표현식을 만들었다. 

  • ## 적용 되지 않는다.
  • 해시태그(#) 뒤에 _ 이외에 특수문자는 적용되지 않는다.
  • 해시태그(#) 앞에 공백이 없으면 적용되지 않는다. 
  • 그 외에 해시태그(#)적용 

 

3. 코드 적용

List<TextSpan> buildTextSpans(
    String text,
    Function(String hashTag)? onHashTag,) {
    final List<TextSpan> spans = [];
    final matches = <RegExpMatch>[];

    matches.addAll(RegexPatterns.hashTagRegex.allMatches(text));
    int lastMatchEnd = 0;

    for (final match in matches) {
      if (match.start > lastMatchEnd) {
        spans.add(
          TextSpan(
            text: text.substring(lastMatchEnd, match.start),
            style: defaultStyle,
          ),
        );
      }
      final matchedText = match.group(0)!;
      if (matchedText.startsWith('#')) {
        spans.add(
          TextSpan(
            text: matchedText,
            style: hashTagStyle,
            recognizer: onHashTag == null
                ? null
                : (TapGestureRecognizer()..onTap = () => onHashTag(matchedText)),
          ),
        );
      } 
      lastMatchEnd = match.end;
    }
    if (lastMatchEnd < text.length) {
      spans.add(
        TextSpan(
          text: text.substring(lastMatchEnd),
          style: defaultStyle,
        ),
      );
    }
    return spans;
  }
  • 함수매개 변수
    • text: 입력받은 문자열입니다. 
    • onHashTag: 해시태그를 터치했을 때 실행될 콜백 함수. 해시태그를 감지하고 이 함수가 정의되어 있으면, 해당 해시태그에 클릭 이벤트 연결. 만약 null이면 상호작용이 없는 상태로 해시태그를 표시
  • 동작 흐름
    1. 해시태그(#)를 찾기 위한 정규식 매칭 : matches.addAll(RegexPatterns.hashTagRegex.allMatches(text));을 사용하여 문자열에서 해시태그에 해당하는 부분을 탐지
    2. 매칭된 해시태그와 일반 텍스트 분리
      1. lastMatchEnd 를 사용하여 이전에 매칭된 텍스트 이후의 남은 텍스트를 추적 
      2. 해시태그와 해시태그 사이에 있는 일반 텍스트는 따로 처리하여 TextSpan에 기본 스타일을 적용
    3. 일반 텍스트 스타일 추가
    4. 해시태그 스타일 추가
    5. 마지막 남은 텍스트 처리 
      1. 마지막으로 매칭이 끝난 부분 이후에 남아있는 텍스트가 있다면, 해당 텍스트도 기본 스타일을 사용해 TextSpan으로 추가

4. 결과 화면

아래와 같이 해시태그(#)와 (_) 부분이 잘 분리되어 표현되고 있는 것을 볼 수 있다. 

 

 

반응형

댓글