颤动补间基本动画在FutureBuilder
内部不起作用
我已经使用gridview.builder创建了一个图片库页面,但是由于某种原因,该动画无法在futurebuilder
内运行。我直接在人体容器内的静态图像上尝试了相同的动画,效果非常好。需要某种方式来对futurebuilder中的网络图像进行动画处理。
class _GalleryGridState extends State<GalleryGrid>
with TickerProviderStateMixin {
AnimationController _controller;
Animation _squeezeOutAnimation, transformationAnim;
List<GalleryModel> lists = List();
Future<List<GalleryModel>> fetchPost() async {
final response =
await http.get("https://jsonplaceholder.typicode.com/photos");
if (response.statusCode == 200) {
var datas = json.decode(response.body);
lists = (datas as List)
.map((data) => new GalleryModel.fromJson(data))
.toList();
return lists;
} else {
throw Exception("Failed to load photos");
}
}
@override
void initState() {
super.initState();
_controller =
AnimationController(duration: Duration(seconds: 3), vsync: this);
transformationAnim = BorderRadiusTween(
begin: BorderRadius.circular(150.0),
end: BorderRadius.circular(0.0))
.animate(CurvedAnimation(parent: _controller, curve: Curves.ease));
_squeezeOutAnimation = Tween<double>(begin: 150.0, end: 1000.0)
.animate(CurvedAnimation(parent: _controller, curve: Curves.ease));
}
@override
void dispose() {
super.dispose();
_controller.dispose();
}
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: fetchPost(),
builder: (context, data) {
switch (data.connectionState) {
case ConnectionState.waiting:
return Center(child: CircularProgressIndicator());
default:
return GridView.builder(
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
itemCount: lists.length,
itemBuilder: (BuildContext context, int index) {
return Stack(
children: <Widget>[
Container(
child: Card(
shape: BeveledRectangleBorder(
borderRadius: transformationAnim.value),
elevation: 10.0,
child: GestureDetector(
onTap: () {
_controller.forward();
},
child: Container(
width: _squeezeOutAnimation.value,
height: _squeezeOutAnimation.value,
child: Image.network(
lists[index].thumbnailUrl,
fit: BoxFit.fill,
width: _squeezeOutAnimation.value,
),
),
),
),
),
])
答案 0 :(得分:0)
您可以使用Hero小部件,该小部件通过使用标签为您完成许多工作:
class HomePage extends StatefulWidget {
@override
State<StatefulWidget> createState() => new _HomePageState();
}
class _HomePageState extends State<HomePage> {
List<Image> images;
@override
void initState() {
images = new List<Image>();
images.add(Image.asset("assets/blue.png"));
images.add(Image.asset("assets/red.png"));
images.add(Image.asset("assets/green.png"));
images.add(Image.asset("assets/yellow.png"));
images.add(Image.asset("assets/pink.png"));
images.add(Image.asset("assets/cyan.png"));
// get images
super.initState();
}
@override
Widget build(BuildContext context) {
return Material(
child: GridView.builder(
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
itemCount: images.length,
itemBuilder: (context, index) {
String tag = "Image" + index.toString();
return Hero(
tag: tag,
child: Material(
child: InkWell(
child: GridTile(child: images[index]),
onTap: () {
Navigator.push(context, MaterialPageRoute(builder: (context) {
return Scaffold(
appBar: AppBar(title: Text(tag)),
body: ImagePage(image: images[index], imageTag: tag));
}));
},
)));
},
));
}
}
class ImagePage extends StatefulWidget {
final Image image;
final String imageTag;
ImagePage({this.image, this.imageTag});
@override
State<StatefulWidget> createState() => new _ImagePageState();
}
class _ImagePageState extends State<ImagePage> {
@override
Widget build(BuildContext context) {
return Hero(
tag: widget.imageTag,
child: Material(
child: Center(
child: widget.image,
),
),
);
}
}
答案 1 :(得分:0)
动画正在运行,但是您的构建窗口小部件未更新,即重建
如果您期望的那样运行此代码,请告诉我。
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:async';
import 'dart:convert';
void main() => runApp(GalleryGrid());
class GalleryGrid extends StatefulWidget {
@override
_GalleryGridState createState() => _GalleryGridState();
}
class GalleryModel {
final String thumbnailUrl;
GalleryModel(this.thumbnailUrl);
factory GalleryModel.fromJson(Map<String, dynamic> data) {
return GalleryModel(data['thumbnailUrl']);
}
}
class _GalleryGridState extends State<GalleryGrid>
{
List<GalleryModel> lists = List();
Future<List<GalleryModel>> fetchPost() async {
final response =
await http.get("https://jsonplaceholder.typicode.com/photos");
if (response.statusCode == 200) {
var datas = json.decode(response.body);
lists = (datas as List)
.map((data) => new GalleryModel.fromJson(data))
.toList();
return lists;
} else {
throw Exception("Failed to load photos");
}
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: FutureBuilder(
future: fetchPost(),
builder: (context, data) {
switch (data.connectionState) {
case ConnectionState.waiting:
return Center(child: CircularProgressIndicator());
default:
return new GridWidget(lists: lists);
}
},
),
),
);
//),
//);
}
}
class GridWidget extends StatefulWidget {
const GridWidget({
Key key,
@required this.lists,
}) ;
final List<GalleryModel> lists;
@override
GridWidgetState createState() {
return new GridWidgetState();
}
}
class GridWidgetState extends State<GridWidget> with TickerProviderStateMixin{
AnimationController _controller;
Animation _squeezeOutAnimation, transformationAnim;
@override
void initState() {
super.initState();
_controller =
AnimationController(duration: Duration(seconds: 3), vsync: this);
transformationAnim = BorderRadiusTween(
begin: BorderRadius.circular(150.0),
end: BorderRadius.circular(0.0))
.animate(CurvedAnimation(parent: _controller, curve: Curves.ease))
..addListener(() {
setState(() {});
});
_squeezeOutAnimation = Tween<double>(begin: 150.0, end: 1000.0)
.animate(CurvedAnimation(parent: _controller, curve: Curves.ease));
}
@override
void dispose() {
super.dispose();
_controller.dispose();
}
@override
Widget build(BuildContext context) {
return GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2),
itemCount: widget.lists.length,
itemBuilder: (BuildContext context, int index) {
return Stack(children: <Widget>[
Container(
child: Card(
shape: BeveledRectangleBorder(
borderRadius: transformationAnim.value),
elevation: 10.0,
child: GestureDetector(
onTap: () {
print('Card $index is pressed');
_controller.reset();
_controller.forward();
},
child: Container(
width: _squeezeOutAnimation.value,
height: _squeezeOutAnimation.value,
child: Image.network(
widget.lists[index].thumbnailUrl,
fit: BoxFit.fill,
width: _squeezeOutAnimation.value,
),
),
),
),
),
]);
},
);
}
}