Skip to content

Commit c200f33

Browse files
committed
Create UI Detail Movie
1 parent 913e2a9 commit c200f33

8 files changed

+284
-6
lines changed

Diff for: assets/images/screenshot_1_backdrop_path.jpeg

25.3 KB
Loading

Diff for: assets/images/screenshot_2_backdrop_path.jpeg

21.5 KB
Loading

Diff for: assets/images/screenshot_3_backdrop_path.jpeg

21.1 KB
Loading

Diff for: assets/images/screenshot_4_backdrop_path.jpeg

37.4 KB
Loading

Diff for: assets/images/screenshot_5_backdrop_path.jpeg

25.9 KB
Loading

Diff for: lib/src/ui/detail/detail_screen.dart

+272-5
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import 'dart:io';
22

33
import 'package:flutter/cupertino.dart';
44
import 'package:flutter/material.dart';
5+
import 'package:flutter_rating_bar/flutter_rating_bar.dart';
6+
import 'package:flutter_ui_cinemax/res/color_app.dart';
57
import 'package:flutter_ui_cinemax/src/model/banner/banner_movie.dart';
68

79
class DetailScreen extends StatelessWidget {
@@ -22,10 +24,29 @@ class DetailScreen extends StatelessWidget {
2224
children: <Widget>[
2325
Stack(
2426
children: <Widget>[
25-
WavyHeaderImage(bannerMovie.backdropPath),
27+
BackdropImage(bannerMovie.backdropPath),
2628
_buildWidgetAppBar(mediaQuery),
29+
_buildWidgetFloatingActionButton(mediaQuery),
30+
_buildWidgetIconBuyAndShare(mediaQuery),
2731
],
2832
),
33+
Expanded(
34+
child: ListView(
35+
children: <Widget>[
36+
_buildWidgetTitleMovie(context),
37+
SizedBox(height: 4.0),
38+
_buildWidgetGenreMovie(context),
39+
SizedBox(height: 16.0),
40+
_buildWidgetRating(),
41+
SizedBox(height: 16.0),
42+
_buildWidgetShortDescriptionMovie(context),
43+
SizedBox(height: 16.0),
44+
_buildWidgetSynopsisMovie(context),
45+
SizedBox(height: 16.0),
46+
_buildWidgetScreenshots(mediaQuery, context),
47+
],
48+
),
49+
),
2950
],
3051
),
3152
),
@@ -60,12 +81,258 @@ class DetailScreen extends StatelessWidget {
6081
),
6182
);
6283
}
84+
85+
Widget _buildWidgetFloatingActionButton(MediaQueryData mediaQuery) {
86+
return Column(
87+
children: <Widget>[
88+
SizedBox(height: mediaQuery.size.height / 2 - 60),
89+
Center(
90+
child: FloatingActionButton(
91+
onPressed: () {
92+
// TODO: do something in here
93+
},
94+
child: Icon(
95+
Icons.play_arrow,
96+
color: ColorApp.primaryDarkColor,
97+
size: 32.0,
98+
),
99+
backgroundColor: Colors.white,
100+
),
101+
),
102+
],
103+
);
104+
}
105+
106+
Widget _buildWidgetIconBuyAndShare(MediaQueryData mediaQuery) {
107+
return Padding(
108+
padding: const EdgeInsets.symmetric(horizontal: 16.0),
109+
child: Column(
110+
children: <Widget>[
111+
SizedBox(
112+
height: mediaQuery.size.height / 2 - 40,
113+
),
114+
Stack(
115+
children: <Widget>[
116+
Align(
117+
alignment: Alignment.centerLeft,
118+
child: Icon(Icons.add),
119+
),
120+
Align(
121+
alignment: Alignment.centerRight,
122+
child: Icon(Icons.share),
123+
),
124+
],
125+
),
126+
],
127+
),
128+
);
129+
}
130+
131+
Widget _buildWidgetTitleMovie(BuildContext context) {
132+
return Center(
133+
child: Text(
134+
'Angel Has Fallen',
135+
style: Theme.of(context).textTheme.title,
136+
),
137+
);
138+
}
139+
140+
Widget _buildWidgetGenreMovie(BuildContext context) {
141+
return Center(
142+
child: Text(
143+
'Action',
144+
style: Theme.of(context).textTheme.subtitle.merge(
145+
TextStyle(color: Colors.grey),
146+
),
147+
),
148+
);
149+
}
150+
151+
Widget _buildWidgetRating() {
152+
return Center(
153+
child: RatingBar(
154+
initialRating: 4.0,
155+
itemCount: 5,
156+
allowHalfRating: true,
157+
direction: Axis.horizontal,
158+
itemPadding: EdgeInsets.symmetric(horizontal: 2.0),
159+
itemBuilder: (BuildContext context, int index) {
160+
return Icon(
161+
Icons.star,
162+
color: ColorApp.primaryDarkColor,
163+
);
164+
},
165+
tapOnlyMode: true,
166+
itemSize: 24.0,
167+
unratedColor: Colors.black,
168+
onRatingUpdate: (rating) {
169+
/* Nothing to do in here */
170+
},
171+
),
172+
);
173+
}
174+
175+
Widget _buildWidgetShortDescriptionMovie(BuildContext context) {
176+
return Padding(
177+
padding: const EdgeInsets.symmetric(horizontal: 16.0),
178+
child: Row(
179+
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
180+
children: <Widget>[
181+
RichText(
182+
textAlign: TextAlign.center,
183+
text: TextSpan(
184+
children: [
185+
TextSpan(
186+
text: 'Country\n',
187+
style: Theme.of(context).textTheme.subtitle.merge(
188+
TextStyle(
189+
color: Colors.black54,
190+
),
191+
),
192+
),
193+
TextSpan(
194+
text: 'USA',
195+
style: Theme.of(context).textTheme.subtitle.merge(
196+
TextStyle(
197+
color: Colors.black,
198+
fontWeight: FontWeight.bold,
199+
fontSize: 16.0,
200+
),
201+
),
202+
),
203+
],
204+
),
205+
),
206+
RichText(
207+
textAlign: TextAlign.center,
208+
text: TextSpan(
209+
children: [
210+
TextSpan(
211+
text: 'Year\n',
212+
style: Theme.of(context).textTheme.subtitle.merge(
213+
TextStyle(
214+
color: Colors.black54,
215+
),
216+
),
217+
),
218+
TextSpan(
219+
text: '2018',
220+
style: Theme.of(context).textTheme.subtitle.merge(
221+
TextStyle(
222+
color: Colors.black,
223+
fontWeight: FontWeight.bold,
224+
fontSize: 16.0,
225+
),
226+
),
227+
),
228+
],
229+
),
230+
),
231+
RichText(
232+
textAlign: TextAlign.center,
233+
text: TextSpan(
234+
children: [
235+
TextSpan(
236+
text: 'Lenght\n',
237+
style: Theme.of(context).textTheme.subtitle.merge(
238+
TextStyle(
239+
color: Colors.black54,
240+
),
241+
),
242+
),
243+
TextSpan(
244+
text: '112 min',
245+
style: Theme.of(context).textTheme.subtitle.merge(
246+
TextStyle(
247+
color: Colors.black,
248+
fontWeight: FontWeight.bold,
249+
fontSize: 16.0,
250+
),
251+
),
252+
),
253+
],
254+
),
255+
),
256+
],
257+
),
258+
);
259+
}
260+
261+
Widget _buildWidgetSynopsisMovie(BuildContext context) {
262+
return Padding(
263+
padding: const EdgeInsets.symmetric(horizontal: 16.0),
264+
child: Center(
265+
child: Text(
266+
'Secret Service Agent Mike Banning is framed for the attempted '
267+
'assassination of the President and must evade his own agency '
268+
'and the FBI as he tries to uncover the real threat.',
269+
textAlign: TextAlign.justify,
270+
),
271+
),
272+
);
273+
}
274+
275+
Widget _buildWidgetScreenshots(
276+
MediaQueryData mediaQuery, BuildContext context) {
277+
var listScreenshotsMovie = [
278+
'assets/images/screenshot_1_backdrop_path.jpeg',
279+
'assets/images/screenshot_2_backdrop_path.jpeg',
280+
'assets/images/screenshot_3_backdrop_path.jpeg',
281+
'assets/images/screenshot_4_backdrop_path.jpeg',
282+
'assets/images/screenshot_5_backdrop_path.jpeg',
283+
];
284+
return Column(
285+
children: <Widget>[
286+
Padding(
287+
padding: const EdgeInsets.symmetric(horizontal: 16.0),
288+
child: Row(
289+
crossAxisAlignment: CrossAxisAlignment.center,
290+
children: <Widget>[
291+
Expanded(
292+
child: Text(
293+
'Screenshots',
294+
style: Theme.of(context).textTheme.subhead.merge(
295+
TextStyle(fontWeight: FontWeight.bold),
296+
),
297+
),
298+
),
299+
Icon(Icons.chevron_right),
300+
],
301+
),
302+
),
303+
SizedBox(height: 8.0),
304+
Container(
305+
width: mediaQuery.size.width,
306+
height: 100.0,
307+
child: ListView.builder(
308+
scrollDirection: Axis.horizontal,
309+
itemBuilder: (BuildContext context, int index) {
310+
return Padding(
311+
padding: EdgeInsets.only(
312+
left: 16.0,
313+
right: index == listScreenshotsMovie.length - 1 ? 16.0 : 0.0,
314+
),
315+
child: ClipRRect(
316+
borderRadius: BorderRadius.circular(8.0),
317+
child: Image.asset(
318+
listScreenshotsMovie[index],
319+
fit: BoxFit.cover,
320+
),
321+
),
322+
);
323+
},
324+
itemCount: listScreenshotsMovie.length,
325+
),
326+
),
327+
],
328+
);
329+
}
63330
}
64331

