Flutter 封裝:富文字 RichText 極簡封裝

SoaringHeart發表於2021-07-31

1. 需求:

開發中遇到一個富文字展示點選效果(使用者協議和隱私),通過官方的原始方法能夠實現,但是很繁瑣而且無聊,隨想實現一個方便且高效的富文字生成方法,參考 iOS,最終完美實現;

2. 實現原理:

  1. 宣告協議字典, 例如

    var linkMap = {
      '《使用者協議》': 'https://flutter.dev',
      '《隱私政策》': 'https://flutter.dev',
    };
    複製程式碼
  2. 通過 《 》分割整段文字為陣列;然後判斷陣列元素是否等於 “《$e》”; 如果等於則建立為連結 TextSpan),不等於則建立普通 TextSpan;可以得到 TextSpan 陣列;

  3. ontap 回撥(點選連結)返回 linkMap 中對應 key 和 value;

3. sceenshot:

Simulator Screen Shot - iPhone 11 Pro - 2021-07-31 at 12.50.12.png

4. example:

//
//  RichTextDemo.dart
//  fluttertemplet
//
//  Created by shang on 7/31/21 12:11 PM.
//  Copyright © 7/31/21 shang. All rights reserved.
//

import 'package:flutter/material.dart';
import 'package:fluttertemplet/basicWidget/AttributedString.dart';
import 'package:fluttertemplet/dartExpand/ddlog.dart';

class RichTextDemo extends StatefulWidget {

  final String? title;

  RichTextDemo({ Key? key, this.title}) : super(key: key);


  @override
  _RichTextDemoState createState() => _RichTextDemoState();
}

class _RichTextDemoState extends State<RichTextDemo> {

  @override
  Widget build(BuildContext context) {
    dynamic arguments = ModalRoute.of(context)!.settings.arguments;

    return Scaffold(
        appBar: AppBar(
          title: Text(widget.title ?? "$widget"),
        ),
        body: buildRichText(context),
    );
  }

  Widget buildRichText(BuildContext context) {

    var linkMap = {
      '《使用者協議》': 'https://flutter.dev',
      '《隱私政策》': 'https://flutter.dev',
    };

    String text = """
        親愛的xxxx使用者,感謝您信任並使用xxxxAPP!
xxxx十分重視使用者權利及隱私政策並嚴格按照相關法律法規的要求,對《使用者協議》和《隱私政策》進行了更新,特向您說明如下:
        1.為向您提供更優質的服務,我們會收集、使用必要的資訊,並會採取業界先進的安全措施保護您的資訊保安;
        2.基於您的明示授權,我們可能會獲取裝置號資訊、包括:裝置型號、作業系統版本、裝置設定、裝置識別符號、MAC(媒體訪問控制)地址、IMEI(移動裝置國際身份碼)、廣告識別符號(“IDFA”與“IDFV”)、積體電路卡識別碼(“ICCD”)、軟體安裝列表。我們將使用三方產品(友盟、極光等)統計使用我們產品的裝置數量並進行裝置機型資料分析與裝置適配性分析。(以保障您的賬號與交易安全),且您有權拒絕或取消授權;
        3.您可靈活設定伴伴賬號的功能內容和互動許可權,您可在《隱私政策》中瞭解到許可權的詳細應用說明;
        4.未經您同意,我們不會從第三方獲取、共享或向其提供您的資訊;
        5.您可以查詢、更正、刪除您的個人資訊,我們也提供賬戶登出的渠道。
        請您仔細閱讀並充分理解相關條款,其中重點條款已為您黑體加粗標識,方便您瞭解自己的權利。如您點選“同意”,即表示您已仔細閱讀並同意本《使用者協議》及《隱私政策》,將盡全力保障您的合法權益並繼續為您提供優質的產品和服務。如您點選“不同意”,將可能導致您無法繼續使用我們的產品和服務。
""";
    final textRich = Text.rich(
      TextSpan(
        children: AttributedString(
            context: context,
            text: text,
            linkMap: linkMap,
            // style: TextStyle(
            //     fontSize: 13,
            // ),
            // linkStyle: TextStyle(fontSize: 15),
            onTap: (key, value){
              ddlog(key);
              ddlog(value);
            }
        ).textSpans,
      ),
      strutStyle: StrutStyle(
        leading: 0.4,
      ),
    );

    return Container(
      padding: EdgeInsets.all(12),
      child: textRich,
    );
  }
}

//flutter: 2021-07-31 12:57:28.257309  RichTextDemo.dart, _RichTextDemoState [line 66]: 《使用者協議》
//flutter: 2021-07-31 12:57:28.257929  RichTextDemo.dart, _RichTextDemoState [line 67]: https://flutter.dev
//flutter: 2021-07-31 12:57:28.890716  RichTextDemo.dart, _RichTextDemoState [line 66]: 《隱私政策》
//flutter: 2021-07-31 12:57:28.891331  RichTextDemo.dart, _RichTextDemoState [line 67]: https://flutter.dev
複製程式碼

5. 兩種封裝方式:

擴充套件封裝: richText_extension.dart

//...
children: RichTextExt.createTextSpans(context,
    text: text,
    linkMap: protocolMap,
    onTap: (key, value){
      ddlog(key);
      ddlog(value);
    }
)
//...
複製程式碼

類封裝: AttributedString.dart

//...
// children: AttributedString(
//     context: context,
//     text: text,
//     linkMap: protocolMap,
//     onTap: (key, value){
//       ddlog(key);
//       ddlog(value);
//     }
// ).textSpans,
//...
複製程式碼

相關文章