Line data Source code
1 : import 'package:cached_network_image/cached_network_image.dart';
2 : import 'package:flutter/material.dart';
3 : import 'package:flutter/services.dart';
4 : import 'package:flutter/widgets.dart';
5 : import 'package:pal/src/theme.dart';
6 :
7 : class MediaCellWidget extends StatefulWidget {
8 : final String id;
9 : final String url;
10 : final bool isSelected;
11 : final Function() onTap;
12 :
13 1 : MediaCellWidget({
14 : Key key,
15 : @required this.id,
16 : @required this.url,
17 : this.isSelected = false,
18 : this.onTap,
19 1 : }) : super(key: key);
20 :
21 1 : @override
22 1 : _MediaCellWidgetState createState() => _MediaCellWidgetState();
23 : }
24 :
25 : class _MediaCellWidgetState extends State<MediaCellWidget>
26 : with SingleTickerProviderStateMixin {
27 : AnimationController _animationController;
28 : double _scale;
29 : Duration _duration = Duration(milliseconds: 100);
30 :
31 1 : @override
32 : void initState() {
33 2 : _animationController = AnimationController(
34 : vsync: this,
35 1 : duration: _duration,
36 : lowerBound: 0.0,
37 : upperBound: 0.1,
38 1 : )..addListener(() {
39 0 : setState(() {});
40 : });
41 1 : super.initState();
42 : }
43 :
44 1 : @override
45 : void dispose() {
46 2 : _animationController?.dispose();
47 1 : super.dispose();
48 : }
49 :
50 1 : @override
51 : Widget build(BuildContext context) {
52 4 : _scale = 1 - _animationController.value;
53 :
54 1 : return GestureDetector(
55 4 : key: ValueKey('pal_MediaCellWidget_${widget.id}'),
56 1 : onTapDown: _onTapDown,
57 1 : onTapUp: _onTapUp,
58 1 : onTapCancel: _onTapCancel,
59 1 : child: Transform.scale(
60 1 : scale: _scale,
61 1 : child: Stack(
62 1 : children: [
63 1 : CachedNetworkImage(
64 2 : imageUrl: widget.url,
65 3 : placeholder: (context, url) => Center(child: CircularProgressIndicator()),
66 0 : errorWidget: (context, url, error) => Center(child: Icon(Icons.error)),
67 : ),
68 1 : Container(
69 1 : decoration: BoxDecoration(
70 4 : image: DecorationImage(image: CachedNetworkImageProvider(widget.url),
71 : fit: BoxFit.cover),
72 1 : border: Border.all(
73 3 : color: PalTheme.of(context).colors.color1,
74 : width: 6.0,
75 2 : style: (widget.isSelected)
76 : ? BorderStyle.solid
77 : : BorderStyle.none,
78 : ),
79 : ),
80 : ),
81 3 : if (widget.isSelected) _buildCheckbox()
82 : ],
83 : ),
84 : ),
85 : );
86 : }
87 :
88 1 : _buildCheckbox() {
89 1 : return Align(
90 : alignment: Alignment.topRight,
91 1 : child: Container(
92 : height: 25,
93 : width: 25,
94 1 : decoration: BoxDecoration(
95 1 : borderRadius: BorderRadius.only(
96 : bottomLeft: const Radius.circular(10.0),
97 : ),
98 4 : color: PalTheme.of(context).colors.color1,
99 : ),
100 1 : child: Center(
101 1 : child: Icon(
102 : Icons.check,
103 4 : key: ValueKey('pal_MediaCellWidget_${widget.id}'),
104 : color: Colors.white,
105 : size: 15,
106 : ),
107 : ),
108 : ),
109 : );
110 : }
111 :
112 0 : _onTapDown(TapDownDetails details) {
113 0 : _animationController.forward();
114 0 : HapticFeedback.selectionClick();
115 : }
116 :
117 0 : _onTapUp(TapUpDetails details) {
118 0 : Future.delayed(_duration, () {
119 0 : _animationController.reverse();
120 : });
121 0 : widget.onTap();
122 : }
123 :
124 0 : _onTapCancel() {
125 0 : _animationController.reverse();
126 : }
127 : }
|