Flutter 支持圖片以及特殊文字的輸入框(一)使用方法

extended_text_field 相關文章git

最近有客戶Alex提出Flutter輸入框須要支持支持圖片和特殊文字樣式,就跟QQ,微信,微博同樣,能夠插入表情,@xxx或者一個話題. 天天追更,天天都在羣裏@我(FlutterCandies QQ羣:181398081),就差點就把他禁言了。可是我沒有這樣作,客戶就是上帝,由於以前作過Extended Text,僞裝感受應該很簡單,悄悄在空閒的時候就動手作起來了。github

本篇只介紹下用法,下一篇再講講開發中的辛酸歷程,先上效果圖。微信

使用步驟

關注,點贊,轉發,送飛機

pub 搜索 extended_text_fieldthis

pub package

github 地址:extended_text_field

定義本身的特殊文字

好比表情

我這裏定義的格式是好比[1],就表明是表情1(就是你對應的表情圖片).

class EmojiText extends SpecialText {
  static const String flag = "[";
  final int start;
  EmojiText(TextStyle textStyle, {this.start})
      : super(EmojiText.flag, "]", textStyle);

  @override
  TextSpan finishText() {
    // TODO: implement finishText
    var key = toString();
    if (EmojiUitl.instance.emojiMap.containsKey(key)) {
      //fontsize id define image height
      //size = 30.0/26.0 * fontSize
      final double size = 20.0;

      ///fontSize 26 and text height =30.0
      //final double fontSize = 26.0;

      return ImageSpan(AssetImage(EmojiUitl.instance.emojiMap[key]),
          actualText: key,
          imageWidth: size,
          imageHeight: size,
          start: start,
          deleteAll: true,
          fit: BoxFit.fill,
          margin: EdgeInsets.only(left: 2.0, top: 2.0, right: 2.0));
    }

    return TextSpan(text: toString(), style: textStyle);
  }
}

class EmojiUitl {
  final Map<String, String> _emojiMap = new Map<String, String>();

  Map<String, String> get emojiMap => _emojiMap;

  final String _emojiFilePath = "assets";

  static EmojiUitl _instance;
  static EmojiUitl get instance {
    if (_instance == null) _instance = new EmojiUitl._();
    return _instance;
  }

  EmojiUitl._() {
    for (int i = 1; i < 49; i++) {
      _emojiMap["[$i]"] = "$_emojiFilePath/$i.png";
    }
  }
}
複製代碼

再舉一個

好比 @法的空間

以@爲開始標誌,空格爲結束標誌

class AtText extends SpecialText {
  static const String flag = "@";
  final int start;

  /// whether show background for @somebody
  final bool showAtBackground;

  final BuilderType type;
  AtText(TextStyle textStyle, SpecialTextGestureTapCallback onTap,
      {this.showAtBackground: false, this.type, this.start})
      : super(flag, " ", textStyle, onTap: onTap);

  @override
  TextSpan finishText() {
    // TODO: implement finishText
    TextStyle textStyle =
        this.textStyle?.copyWith(color: Colors.blue, fontSize: 16.0);

    final String atText = toString();

    if (type == BuilderType.extendedText)
      return TextSpan(
          text: atText,
          style: textStyle,
          recognizer: TapGestureRecognizer()
            ..onTap = () {
              if (onTap != null) onTap(atText);
            });

    return showAtBackground
        ? BackgroundTextSpan(
            background: Paint()..color = Colors.blue.withOpacity(0.15),
            text: atText,
            actualText: atText,
            start: start,
            deleteAll: false,
            style: textStyle,
            recognizer: type == BuilderType.extendedText
                ? (TapGestureRecognizer()
                  ..onTap = () {
                    if (onTap != null) onTap(atText);
                  })
                : null)
        : SpecialTextSpan(
            text: atText,
            actualText: atText,
            start: start,
            deleteAll: false,
            style: textStyle,
            recognizer: type == BuilderType.extendedText
                ? (TapGestureRecognizer()
                  ..onTap = () {
                    if (onTap != null) onTap(atText);
                  })
                : null);
  }
}
複製代碼

