Flutter —— Text文字漸變


Flutter Text 設置文本漸變色

 

API是使用TextStyle中的foreground 設置文字顏色漸變,如下圖:

https://api.flutter.dev/flutter/painting/TextStyle-class.html

頭文件import 'dart:ui' as ui; 

 

根據以上代碼構造之后結果如下圖行1所示,但是如果Text控件居中並縮短字符串長度后就會發現漸變顏色不同的,如下圖行2所示。(最后有相關代碼)

通過多次對比發現,漸變色是基於在整個window偏移的,代碼中的offset 分別表示Offset from,Offset to 起點與終點偏移量,代碼中const Offset(0, 20),const Offset(150, 20),表示從坐標(0,20),到(150,20,修改偏移量為const Offset(100, 20),const Offset(250, 20),結果圖行3、4。

 

所以行2中Text居中后dx還是從0開始,顏色不是正紅色開始,查看Gradient.linear,有一個colorStops屬性,具體含義可查看相關注釋,如下圖

 

 

在偏移量超過其字符串最大dx的時候,設置colorStops,<double>[0.3,0.9],結果如結果圖中的行5,通過調整colorStops,可以得到想要的漸變效果。

注意: 設置漸變色不能同時設置TextStyle的color屬性,否則會報錯,如下圖:

 

設置漸變色還有另外一種寫法:

Text(

  'Greetings, planet!',

  style: TextStyle(

      fontSize: 30,

      foreground: Paint()

        ..shader = LinearGradient(colors: [

          Colors.red,

          Colors.yellow,

        ]).createShader(Rect.fromLTWH(0, 0, 150, 0))),

)

或者

Gradient gradient =  LinearGradient(colors: [

  Colors.red,

  Colors.yellow,

]);

Text(

  'Greetings, planet!',

  style: TextStyle(

      fontSize: 30,

      foreground: Paint()

        ..shader = gradient.createShader(Rect.fromLTWH(0, 0, 100, 0))),

)

 

createShader中的Rect和上面的偏移量類似,又不完全相同,Rect.fromLTWH(0, 0, 100, 0),  width,表示漸變的寬度范圍,結果如圖行6。

這時候只是固定位置text設置漸變色,如果在不確定text坐標的時候如何使用漸變色

1、 設置Text的key值globalKey,通過globalKey 獲取Text控件的size及position

final RenderBox box = globalKey.currentContext.findRenderObject();

final size = box.size;

final topLeftPosition = box.localToGlobal(Offset.zero);

2、如果設置的比較多可以封裝組件widget,根據組件context獲取位置大小,具體可查看以下的TextGradientColorWidget

 

驗證相關代碼:

import 'dart:ui' as ui;
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        // This is the theme of your application.
        //
        // Try running your application with "flutter run". You'll see the
        // application has a blue toolbar. Then, without quitting the app, try
        // changing the primarySwatch below to Colors.green and then invoke
        // "hot reload" (press "r" in the console where you ran "flutter run",
        // or simply save your changes to "hot reload" in a Flutter IDE).
        // Notice that the counter didn't reset back to zero; the application
        // is not restarted.
        primarySwatch: Colors.blue,
        // This makes the visual density adapt to the platform that you run
        // the app on. For desktop platforms, the controls will be smaller and
        // closer together (more dense) than on mobile platforms.
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

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

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
  }

  @override
  void didChangeDependencies() {
    // TODO: implement didChangeDependencies
    super.didChangeDependencies();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          // Here we take the value from the MyHomePage object that was created by
          // the App.build method, and use it to set our appbar title.
          title: Text(widget.title),
        ),
        body: Column(
          mainAxisAlignment: MainAxisAlignment.start,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Container(
                margin: EdgeInsets.only(top: 20, bottom: 20),
                child: Text(
                  '1.Greetings, planet!',
                  style: TextStyle(
                      fontSize: 30,
                      foreground: Paint()
                        ..shader = ui.Gradient.linear(
                            const Offset(0, 20), const Offset(150, 20), <Color>[
                          Colors.red,
                          Colors.yellow,
                        ])),
                )),
            Container(
                margin: EdgeInsets.only(top: 20, bottom: 20),
                child: Center(
                    child: Text(
                  '2.Greetings!',
                  style: TextStyle(
                      fontSize: 30,
                      foreground: Paint()
                        ..shader = ui.Gradient.linear(
                            const Offset(0, 20), const Offset(150, 20), <Color>[
                          Colors.red,
                          Colors.yellow,
                        ])),
                ))),
            Container(
                margin: EdgeInsets.only(top: 20, bottom: 20),
                child: Text(
                  '3.Greetings, planet!',
                  style: TextStyle(
                      fontSize: 30,
                      foreground: Paint()
                        ..shader = ui.Gradient.linear(const Offset(100, 20),
                            const Offset(250, 20), <Color>[
                          Colors.red,
                          Colors.yellow,
                        ])),
                )),
            Container(
              margin: EdgeInsets.only(top: 20, bottom: 20),
              child: Center(
                  child: Text(
                '4.Greetings!',
                style: TextStyle(
                    fontSize: 30,
                    foreground: Paint()
                      ..shader = ui.Gradient.linear(
                          const Offset(100, 20), const Offset(250, 20), <Color>[
                        Colors.red,
                        Colors.yellow,
                      ])),
              )),
            ),
            Container(
                margin: EdgeInsets.only(top: 20, bottom: 20),
                child: Center(
                    child: Text(
                  '5.Greetings!',
                  style: TextStyle(
                      fontSize: 30,
                      foreground: Paint()
                        ..shader = ui.Gradient.linear(const Offset(100, 20),
                            const Offset(250, 20), <Color>[
                          Colors.red,
                          Colors.yellow,
                        ], <double>[
                          0.3,
                          0.9
                        ])),
                ))),
            Container(
                margin: EdgeInsets.only(top: 20, bottom: 20),
                child: Text(
                  '6.Greetings, planet!',
                  style: TextStyle(
                      fontSize: 30,
                      foreground: Paint()
                        ..shader = LinearGradient(colors: [
                          Colors.red,
                          Colors.yellow,
                        ]).createShader(Rect.fromLTWH(0, 0, 150, 0))),
                )),
            Container(
              margin: EdgeInsets.only(top: 20, bottom: 20),
              child: Center(
                child: TextGradientColorWidget(data: "7.Greetings", colors: [
                  Colors.red,
                  Colors.yellow,
                ]),
              ),
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceAround,
              children: [
                Center(
                  child: TextGradientColorWidget(data: "Greetings", colors: [
                    Colors.red,
                    Colors.yellow,
                  ]),
                ),
                Center(
                  child: TextGradientColorWidget(data: "Greetings", colors: [
                    Colors.red,
                    Colors.yellow,
                  ]),
                )
              ],
            )
          ],
        ) // This trailing comma makes auto-formatting nicer for build methods.
        );
  }
}
//根據實際需求設置相關參數
class TextGradientColorWidget extends StatefulWidget {
  String data;
  TextStyle style;
  List<Color> colors;

  TextGradientColorWidget({Key key, this.data, this.colors}) : super(key: key);

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

class _TextGradientColorState extends State<TextGradientColorWidget> {
  WidgetsBinding widgetsBinding = WidgetsBinding.instance;

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    if (widget.colors != null) {
      widgetsBinding.addPostFrameCallback((timeStamp) {
        final RenderBox box = context.findRenderObject();
        var left = 0.0;
        var width = 0.0;
        if (box != null) {
          final topLeftPosition = box.localToGlobal(Offset.zero);
          final size = box.size;
          left = topLeftPosition.dx;
          width = size.width;
          setState(() {
            widget.style = TextStyle(
                fontSize: 30,
                foreground: Paint()
                  ..shader =
                      LinearGradient(colors: widget.colors, stops: [0.3, 0.8])
                          .createShader(Rect.fromLTWH(left, 0, width, 0)));
          });

          //注意 TextStyle中color和foreground 中colors不能同時設置
        }
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Text(widget.data, style: widget.style);
  }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM