Codelabのサンプルアプリ作成サイトでECアプリを作成中です。ホーム画面のAppBarのTitleを変更する作業をしています。
変更前 | 変更後 |
---|---|
titleプロパティにじAnimatedWidgetを拡張させた_BackdropTitle
を定義し引数listenable
にAnimationControllerを渡しています。
import 'package:Shrine/login.dart'; import 'package:flutter/material.dart'; import 'package:meta/meta.dart'; import 'model/product.dart'; import 'login.dart'; const double _kFlingVelocity = 2.0; class Backdrop extends StatefulWidget { final Category currentCategory; final Widget frontLayer; final Widget backLayer; final Widget frontTitle; final Widget backTitle; const Backdrop({ Key? key, required this.currentCategory, required this.frontLayer, required this.backLayer, required this.frontTitle, required this.backTitle, }) : super(key: key); @override _BackdropState createState() => _BackdropState(); } class _BackdropState extends State<Backdrop> with SingleTickerProviderStateMixin { final GlobalKey _backdropKey = GlobalKey(debugLabel: 'Backdrop'); late AnimationController _controller; @override void initState() { super.initState(); _controller = AnimationController( vsync: this, duration: Duration(milliseconds: 300), value: 1.0, ); } @override void dispose() { _controller.dispose(); super.dispose(); } bool get _frontLayerVisible { final AnimationStatus status = _controller.status; return status == AnimationStatus.completed || status == AnimationStatus.forward; } void _toggleBackdropLayerVisibility() { _controller.fling( velocity: _frontLayerVisible ? -_kFlingVelocity : _kFlingVelocity); } Widget _buildStack(BuildContext context, BoxConstraints constraints) { const double layerTitleHeight = 48.0; final Size layerSize = constraints.biggest; final double layerTop = layerSize.height - layerTitleHeight; Animation<RelativeRect> layerAnimation = RelativeRectTween( begin: RelativeRect.fromLTRB( 0.0, layerTop, 0.0, layerTop - layerSize.height), end: RelativeRect.fromLTRB(0, 0, 0, 0), ).animate(_controller.view); return Stack( key: _backdropKey, children: [ ExcludeSemantics( child: widget.backLayer, excluding: _frontLayerVisible, ), PositionedTransition( rect: layerAnimation, child: _FrontLayer( onTap: _toggleBackdropLayerVisibility, child: widget.frontLayer), ), ], ); } @override void didUpdateWidget(Backdrop old) { super.didUpdateWidget(old); if (widget.currentCategory != old.currentCategory) { _toggleBackdropLayerVisibility(); } else if (!_frontLayerVisible) { _controller.fling(velocity: _kFlingVelocity); } } @override Widget build(BuildContext context) { var appBar = AppBar( brightness: Brightness.light, elevation: 0.0, titleSpacing: 0.0, title: _BackdropTitle( // AppBarのtitleプロパティにセット listenable: _controller.view, onPress: _toggleBackdropLayerVisibility, frontTitle: widget.frontTitle, backTitle: widget.backTitle, ), actions: [ IconButton( icon: Icon( Icons.search, semanticLabel: 'login', ), onPressed: () { Navigator.push( context, MaterialPageRoute(builder: (context) => LoginPage()), ); }), IconButton( icon: Icon( Icons.tune, semanticLabel: 'login', ), onPressed: () { Navigator.push( context, MaterialPageRoute(builder: (context) => LoginPage()), ); }), ], ); return Scaffold( appBar: appBar, body: LayoutBuilder( builder: _buildStack, ), ); } } class _FrontLayer extends StatelessWidget { const _FrontLayer({Key? key, required this.child, required this.onTap}) : super(key: key); final Widget child; final VoidCallback onTap; @override Widget build(BuildContext context) { return Material( elevation: 16.0, shape: BeveledRectangleBorder( borderRadius: BorderRadius.only(topLeft: Radius.circular(46.0)), ), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ GestureDetector( behavior: HitTestBehavior.opaque, onTap: onTap, child: Container( height: 40.0, alignment: AlignmentDirectional.centerStart, ), ), Expanded(child: child), ], ), ); } }
そして、_BackdropTitle
のビルド内でAnimation<double>の変数animation
に渡したコントローラーを代入するとエラーが発生します。
class _BackdropTitle extends AnimatedWidget { final Function onPress; final Widget frontTitle; final Widget backTitle; const _BackdropTitle({ Key? key, required Listenable listenable, required this.onPress, required this.frontTitle, required this.backTitle, }) : assert(frontTitle != null), assert(backTitle != null), super(key: key, listenable: listenable); @override Widget build(BuildContext context) { final Animation<double> animation = this.listenable; // ここでエラー発生 return DefaultTextStyle( style: Theme.of(context).primaryTextTheme.headline6!, softWrap: false, overflow: TextOverflow.ellipsis, child: Row(children: <Widget>[ // branded icon SizedBox( width: 72.0, child: IconButton( padding: EdgeInsets.only(right: 8.0), onPressed: () => this.onPress, icon: Stack(children: <Widget>[ Opacity( opacity: animation.value, child: ImageIcon(AssetImage('assets/slanted_menu.png')), ), FractionalTranslation( translation: Tween<Offset>( begin: Offset.zero, end: Offset(1.0, 0.0), ).evaluate(animation), child: ImageIcon(AssetImage('assets/diamond.png')), ) ]), ), ), // Here, we do a custom cross fade between backTitle and frontTitle. // This makes a smooth animation between the two texts. Stack( children: <Widget>[ Opacity( opacity: CurvedAnimation( parent: ReverseAnimation(animation), curve: Interval(0.5, 1.0), ).value, child: FractionalTranslation( translation: Tween<Offset>( begin: Offset.zero, end: Offset(0.5, 0.0), ).evaluate(animation), child: backTitle, ), ), Opacity( opacity: CurvedAnimation( parent: animation, curve: Interval(0.5, 1.0), ).value, child: FractionalTranslation( translation: Tween<Offset>( begin: Offset(-0.25, 0.0), end: Offset.zero, ).evaluate(animation), child: frontTitle, ), ), ], ) ]), ); } }
error: A value of type 'Listenable' can't be assigned to a variable of type 'Animation<double>'. (invalid_assignment at [Shrine] lib/backdrop.dart:209)
型の不一致みたいですが、サンプルのコード通りに記述しています。
サイトにもそのようなことは書かれていませんでした。
調べても全くでここない症状のため質問いたしました。
ご協力いただけると助かります。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/07/31 05:08