1. 程式人生 > 其它 >Flutter不常用元件(五)

Flutter不常用元件(五)

PhysicalModel

為子元件設定陰影

它有以下幾個屬性:

  • Key? key:標識鍵
  • BoxShape shape:形狀。預設為BoxShape.rectangle
  • Clip clipBehavior:多餘部分裁剪效果。預設為Clip.none
  • BorderRadius? borderRadius:圓角
  • double elevation:相對於放置此物理物件的父級的 z 座標。預設為0.0
  • Color color:顏色
  • Color shadowColor:陰影顏色。預設為Color(0xFF000000)
  • Widget? child:子元件
Center(
  child: PhysicalModel(
    shape: BoxShape.rectangle,
    clipBehavior: Clip.none,
    borderRadius: BorderRadius.all(Radius.circular(12)),
    color: Colors.white,
    elevation: 4.0,
    shadowColor: Color(0xFF000000),
    child: SizedBox(width: 200, height: 200),
  ),
)

PhysicalShape

建立具有任意形狀剪輯的元件

它有以下幾個屬性:

  • Key? key:標識鍵
  • CustomClipper clipper:裁剪形狀。可以通過繼承CustomClipper自定義
  • Clip clipBehavior:多餘部分裁剪效果。預設為Clip.none
  • double elevation:相對於放置此物理物件的父級的 z 座標。預設為0.0
  • Color color:顏色
  • Color shadowColor:陰影顏色。預設為Color(0xFF000000)
  • Widget? child:子元件
Center(
  child: PhysicalShape(
    elevation: 5.0,
    clipper: ShapeBorderClipper(
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(100.0),
      ),
    ),
    color: Colors.orange,
    child: Container(
      height: 200.0,
      width: 200.0,
      alignment: Alignment.center,
      child: const Text(
        'Hello, World!',
        style: TextStyle(color: Colors.white, fontSize: 20.0),
      ),
    ),
  ),
)

PlatformAdaptiveIcons

使用Icons.adaptive開頭的圖示,可以在 Android 和 IOS 兩個平臺顯示不同的圖示樣式。

RotatedBox

旋轉子元件。旋轉角度有限

它有以下幾個屬性:

  • Key? key:標識鍵
  • int quarterTurns:旋轉角度。1代表90°,以此類推
  • Widget? child:子元件
Center(
  child: RotatedBox(
    quarterTurns: 1,
    child: FlutterLogo(size: 200),
  ),
)

SearchDelegate

定義搜尋頁面

我們先製作一個前往搜尋頁面的元件:

Center(
  child: Container(
    margin: const EdgeInsets.symmetric(horizontal: 16),
    child: TextField(
      readOnly: true,
      decoration: const InputDecoration(
        hintText: '搜尋',
        suffixIcon: Icon(Icons.search),
      ),
      onTap: () {},  // TODO
    ),
  ),
)

SearchDelegate不能直接使用,我們需要自定義一類來繼承它。

class SearchPage extends SearchDelegate<String> {
  @override
  List<Widget>? buildActions(BuildContext context) {
    return [
      IconButton(
        onPressed: () {
          query = '';
        },
        icon: const Icon(Icons.clear),
      ),
    ];
  }

  @override
  Widget? buildLeading(BuildContext context) {
    return const BackButton();
  }

  @override
  Widget buildResults(BuildContext context) {
    return searchContent();
  }

  @override
  Widget buildSuggestions(BuildContext context) {
    return searchContent();
  }

  Widget searchContent() {
    List<String> filterName = names
        .where((name) => name.toLowerCase().contains(query.toLowerCase()))
        .toList();
    return ListView.builder(
      itemCount: filterName.length,
      itemBuilder: (context, index) {
        return ListTile(
          title: Text(filterName[index]),
          onTap: () {
            query = filterName[index];
          },
        );
      },
    );
  }
}

接下來我們需要呼叫showSearch這個方法來顯示這個介面:

onTap: () {
	showSearch(context: context, delegate: SearchPage());
}

ShaderMask

建立一個將Shader生成的蒙版應用到其子級的小部件

