[Flutter]要素を重ねたい時はStack
左のオレンジ部分をタップすると、2枚目の写真の様にオレンジ部分が消える。CardItemクラスのisTappedがtrue又はfalseでStackの重ねる部分を表示させるかどうか決めている。
import 'package:flutter/material.dart';
class CardItem {
final String title;
final String urlImage;
final Color color;
final bool isTapped;
const CardItem({
@required this.title,
@required this.urlImage,
@required this.color,
this.isTapped = false,
});
CardItem copy({
String title,
String urlImage,
Color color,
bool isTapped,
}) =>
CardItem(
title: title ?? this.title,
urlImage: urlImage ?? this.urlImage,
color: color ?? this.color,
isTapped: isTapped ?? this.isTapped,
);
}
class CardPage extends StatefulWidget {
@override
_MyCardState createState() => _MyCardState();
}
class _MyCardState extends State<CardPage> {
List<CardItem> items = <CardItem>[
CardItem(
title: 'Painting',
color: Colors.orange,
urlImage:
'https://images.unsplash.com/photo-1503454537195-1dcabb73ffb9?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=333&q=80',
),
CardItem(
title: 'Fun',
color: Colors.blue,
urlImage:
'https://images.unsplash.com/photo-1578878799601-d40c1b42d86c?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=400&q=60',
),
CardItem(
title: 'Sport',
color: Colors.deepPurple,
urlImage:
'https://images.unsplash.com/photo-1518611012118-696072aa579a?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=400&q=60',
),
CardItem(
title: 'Animals',
color: Colors.green,
urlImage:
'https://images.unsplash.com/photo-1601758063541-d2f50b4aafb2?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=994&q=80',
),
CardItem(
title: 'Reading',
color: Colors.red,
urlImage:
'https://images.unsplash.com/photo-1491841550275-ad7854e35ca6?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=967&q=80',
),
CardItem(
title: 'Ideas',
color: Colors.greenAccent,
urlImage:
'https://images.unsplash.com/photo-1542178432-52211bc52073?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=634&q=80',
),
];
@override
Widget build(BuildContext context) {
return Scaffold(
body: GridView.builder(
padding: EdgeInsets.all(8.0),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 8.0,
mainAxisSpacing: 8.0,
childAspectRatio: 3 / 4,
),
itemCount: items.length,
itemBuilder: (context, index) {
final item = items[index];
return buildCard(item: item);
},
),
);
}
Widget buildCard({@required CardItem item}) => GestureDetector(
onTapDown: (_) => setTapped(item, isTapped: true),
onTapUp: (_) => setTapped(item, isTapped: false),
onTapCancel: () => setTapped(item, isTapped: false),
child: ClipRRect(
borderRadius: BorderRadius.circular(24),
child: Stack(
fit: StackFit.expand,
children: [
Container(
color: item.color,
child: AnimatedOpacity(
duration: Duration(milliseconds: 500),
opacity: item.isTapped ? 1 : 0.5,
child: Image.network(item.urlImage, fit: BoxFit.cover),
),
),
if (!item.isTapped)
Center(
child: Text(
item.title,
style: TextStyle(fontSize: 24, color: Colors.white),
),
),
],
),
),
);
void setTapped(CardItem item, {@required bool isTapped}) {
setState(() {
this.items = items
.map((otherItem) =>
item == otherItem ? item.copy(isTapped: isTapped) : otherItem)
.toList();
});
}
}
こちらの内容です。