鉴于这些宽度:
const DESKTOP_RESULT_DETAILS_WIDTH = 370.0;
const DESKTOP_SEARCH_RESULTS_WIDTH = 320.0;
_mapWidth =
MediaQuery.of(context).size.width - DESKTOP_SEARCH_RESULTS_WIDTH;
当名为
Position(left: DESKTOP_SEARCH_RESULTS_WIDTH)
的变量为空时,我正在尝试将小部件动画化为_model
,而当Position(left: DESKTOP_SEARCH_RESULTS_WIDTH + DESKTOP_RESULT_DETAILS_WIDTH)
不为空时为_model
。
问题是在每个动画开始时,它从错误的位置开始动画,然后在正确的位置结束。谁能看到我的代码的问题?:
AnimationController 定义:
@override
void initState() {
_mapAc = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 1000),
value: 0,
);
super.initState();
}
计算左侧位置:
double _mapLeft({required SearchResultModel? model}) {
if (model == null) {
return (_mapWidth * _mapAc.value) + DESKTOP_SEARCH_RESULTS_WIDTH;
} else {
return _mapAc.value *
(DESKTOP_SEARCH_RESULTS_WIDTH + DESKTOP_RESULT_DETAILS_WIDTH);
}
}
动画定义和触发动画的代码:
final animation = Tween(
begin: DESKTOP_SEARCH_RESULTS_WIDTH,
end: DESKTOP_SEARCH_RESULTS_WIDTH + DESKTOP_RESULT_DETAILS_WIDTH)
.animate(_mapAc);
ref.listen<SearchResultModel?>(vgnItmEstDetailsProvider, (previous, next) {
if (next != null) {
_mapAc.animateTo(1, duration: Duration(milliseconds: 1000));
} else {
_mapAc.animateTo(0, duration: Duration(milliseconds: 1000));
}
});
动画建造者:
AnimatedBuilder(
animation: animation,
builder: (context, child) {
return Positioned(
left: _mapLeft(model: _model),
child: SizedBox(
width: MediaQuery.of(context).size.width -
DESKTOP_SEARCH_RESULTS_WIDTH,
height: MediaQuery.of(context).size.height - TOP_NAV_HEIGHT,
child: MapWidget(
vm,
),
),
);
},
)
希望有帮助
// ignore_for_file: constant_identifier_names
import 'package:flutter/material.dart';
void main() {
runApp(
const MaterialApp(
home: MyApp(),
),
);
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
const DESKTOP_RESULT_DETAILS_WIDTH = 370.0;
const DESKTOP_SEARCH_RESULTS_WIDTH = 320.0;
const TOP_NAV_HEIGHT = 64.0;
class _MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {
bool hasModel = false;
late AnimationController _mapAc;
@override
void initState() {
_mapAc = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 300),
);
super.initState();
}
double _mapLeft({required bool hasModel, required double animationValue}) {
final mapWidth =
MediaQuery.of(context).size.width - DESKTOP_SEARCH_RESULTS_WIDTH;
final positionWhereMapShouldBeIfHasModel =
DESKTOP_SEARCH_RESULTS_WIDTH + DESKTOP_RESULT_DETAILS_WIDTH;
final positionWhereMapShouldBeIfHasNoModel = DESKTOP_SEARCH_RESULTS_WIDTH;
final animationDiff = positionWhereMapShouldBeIfHasModel -
positionWhereMapShouldBeIfHasNoModel;
return positionWhereMapShouldBeIfHasNoModel +
(animationDiff * animationValue);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: ElevatedButton(
onPressed: () {
setState(() {
hasModel = !hasModel;
if (hasModel) {
_mapAc.animateTo(1);
} else {
_mapAc.animateTo(0);
}
});
},
child: const Text('Animate'),
),
),
body: Stack(
children: [
AnimatedBuilder(
animation: _mapAc,
builder: (context, child) {
return Positioned(
left:
_mapLeft(hasModel: hasModel, animationValue: _mapAc.value),
child: SizedBox(
width: MediaQuery.of(context).size.width -
DESKTOP_SEARCH_RESULTS_WIDTH,
height: MediaQuery.of(context).size.height - TOP_NAV_HEIGHT,
child: child,
),
);
},
child: const MapWidget(),
),
],
),
);
}
}
class MapWidget extends StatelessWidget {
const MapWidget({super.key});
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.red),
),
child: const Text('Map'),
);
}
}