它有以下幾個屬性:

  • Key? key:標識鍵
  • Shader Function(Rect) shaderCallback:呼叫以建立生成遮罩的dart:ui.Shader
  • BlendMode blendMode:平鋪模式。預設值為BlendMode.modulate
  • Widget? child:子元件
ShaderMask(
  shaderCallback: (bounds) => const RadialGradient(
    center: Alignment.topLeft,
    radius: 1.0,
    colors: [Colors.yellow, Colors.deepOrange],
    tileMode: TileMode.mirror,
  ).createShader(bounds),
  child: const Text(
    "Hello World",
    style: TextStyle(
      fontSize: 40,
      color: Colors.white,  // 一定要設定為白色
      fontWeight: FontWeight.bold,
    ),
  ),
)

SizedOverflowBox

關於該元件的詳細介紹可以檢視文章:SizedOverflowBox

Stepper

步驟元件

它有以下幾個元件:

  • Key? key:標識鍵
  • List stepsStep列表
  • ScrollPhysics? physics:物理滾動效果
  • StepperType type:步驟指示條顯示的方式。預設為StepperType.vertical
  • int currentStep:當前步驟。預設為0
  • void Function(int)? onStepTapped:步驟點選事件
  • void Function()? onStepContinue:步驟繼續事件
  • void Function()? onStepCancel:步驟取消事件
  • Widget Function(BuildContext ControlsDetails)? controlsBuilder:建立自定義控制元件
  • double? elevation:相對於放置此物理物件的父級的 z 座標。預設為0.0
  • EdgeInsetsGeometry? margin:外邊距
Stepper(
  currentStep: _index,
  onStepCancel: () {
    if (_index > 0) {
      setState(() {
        _index -= 1;
      });
    }
  },
  onStepContinue: () {
    if (_index <= 0) {
      setState(() {
        _index += 1;
      });
    }
  },
  onStepTapped: (int index) {
    setState(() {
      _index = index;
    });
  },
  steps: <Step>[
    Step(
      title: const Text('步驟 1'),
      content: Container(
        alignment: Alignment.centerLeft,
        child: const Text('確認是否繼續?'),
      ),
    ),
    const Step(
      title: Text('步驟 2'),
      content: Text('確定還繼續?'),
    ),
  ],
)

UnconstrainedBox

用於去除父元件的約束

它有以下幾個屬性:

  • Key? key:標識鍵
  • Widget? child:子元件
  • TextDirection? textDirection:文字方向
  • AlignmentGeometry alignment:對齊方式。預設為Alignment.center
  • Axis? constrainedAxis:保留約束的軸
  • Clip clipBehavior :裁剪效果。預設為Clip.none
UnconstrainedBox(
  constrainedAxis: Axis.vertical,
  child: Container(
    color: Colors.blue,
    width: 150,
  ),
)

![Slide 16_9 - 29](F:\學習\flutter\images\Slide 16_9 - 29.png)

如果我們不使用UnconstrainedBox,直接寫Container(color: Colors.blue)不寫寬高,會預設佔滿整個介面。當我們使用UnconstrainedBox後,Container不寫寬高就不會顯示任何東西,這裡Axis.vertical是保留垂直方向的約束,所以高度為這個介面,如果Container不寫寬度,照樣什麼都看不到。這個演示程式碼去掉UnconstrainedBox效果也是第二張圖,這裡只做該元件的講解。

WillPopScope

建立一個小部件,該小部件註冊回撥以否決使用者嘗試關閉封閉的ModalRoute

它有以下幾個屬性:

  • Key? key:標識鍵
  • Widget child:子元件
  • Future Function()? onWillPop:關閉封閉的ModalRoute事件
WillPopScope(
  child: Scaffold(
      appBar: AppBar(title: const Text("TestWidget")),
      body: const Center(
        child: Text("雙擊返回鍵退出"),
      )),
  onWillPop: () async {
    if (_lastQUitTime == null || DateTime.now().difference(_lastQUitTime!).inMilliseconds > 500) {
      _lastQUitTime = DateTime.now();
      return false;
    } else {
      Navigator.of(context).pop(true);
      // await SystemChannels.platform.invokeMethod('SystemNavigator.pop');
      return true;
    }
  },
)