Line data Source code
1 : import 'package:flutter/material.dart';
2 : import 'package:flutter/services.dart';
3 : import 'package:flutter/widgets.dart';
4 : import 'package:pal/src/theme.dart';
5 :
6 : class PreviewCard {
7 : final String previewImage;
8 : final String title;
9 : final String description;
10 : bool isSelected;
11 :
12 3 : PreviewCard(
13 : this.previewImage,
14 : this.title,
15 : this.description, {
16 : this.isSelected = false,
17 : });
18 : }
19 :
20 : class PreviewCardWidget extends StatefulWidget {
21 : final PreviewCard cardData;
22 : final int index;
23 : final Function(int) onTap;
24 :
25 2 : const PreviewCardWidget({
26 : Key key,
27 : @required this.cardData,
28 : this.index,
29 : this.onTap,
30 2 : }) : super(key: key);
31 :
32 2 : @override
33 2 : _PreviewCardWidgetState createState() => _PreviewCardWidgetState();
34 : }
35 :
36 : class _PreviewCardWidgetState extends State<PreviewCardWidget>
37 : with SingleTickerProviderStateMixin {
38 : AnimationController _animationController;
39 : double _scale;
40 : Duration _duration = Duration(milliseconds: 100);
41 :
42 2 : @override
43 : void initState() {
44 4 : _animationController = AnimationController(
45 : vsync: this,
46 2 : duration: _duration,
47 : lowerBound: 0.0,
48 : upperBound: 0.1,
49 2 : )..addListener(() {
50 0 : setState(() {});
51 : });
52 2 : super.initState();
53 : }
54 :
55 2 : @override
56 : void dispose() {
57 4 : _animationController?.dispose();
58 2 : super.dispose();
59 : }
60 :
61 2 : @override
62 : Widget build(BuildContext context) {
63 8 : _scale = 1 - _animationController.value;
64 :
65 2 : return GestureDetector(
66 8 : key: ValueKey('pal_PreviewCard_${widget.index}'),
67 2 : onTapDown: _onTapDown,
68 2 : onTapUp: _onTapUp,
69 2 : onTapCancel: _onTapCancel,
70 2 : child: Transform.scale(
71 2 : scale: _scale,
72 2 : child: Card(
73 2 : shape: RoundedRectangleBorder(
74 2 : borderRadius: BorderRadius.circular(25.0),
75 6 : side: (widget.cardData.isSelected)
76 2 : ? BorderSide(
77 6 : color: PalTheme.of(context).colors.color1,
78 : width: 6.0,
79 : )
80 : : BorderSide.none,
81 : ),
82 : elevation: 15,
83 2 : child: Stack(
84 2 : children: [
85 8 : if (widget.cardData.isSelected) _buildCheckbox(),
86 2 : Column(
87 2 : children: [
88 2 : Expanded(
89 2 : child: Padding(
90 : padding: const EdgeInsets.symmetric(
91 : vertical: 20.0,
92 : horizontal: 35.0,
93 : ),
94 8 : child: Image.asset(widget.cardData.previewImage),
95 : ),
96 : ),
97 2 : Padding(
98 : padding: const EdgeInsets.only(
99 : left: 20.0,
100 : right: 20.0,
101 : bottom: 30.0,
102 : ),
103 2 : child: Column(
104 : crossAxisAlignment: CrossAxisAlignment.start,
105 2 : children: [
106 2 : Text(
107 6 : widget.cardData.title,
108 : maxLines: 2,
109 : overflow: TextOverflow.ellipsis,
110 2 : style: TextStyle(
111 : fontSize: 20.0,
112 : fontWeight: FontWeight.w500,
113 : ),
114 : ),
115 2 : SizedBox(height: 6.0),
116 2 : Text(
117 6 : widget.cardData.description,
118 : maxLines: 4,
119 : overflow: TextOverflow.ellipsis,
120 2 : style: TextStyle(
121 : fontSize: 11.0,
122 : fontWeight: FontWeight.w300,
123 : ),
124 : ),
125 : ],
126 : ),
127 : ),
128 : ],
129 : ),
130 : ],
131 : ),
132 : ),
133 : ),
134 : );
135 : }
136 :
137 2 : _buildCheckbox() {
138 2 : return Align(
139 : alignment: Alignment.topRight,
140 2 : child: Container(
141 : height: 50,
142 : width: 50,
143 2 : decoration: BoxDecoration(
144 2 : borderRadius: BorderRadius.only(
145 : topRight: const Radius.circular(25.0),
146 : bottomLeft: const Radius.circular(25.0),
147 : ),
148 8 : color: PalTheme.of(context).colors.color1,
149 : ),
150 2 : child: Center(
151 2 : child: Icon(
152 : Icons.check,
153 8 : key: ValueKey('pal_PreviewCard_Check_${widget.index}'),
154 : color: Colors.white,
155 : ),
156 : ),
157 : ),
158 : );
159 : }
160 :
161 2 : _onTapDown(TapDownDetails details) {
162 4 : _animationController.forward();
163 2 : HapticFeedback.selectionClick();
164 : }
165 :
166 2 : _onTapUp(TapUpDetails details) {
167 6 : Future.delayed(_duration, () {
168 4 : _animationController.reverse();
169 : });
170 10 : widget.onTap(widget.index);
171 : }
172 :
173 1 : _onTapCancel() {
174 2 : _animationController.reverse();
175 : }
176 : }
|