Flutter 開發從 0 到 1(六)Markdown 與代碼高亮

2022-01-02 吳小龍同學

《Fluuter 開發從 0 到 1》博客詳情是 Markdown,今天就來說說 Flutter Markdown 如何實現的。

先劇透下,今天的主角是 flutter_markdown,可以實現從使用簡單的 Markdown 標記格式化的純文本數據創建富文本輸出,包括文本樣式,表格,連結等。

準備

將 flutter_markdown 添加到 pubspec.yaml 文件中:

dependencies:
  flutter_markdown: ^0.4.4

項目根目錄執行如下命令安裝 flutter_markdown:

flutter pub get

使用

使用 Markdown 很簡單,只需將源 markdown 作為字符串傳遞,參數如下:

Markdown({
    Key key,
    //填充內容
    @required String data,
    bool selectable = false,
    //定製 Markdown 樣式
    MarkdownStyleSheet styleSheet,
    MarkdownStyleSheetBaseTheme styleSheetTheme,
    //設置代碼高亮
    SyntaxHighlighter syntaxHighlighter,
    //獲取點擊連結,可以使用 webview 展示
    MarkdownTapLinkCallback onTapLink,
    String imageDirectory,
    md.ExtensionSet extensionSet,
    MarkdownImageBuilder imageBuilder,
    MarkdownCheckboxBuilder checkboxBuilder,
    Map<String, MarkdownElementBuilder> builders = const {},
    this.padding = const EdgeInsets.all(16.0),
    this.controller,
    this.physics,
    this.shrinkWrap = false,
  })

syntaxHighlighter 可以設置代碼高亮,這裡有個坑,需要結合插件 syntax_highlighter 一起使用,後面再說。

實例

我們用《Fluuter 開發從 0 到 1(四)ListView 下拉加載和加載更多》md 文件用於測試,放到項目根目錄 assets 文件夾下,在 pubspec.yaml 中引用:

  assets:
    - assets/files/Markdown.md

代碼中獲取:

  Future<String> _loadFromAssets() async {
    String filePath = 'assets/files/Markdown.md';

    String fileContents = await rootBundle.loadString(filePath);
    return fileContents;
  }

完整代碼如下:

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_markdown/flutter_markdown.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Markdown Demo'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  var _result = "";
  dynamic result;

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: new Markdown(
        controller: ScrollController(),
        selectable: true,
        data: _result,
        styleSheet: new MarkdownStyleSheet(
          p: new TextStyle(fontSize: 16),
          h2: new TextStyle(color: Colors.blue, fontSize: 24),
        ),
        onTapLink: (url) {
          // 獲取點擊連結,可以使用webview展示
          print(url);
        },
      ),
    );
  }

  void loadAssests() async {
    result = await _loadFromAssets();
    print(result);
    setState(() {
      _result = result.toString();
    });
  }

  Future<String> _loadFromAssets() async {
    String filePath = 'assets/files/Markdown.md';

    String fileContents = await rootBundle.loadString(filePath);
    return fileContents;
  }
}

效果如下:

Markdown 文件完美展示了,但發現代碼沒有高亮,對於我這個有強迫症的人,不允許

代碼高亮

Flutter 插件 syntax_highlighter 可以是代碼高亮,如果是有文字+代碼這種形式,就不會高亮,這裡需要結合flutter_markdown 一起使用。

將 syntax_highlighter 添加到 pubspec.yaml 文件中:

dependencies:
  syntax_highlighter: ^0.1.1

項目根目錄執行如下命令安裝 flutter_markdown:

flutter pub get

看 flutter_markdown 的 syntaxHighlighter 參數類是抽象類:

abstract class SyntaxHighlighter {
  // ignore: one_member_abstracts
  /// Returns the formatted [TextSpan] for the given string.
  TextSpan format(String source);
}

新建 my_markdown_style.dart 繼承 SyntaxHighlighterfu override format 方法:

import 'package:flutter/material.dart';
import 'package:flutter_markdown/flutter_markdown.dart' as md;
import 'package:syntax_highlighter/syntax_highlighter.dart';

class HighLight extends md.SyntaxHighlighter {

