Flutter實(shí)戰(zhàn) 組合現(xiàn)有組件

2021-03-08 18:02 更新

在 Flutter 中頁面UI通常都是由一些低階別的組件組合而成,當(dāng)我們需要封裝一些通用組件時(shí),應(yīng)該首先考慮是否可以通過組合其它組件來實(shí)現(xiàn),如果可以,則應(yīng)優(yōu)先使用組合,因?yàn)橹苯油ㄟ^現(xiàn)有組件拼裝會(huì)非常簡(jiǎn)單、靈活、高效。

#示例:自定義漸變按鈕

Flutter Material 組件庫中的按鈕默認(rèn)不支持漸變背景,為了實(shí)現(xiàn)漸變背景按鈕,我們自定義一個(gè)GradientButton組件,它需要支持一下功能:

  1. 背景支持漸變色
  2. 手指按下時(shí)有漣漪效果
  3. 可以支持圓角

我們先來看看最終要實(shí)現(xiàn)的效果(圖10-1):

gradient-button

我們DecoratedBox可以支持背景色漸變和圓角,InkWell在手指按下有漣漪效果,所以我們可以通過組合DecoratedBoxInkWell來實(shí)現(xiàn)GradientButton,代碼如下:

  1. import 'package:flutter/material.dart';
  2. class GradientButton extends StatelessWidget {
  3. GradientButton({
  4. this.colors,
  5. this.width,
  6. this.height,
  7. this.onPressed,
  8. this.borderRadius,
  9. @required this.child,
  10. });
  11. // 漸變色數(shù)組
  12. final List<Color> colors;
  13. // 按鈕寬高
  14. final double width;
  15. final double height;
  16. final Widget child;
  17. final BorderRadius borderRadius;
  18. //點(diǎn)擊回調(diào)
  19. final GestureTapCallback onPressed;
  20. @override
  21. Widget build(BuildContext context) {
  22. ThemeData theme = Theme.of(context);
  23. //確保colors數(shù)組不空
  24. List<Color> _colors = colors ??
  25. [theme.primaryColor, theme.primaryColorDark ?? theme.primaryColor];
  26. return DecoratedBox(
  27. decoration: BoxDecoration(
  28. gradient: LinearGradient(colors: _colors),
  29. borderRadius: borderRadius,
  30. ),
  31. child: Material(
  32. type: MaterialType.transparency,
  33. child: InkWell(
  34. splashColor: _colors.last,
  35. highlightColor: Colors.transparent,
  36. borderRadius: borderRadius,
  37. onTap: onPressed,
  38. child: ConstrainedBox(
  39. constraints: BoxConstraints.tightFor(height: height, width: width),
  40. child: Center(
  41. child: Padding(
  42. padding: const EdgeInsets.all(8.0),
  43. child: DefaultTextStyle(
  44. style: TextStyle(fontWeight: FontWeight.bold),
  45. child: child,
  46. ),
  47. ),
  48. ),
  49. ),
  50. ),
  51. ),
  52. );
  53. }
  54. }

可以看到GradientButton是由DecoratedBoxPadding、Center、InkWell等組件組合而成。當(dāng)然上面的代碼只是一個(gè)示例,作為一個(gè)按鈕它還并不完整,比如沒有禁用狀態(tài),讀者可以根據(jù)實(shí)際需要來完善。

#使用GradientButton

  1. import 'package:flutter/material.dart';
  2. import '../widgets/index.dart';
  3. class GradientButtonRoute extends StatefulWidget {
  4. @override
  5. _GradientButtonRouteState createState() => _GradientButtonRouteState();
  6. }
  7. class _GradientButtonRouteState extends State<GradientButtonRoute> {
  8. @override
  9. Widget build(BuildContext context) {
  10. return Container(
  11. child: Column(
  12. children: <Widget>[
  13. GradientButton(
  14. colors: [Colors.orange, Colors.red],
  15. height: 50.0,
  16. child: Text("Submit"),
  17. onPressed: onTap,
  18. ),
  19. GradientButton(
  20. height: 50.0,
  21. colors: [Colors.lightGreen, Colors.green[700]],
  22. child: Text("Submit"),
  23. onPressed: onTap,
  24. ),
  25. GradientButton(
  26. height: 50.0,
  27. colors: [Colors.lightBlue[300], Colors.blueAccent],
  28. child: Text("Submit"),
  29. onPressed: onTap,
  30. ),
  31. ],
  32. ),
  33. );
  34. }
  35. onTap() {
  36. print("button click");
  37. }
  38. }

#總結(jié)

通過組合的方式定義組件和我們之前寫界面并無差異,不過在抽離出單獨(dú)的組件時(shí)我們要考慮代碼規(guī)范性,如必要參數(shù)要用@required 標(biāo)注,對(duì)于可選參數(shù)在特定場(chǎng)景需要判空或設(shè)置默認(rèn)值等。這是由于使用者大多時(shí)候可能不了解組件的內(nèi)部細(xì)節(jié),所以為了保證代碼健壯性,我們需要在用戶錯(cuò)誤地使用組件時(shí)能夠兼容或報(bào)錯(cuò)提示(使用assert斷言函數(shù))。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)