矢印が移動しながら回転し、左側の横幅がそれに伴って変わる

NavigationRailだとカスタマイズが効かないので、 左メニューを自作できないかと試行錯誤中です。

今回は、メニューを開いたり閉じたりする部分を作ってみました。

NavigationRailも中身はConstrainedBoxなので、 minWidthをAnimationControllerで操作します。

import 'dart:math' as math;

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';

/// 矢印が移動しながら回転し、左側の領域のサイズが変わる
void main() {
  runApp(ProviderScope(
      child: MaterialApp(
          home: Scaffold(
    body: MyHomePage(),
  ))));
}

class MyHomePage extends HookWidget {
  @override
  Widget build(BuildContext context) {
    const _iconSize = 32.0;
    final controller = useAnimationController(
      duration: const Duration(milliseconds: 250),
    );
    useListenable(controller);
    return Row(
      children: [
        ConstrainedBox(
          // 160.0くらいが見た目的にいい感じなので、
          // (1 * 4 + 1) * 32 = 5 * 32
          constraints:
              BoxConstraints(minWidth: (controller.value * 4 + 1) * _iconSize),
          child: Align(
            alignment: Alignment.topLeft,
            child: FractionalTranslation(
              // Tween<Offset>を使うと指定が簡単になるが、
              // 最初は理解が難しくなるので使わない
              translation: Offset(controller.value * 4, 0),
              child: InkWell(
                onTap: () {
                  if (controller.isDismissed) {
                    controller.forward();
                  } else if (controller.isCompleted) {
                    controller.reverse();
                  }
                },
                child: Transform.rotate(
                  angle: controller.value * math.pi,
                  child: const Icon(
                    Icons.arrow_right,
                    size: _iconSize,
                  ),
                ),
              ),
            ),
          ),
        ),
        VerticalDivider(thickness: 1, width: 1),
        Expanded(
          child: Center(
            child: MyRightWidget(),
          ),
        )
      ],
    );
  }
}

class MyRightWidget extends HookWidget {
  @override
  Widget build(BuildContext context) {
    return Container();
  }
}

20210320103201 20210320103206

プロジェクトの構成などはこちら

https://github.com/na8esin/flutter_side_menu_study/blob/main/lib/study/animation/FractionalTranslation/Rotating_arrow_and_left_menu.dart

追記:2021/7/14 アイコン部分はAnimatedIconでもいいのかもしれない