  @override
  TextSpan format(String source) {
    final SyntaxHighlighterStyle style =
        SyntaxHighlighterStyle.lightThemeStyle();
    return TextSpan(
        style: const TextStyle(
          fontSize: 12.0,
          fontFamily: 'monospace',
        ),
        children: <TextSpan>[DartSyntaxHighlighter(style).format(source)]);
  }
}

這樣在 flutter_markdown syntaxHighlighter 參數可以這樣寫:

    new Markdown(
       //……
      data: _result,
      syntaxHighlighter: new HighLight(),
      //……
    )

效果如下:

代碼高亮了,效果很完美,更多代碼細節詳見《Flutter 開發從 0 到 1(五)源碼》。


相關焦點

  • 打造一款基於monaco-editor及markdown-it的Markdown編輯器(上)
    接下來我們對 Monaco editor 進行使用webpack.config.js下載 monaco-editor-webpack-plugin 插件解決代碼高亮;本項目為了減少引入,只支持 markdown 的高亮,但其實可以支持 XML, PHP, C#, C++, Razor, Markdown, Diff, Java, VB, CoffeeScript
  • Flutter 完整開發實戰詳解 (Flutter 畫面渲染的全面解析) | 開發者說·DTalk
    ): │ transform:I/flutter (32494): │ [0] 2.8,0.0,0.0,0.0I/flutter (32494): │ [1] 0.0,2.8,0.0,0.0I/flutter (32494): │ [2] 0.0,0.0,1.0,0.0I/flutter (32494): │ [3] 0.0,0.0,0.0,1.0I/flutter (32494
  • 半個小時學會Markdown標記語法
    ,遇到很多錯誤,好腦子不如爛筆頭,能一邊敲代碼一邊做筆記,學起來事倍功半,今天分享大家一個做筆記的工具軟體Typora。>ordered list:無序列表un-ordered list:- Red- Green- Blueun-ordered list:代碼塊一般情況下,word等office軟體不支持代碼高亮
  • FlutterBoost1.0到2.0,我一共做了這幾件事...
    同時,我們也持續關注到以下痛點:Flutter在不斷的演進升級,其演進會給上層應用來到更多可能;同時,在我們的業務應用中,FlutterBoost1.0在線上使用的過程中遇到一些如黑屏和白屏的反饋,這些歷史遺留問題我們希望解決掉;最後,社區的關注及需求是推動我們前進的動力,我們也希望藉此將FlutterBoost的開源做的更完善,比如增加更多測試用例,更多文檔等等
  • 探索Flutter混合開發技術方案(下)——淺析Flutter Boost原理
    在理解原理之前,我假設大家都對Flutter Boost的基本用法都已經了解,如果還沒有用過Flutter Boost,我建議大家先閱讀官方文檔以及看看example的代碼。Flutter端加載流程:簡單來說,從Flutter側執行FlutterBoost.open方法打開頁面到FlutterBoost容器打開這個過程,主要經歷了以下階段:單引擎模式《已開源|碼上用它開始Flutter混合開發——FlutterBoost》 文中講到Flutter
  • Flutter 原理及美團實踐
    : "^0.1.2"  plugin1:     git:       url: "git://github.com/flutter/plugin1.git"  plugin2:     path: ..
  • APP 開發從 0 到 1(一)需求與準備
    背景在《手把手教你做個人 app》我有說過,開發一個 APP 很大程度依賴服務端:服務端提供接口數據,然後 APP 展示;開發一個 APP,還需要美工協助切圖。對於以前的我,沒接口,沒美工,照樣可以開發 APP ,可謂 So easy 來形容。
  • 半小時帶你入門 Flutter
    國慶後面兩天在家學習整理了一波flutter,基本把能擼過能看到的代碼都過了一遍,此文篇幅較長,建議保存(star)再看。Questions tagged [flutter]img本文我們從介紹flutter基本概念到梳理常用Widget到常用app demos編寫到~放棄~,希望可以幫助每一個像我一樣的初學者。有誤地方還望大神不吝賜教~
  • 已開源|碼上用它開始Flutter混合開發——FlutterBoost
    開源地址:https://github.com/alibaba/flutter_boost具有一定規模的App通常有一套成熟通用的基礎庫
  • Flutter竟然還有這種高端用法?
    https://juejin.im/user/2840793776393847首先,有很多的文章在說flutter bloc模式的應用,但是百分之八九十的文章都是在說,使用StreamController+StreamBuilder搭建bloc,提升性能的會加上InheritedWidget,這些文章看了很多,真正寫使用bloc作者開發的flutter_bloc卻少之又少。
  • 愛奇藝開播助手Flutter跨平臺Hybrid實踐
    由於雙端的業務幾乎完全一樣,雙端為了提高代碼的復用率,我們試圖接入一套跨平臺的框架同時開發兩端的 APP。移動端跨平臺一直是開發者老生常談的話題,為了儘可能的增加代碼復用,降低開發成本,各大科技巨頭都有自己的跨平臺框架,比如 Facebook 的 React-Native、阿里的 Weex、Cordova 等。
  • Erupt 1.5.3 發布,零前端代碼開發後臺管理系統
    Erupt 可快速的構建管理頁面,零前端代碼、零CURD、自動建表,僅需單個類文件 + 簡潔的註解配置,即可快速開發企業級Admin管理後臺!因此,針對後臺系統開發,市面上有不少成熟的前端 UI 模板,比如螞蟻的 Ant Design,老派的 Ext.js 等,這些框架簡化了前端人員的開發流程,但對整個系統來說,開發的成本依然很高,仍然是兩套體系。有的公司可能沒有條件養活兩個團隊,後端經常要被迫寫前端代碼。那有沒有可能更進一步,僅使用後端技術即可完成開發呢?
  • 用前端最舒服的躺姿 "搞定" Flutter
    如果你是初次接觸 Flutter 可以不用記憶這麼多組件基類,只用記住以下式子就可以, 不誇張的說,熟悉這個式子就可以開發 Flutter 項目了:']), el('ul', [el('li'), el('li')])])再來看看,flutter 用Dart 創建的 widget 代碼結構:Widget build(BuildContext context) { return new Column(
  • 學習一個由阿里開發的Flutter框架
    幾個問題點ListView怎麼使用adapter,數據怎麼和item綁定怎麼將Page當做widget使用(BottomNavigationBar,NavigationRail等等導航欄控制項會使用到)引入GitHub地址:https://github.com/alibaba/fish-reduxPub地址:https://pub.dev/packages/fish_redux我用的是0.3.X的版本,算是第三版,相對於前幾版,改動較大引入fish_redux插件,想用最新版插件,可進入pub地址裡面查看fish_redux: ^0.3.4#演示列表需要用到的庫
  • flutter逆向演練
    目前來說的話,flutter app的逆向一直是個比較困難的問題,在app的lib目錄下會有個libapp.so文件,裡面存放的即是app運行的核心代碼,用ida來看看很明顯,都是些字節,並不能很直觀的看見彙編代碼,到這裡,就可以難到90%的逆向人員了,我們可以在看看導出函數
  • 通過與React的簡單對比來入門Flutter
    如果平時只寫JS可能會不太習慣,但是如果你已經習慣使用TS開發(實際上TS就有很多Java,C#的影子),我相信上手Dart語言不是一件很困難的事。環境搭建參考官網[1],有非常詳細的教程。關鍵步驟,安裝Flutter SDK。
  • Cocos Creator 1.0 正式版發布 讓高效開發觸手可及
    Cocos Creator 1.0版在我們設定的開發計劃中,主要的目標包括:  ● 更友好的代碼開發環境  ● 可靠的原生開發和發布工作流程  ● 新 UI 控制項:文本框和網格式布局  ● 骨骼動畫和瓦片地圖支持
  • Flutter Widgets 之 Container
    Container將會是我們以後最常用的控制項之一,Container是單容器類控制項,即只包含一個子控制項。
  • Flutter - 不聽話的 Container
    // flutter/lib/src/rendering/box.dartBoxConstraints.loose(Size size)    : minWidth = 0.0,      maxWidth = size.width,      minHeight = 0.0,      maxHeight = size.height;
  • flutter實現簡單的旋轉動畫
    前言flutter實現簡單的旋轉動畫,和大家一起學習探討。