65-
class WavyHeaderImage extends StatelessWidget {
332+
class BackdropImage extends StatelessWidget {
66333
final String backdropPath;
67334

68-
WavyHeaderImage(this.backdropPath);
335+
BackdropImage(this.backdropPath);
69336

70337
@override
71338
Widget build(BuildContext context) {
@@ -74,7 +341,7 @@ class WavyHeaderImage extends StatelessWidget {
74341
child: Image.asset(
75342
backdropPath,
76343
height: mediaQuery.size.height / 2,
77-
width: double.infinity,
344+
width: mediaQuery.size.width,
78345
fit: BoxFit.cover,
79346
),
80347
clipper: BottomWaveClipper(),
@@ -101,6 +368,6 @@ class BottomWaveClipper extends CustomClipper<Path> {
101368

102369
@override
103370
bool shouldReclip(CustomClipper<Path> oldClipper) {
104-
return false;
371+
return true;
105372
}
106373
}

Diff for: pubspec.lock

+8-1
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,13 @@ packages:
160160
description: flutter
161161
source: sdk
162162
version: "0.0.0"
163+
flutter_rating_bar:
164+
dependency: "direct main"
165+
description:
166+
name: flutter_rating_bar
167+
url: "https://pub.dartlang.org"
168+
source: hosted
169+
version: "3.0.0"
163170
flutter_test:
164171
dependency: "direct dev"
165172
description: flutter
@@ -451,4 +458,4 @@ packages:
451458
source: hosted
452459
version: "2.1.16"
453460
sdks:
454-
dart: ">=2.3.0 <3.0.0"
461+
dart: ">=2.5.0 <3.0.0"

Diff for: pubspec.yaml

+4
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ dependencies:
1717
# by annotating Dart classes.
1818
json_serializable: ^3.2.2
1919

20+
# A simple yet fully customizable ratingbar for flutter which also
21+
# include a rating bar indicator, supporting any fraction of rating.
22+
flutter_rating_bar: ^3.0.0
23+
2024
dev_dependencies:
2125
flutter_test:
2226
sdk: flutter

0 commit comments

Comments
 (0)