【 開源計劃 - 元件包 】 旋轉切換 toggle_rotate

張風捷特烈發表於2020-03-01

pub地址 】 【github地址

dependencies:
  toggle_rotate: $lastVersion
複製程式碼

一、描述

目標: 讓一個元件點選時執行旋轉,再點選旋轉回去。

最簡使用 時長、曲線、方向 可含一切元件 旋轉角度
【  開源計劃 - 元件包 】 旋轉切換 toggle_rotate
【  開源計劃 - 元件包 】 旋轉切換 toggle_rotate
【  開源計劃 - 元件包 】 旋轉切換 toggle_rotate
【  開源計劃 - 元件包 】 旋轉切換 toggle_rotate
1.所有屬性:
名稱 型別 功能 備註 預設
rad double 旋轉角度 弧度制 pi / 2
durationMs int 動畫時長 毫秒 200
curve Curve 動畫曲線 - Curves.fastOutSlowIn
clockwise bool 是否順時針旋轉 - true
onTap Function 點選事件 @required null
child Widget 子元件 @required null

2.最簡使用:

【  開源計劃 - 元件包 】 旋轉切換 toggle_rotate

ToggleRotate(
  child: Icon(Icons.arrow_upward,size: 60,color: Colors.orangeAccent),
  onTap: () {}, //點選事件
),
複製程式碼

3.指定時長和曲線和方向

【  開源計劃 - 元件包 】 旋轉切換 toggle_rotate

ToggleRotate(
  curve: Curves.decelerate,
  durationMs: 400,//動畫時長
  clockwise: false, //是否是順時針
  child: Icon(Icons.arrow_upward,size: 60,color: Colors.orangeAccent),
  onTap: () {},
),
複製程式碼

4.可使一切元件進行旋轉切換

【  開源計劃 - 元件包 】 旋轉切換 toggle_rotate

ToggleRotate(
  curve: Curves.decelerate,
  durationMs: 400,
  child: Image(width:60,height: 60,image: AssetImage("assets/images/icon_28.jpg")),
  onTap: () {},
)
複製程式碼

5.可使旋轉的角度

【  開源計劃 - 元件包 】 旋轉切換 toggle_rotate

ToggleRotate(
  rad: pi / 4,
  curve: Curves.linear,
  child: Image(width:60,height: 60,image: AssetImage("assets/images/icon_28.jpg")),
  onTap: () {},
)
複製程式碼

二、實現原理

點選時進行一些動畫效果比較好看,順便抽離成一個元件分享一下
這個小元件是一個動畫的經典案例,所以分析一下具體實現還是很有意義的


1.自定義元件

開始分析一下是否有狀態。很明顯,我們需要在點選時讓元件旋轉
元件有是否旋轉是一個狀態量,旋轉過程中的角度也是狀態量
可以說想要實現動畫,基本上是基於StatefulWidget的,先寫出一個基本的元件
由於需要動畫,要with SingleTickerProviderStateMixin

library toggle_rotate;
import 'dart:math';
import 'package:flutter/material.dart';

class ToggleRotate extends StatefulWidget {
  final Widget child;
  final Function onTap;
  final double rad;
  final int durationMs;
  final bool clockwise;
  final Curve curve;

  ToggleRotate(
      {this.child,
      @required this.onTap,
      this.rad = pi / 2,
      this.clockwise = true,
      this.durationMs = 200,
      this.curve = Curves.fastOutSlowIn});

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

class _ToggleRotateState extends State<ToggleRotate> with SingleTickerProviderStateMixin {

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

  @override
  void dispose() 
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Container();
  }
}
複製程式碼

2.動畫器的建立和銷燬

狀態量有旋轉的弧_rad、是否已旋轉_rotated
動畫器AnimationController負責讓數字在0.0~1.0之間均勻變化
通過CurvedAnimation來讓數字變化率為曲線
核心就是確定每次更新狀態時弧度的大小。 通過addListener可以在動畫器每次重新整理時進行監聽
通過addStatusListener對動畫的狀態進行監聽,如果完成_rotated置反

class _ToggleRotateState extends State<ToggleRotate>
    with SingleTickerProviderStateMixin {
  double _rad = 0;
  bool _rotated = false;
  AnimationController _controller;
  Animation _rotate;

  @override
  void initState() {
    _controller = AnimationController(
        duration: Duration(milliseconds: widget.durationMs), vsync: this)
      ..addListener(() => setState(() =>
          _rad = (_rotated ? (1 - _rotate.value) : _rotate.value) * widget.rad))
      ..addStatusListener((status) {
        if (status == AnimationStatus.completed) {
          _rotated = !_rotated;
        }
      });
    _rotate = CurvedAnimation(parent: _controller, curve: widget.curve);
    super.initState();
  }
  
  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
複製程式碼

3.通過Transform實現變換

在點選時先重設控制器,然後再執行。否則第二次是不會動的
在這裡只用onTap回撥點選事件,暴露給外界處理。
clockwise決定是否是順時針旋轉,這樣該元件就完成了。

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () {
        _controller.reset();
        _controller.forward();
        widget.onTap();
      },
      child: Transform(
        transform: Matrix4.rotationZ(widget.clockwise ? _rad : -_rad),
        alignment: Alignment.center,
        child: widget.child,
      ),
    );
  }
複製程式碼

麻雀雖小五臟俱全,這個小元件雖然就60行左右的程式碼,但包含很多知識點。
如果你想要一個元件在點選時不那麼古板,歡迎使用

【  開源計劃 - 元件包 】 旋轉切換 toggle_rotate


尾聲

另外本人有一個Flutter微信交流群,歡迎小夥伴加入,共同探討Flutter的問題,期待與你的交流與切磋。

@張風捷特烈 2019.02.23 未允禁轉
我的公眾號:程式設計之王
聯絡我--郵箱:1981462002@qq.com --微信:zdl1994328
~ END ~

相關文章