定義文字解析幫助類

必須實現createSpecialText方法,這樣才知道你有哪些特殊文字

一個是build的方法,可選實現。若是你本身實現了要注意,特殊TextSpan必須放在返回的TextSpan的children裏面,我只會遍歷這一層,不會再去查找children的children了。

class MySpecialTextSpanBuilder extends SpecialTextSpanBuilder {
  /// whether show background for @somebody
  final bool showAtBackground;
  final BuilderType type;
  MySpecialTextSpanBuilder(
      {this.showAtBackground: false, this.type: BuilderType.extendedText});

  @override
  TextSpan build(String data, {TextStyle textStyle, onTap}) {
    // TODO: implement build
    var textSpan = super.build(data, textStyle: textStyle, onTap: onTap);
    //for performance, make sure your all SpecialTextSpan are only in textSpan.children
    //extended_text_field will only check SpecialTextSpan in textSpan.children
    return textSpan;
  }

  @override
  SpecialText createSpecialText(String flag,
      {TextStyle textStyle, SpecialTextGestureTapCallback onTap, int index}) {
    if (flag == null || flag == "") return null;
    // TODO: implement createSpecialText

    ///index is end index of start flag, so text start index should be index-(flag.length-1)
    if (isStart(flag, AtText.flag)) {
      return AtText(textStyle, onTap,
          start: index - (AtText.flag.length - 1),
          showAtBackground: showAtBackground,
          type: type);
    } else if (isStart(flag, EmojiText.flag)) {
      return EmojiText(textStyle, start: index - (EmojiText.flag.length - 1));
    } else if (isStart(flag, DollarText.flag)) {
      return DollarText(textStyle, onTap,
          start: index - (DollarText.flag.length - 1), type: type);
    } else if (isStart(flag, ImageText.flag)) {
      return ImageText(textStyle,
          start: index - (ImageText.flag.length - 1), type: type, onTap: onTap);
    }
    return null;
  }
}

enum BuilderType { extendedText, extendedTextField }
複製代碼

使用ExtendedTextField

是否是炒雞簡單,這樣你的文字就會自動轉換爲對應的特殊文字類型了

ExtendedTextField(
            specialTextSpanBuilder: MySpecialTextSpanBuilder(
                showAtBackground: true, type: BuilderType.extendedTextField),
複製代碼

限制

readme上面講的同樣,有三種限制。

  • 不支持文字從右到左,也就是不支持TextDirection.rtl。緣由是TextPainter 給的圖片的位置,很是奇怪,徹底無法搞。固然我會繼續跟進,也許哪天官方修好了呢?
  • 不支持那種密碼的輸入樣式解析成特殊TextSpan,也就是不支持obscureText 爲true。沒啥好解釋,文字都變成******了,也不必解析了。
  • 代碼是基於flutter 版本1.5.7,可能在不一樣的flutter 版本下面會出現編譯錯誤,若是出現,但願老闆們能根據本身的版本進行更正。我這邊不太可能都適配到每一個flutter 版本,我會盡可能讓extended_text_field 在flutter 的穩定版本上面沒有錯誤,但願諒解。

最後放上 extended_text_field,若是你有什麼不明白或者對這個方案有什麼改進的地方,請告訴我,歡迎加入Flutter Candies,一塊兒生產可愛的Flutter 小糖果(QQ羣:181398081)

Flutter Candies全家桶

最最後放上Flutter Candies全家桶,真香。

custom flutter candies(widgets) for you to easily build flutter app, enjoy it.

extended_nested_scroll_view

pub package

extended_image

pub package

extended_text

pub package

extended_text_field

pub package

pull_to_refresh_notification

pub package

loading_more_list

pub package

extended_tabs

pub package

http_client_helper

pub package

相關文章
相關標籤/搜索