Created
April 13, 2018 10:45
-
-
Save SelvinPL/2d3c372d742e3503798de3a43c47a338 to your computer and use it in GitHub Desktop.
Popular Movies in Dart/Flutter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'dart:convert'; | |
import 'dart:io'; | |
import 'package:flutter/material.dart'; | |
void main() { | |
runApp(new MyApp()); | |
} | |
class MyTheme { | |
static var _primaryColor = new Color(0xff3a3a3a); | |
static var _accentColor = new Color(0xff78909c); | |
static ThemeData light = new ThemeData( | |
primaryColor: _primaryColor, | |
accentColor: _accentColor, | |
); | |
static ThemeData dark = new ThemeData( | |
primaryColor: _primaryColor, | |
accentColor: _accentColor, | |
brightness: Brightness.dark, | |
); | |
} | |
class MyApp extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return new MaterialApp( | |
title: 'Flutter Demo', | |
theme: MyTheme.light, | |
home: new MyHomePage(), | |
); | |
} | |
} | |
class MyHomePage extends StatefulWidget { | |
MyHomePage({Key key}) : super(key: key); | |
@override | |
_MyHomePageState createState() => new _MyHomePageState(); | |
} | |
class _MyHomePageState extends State<MyHomePage> { | |
static final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey< | |
ScaffoldState>(); | |
_MyHomePageState() { | |
_selectItem(0); | |
} | |
static const String API_KEY = ;//add the 'THE_KEY' here | |
int _currentItem = 1; | |
List<dynamic> _response; | |
var _httpClient = new HttpClient(); | |
@override | |
Widget build(BuildContext context) { | |
var isLandscape = MediaQuery | |
.of(context) | |
.orientation == Orientation.landscape; | |
return new Scaffold( | |
key: _scaffoldKey, | |
body: new CustomScrollView( | |
slivers: <Widget>[ | |
new SliverAppBar( | |
title: new Text('Movies'), | |
floating: true, | |
snap: true | |
), | |
new SliverGrid.count(crossAxisCount: isLandscape ? 4 : 2, | |
childAspectRatio: 2.0 / 2.8, | |
children: _response == null ? [] : _response.map(( | |
dynamic item) { | |
return new GridTile( | |
child: new Stack(children: <Widget>[ | |
new Positioned.fill( | |
child: new MyImage(imageProvider: new NetworkImage( | |
'http://image.tmdb.org/t/p/w342/' + | |
item['poster_path']))), | |
new Positioned( | |
left: 0.0, | |
bottom: 0.0, | |
right: 0.0, child: | |
new Container( | |
child: new Padding( | |
padding: const EdgeInsets.all(8.0), | |
child: new Text( | |
item["title"], | |
style: MyTheme.dark.textTheme.subhead, | |
maxLines: 1, | |
overflow: TextOverflow.ellipsis,), | |
), | |
decoration: new BoxDecoration ( | |
color: Colors.black45 | |
))), | |
new Positioned.fill(child: new Material( | |
color: Colors.transparent, | |
child: new InkWell(onTap: _tap))), | |
]), | |
); | |
}).toList()), | |
]), | |
bottomNavigationBar: new Theme( | |
data: MyTheme.dark, | |
child: new BottomNavigationBar( | |
items: [ | |
new BottomNavigationBarItem( | |
icon: new Icon(Icons.whatshot), | |
title: new Text('Popular')), | |
new BottomNavigationBarItem( | |
icon: new Icon(Icons.star), | |
title: new Text('Top rated') | |
), | |
new BottomNavigationBarItem( | |
icon: new Icon(Icons.favorite), | |
title: new Text('Favourite') | |
) | |
], | |
onTap: _selectItem, | |
currentIndex: _currentItem, | |
), | |
), /**/ | |
); | |
} | |
void _selectItem(int value) async { | |
if (_currentItem != value) { | |
dynamic result; | |
setState(() { | |
_currentItem = value; | |
_response = null; | |
}); | |
if (value != 2) { | |
var type = value == 0 ? 'popular' : 'top_rated'; | |
var url = 'http://api.themoviedb.org/3/movie/$type?api_key=' + API_KEY; | |
var request = await _httpClient.getUrl(Uri.parse(url)); | |
var response = await request.close(); | |
if (response.statusCode == HttpStatus.OK) { | |
var jsonString = await response.transform(utf8.decoder).join(); | |
var data = json.decode(jsonString); | |
result = data['results']; | |
} | |
} else | |
result = []; | |
setState(() { | |
_response = result; | |
}); | |
} | |
} | |
void _tap() async { | |
var t = await showDialog<bool>( | |
context: context, | |
builder: (BuildContext context) { | |
return new AlertDialog( | |
content: new Text( | |
'Discard new event?' | |
), | |
actions: <Widget>[ | |
new FlatButton( | |
child: const Text('CANCEL'), | |
onPressed: () { | |
Navigator.of(context).pop( | |
false); // Pops the confirmation dialog but not the page. | |
} | |
), | |
new FlatButton( | |
child: const Text('DISCARD'), | |
onPressed: () { | |
Navigator.of(context).pop( | |
true); // Returning true to _onWillPop will pop again. | |
} | |
) | |
], | |
); | |
}, | |
) ?? false; | |
} | |
} | |
class MyImage extends StatefulWidget { | |
const MyImage({ | |
Key key, | |
this.imageProvider, | |
}) | |
: assert(imageProvider != null), | |
super(key: key); | |
final ImageProvider imageProvider; | |
@override | |
_MyImageState createState() => new _MyImageState(); | |
} | |
class _MyImageState extends State<MyImage> { | |
ImageStream _imageStream; | |
ImageInfo _imageInfo; | |
@override | |
void didChangeDependencies() { | |
super.didChangeDependencies(); | |
// We call _getImage here because createLocalImageConfiguration() needs to | |
// be called again if the dependencies changed, in case the changes relate | |
// to the DefaultAssetBundle, MediaQuery, etc, which that method uses. | |
_getImage(); | |
} | |
@override | |
void didUpdateWidget(MyImage oldWidget) { | |
super.didUpdateWidget(oldWidget); | |
if (widget.imageProvider != oldWidget.imageProvider) | |
_getImage(); | |
} | |
void _getImage() { | |
final ImageStream oldImageStream = _imageStream; | |
_imageStream = | |
widget.imageProvider.resolve(createLocalImageConfiguration(context)); | |
if (_imageStream.key != oldImageStream?.key) { | |
// If the keys are the same, then we got the same image back, and so we don't | |
// need to update the listeners. If the key changed, though, we must make sure | |
// to switch our listeners to the new image stream. | |
oldImageStream?.removeListener(_updateImage); | |
_imageStream.addListener(_updateImage); | |
} | |
} | |
void _updateImage(ImageInfo imageInfo, bool synchronousCall) { | |
setState(() { | |
// Trigger a build whenever the image changes. | |
_imageInfo = imageInfo; | |
}); | |
} | |
@override | |
void dispose() { | |
_imageStream.removeListener(_updateImage); | |
super.dispose(); | |
} | |
@override | |
Widget build(BuildContext context) { | |
return _imageInfo == null || _imageInfo?.image == null ? new Center( | |
child: new CircularProgressIndicator()) : | |
new RawImage( | |
image: _imageInfo?.image, // this is a dart:ui Image object | |
scale: _imageInfo?.scale ?? 1.0, fit: BoxFit.fitWidth, | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment