Skip to content

Instantly share code, notes, and snippets.

@SelvinPL
Created April 13, 2018 10:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SelvinPL/2d3c372d742e3503798de3a43c47a338 to your computer and use it in GitHub Desktop.
Save SelvinPL/2d3c372d742e3503798de3a43c47a338 to your computer and use it in GitHub Desktop.
Popular Movies in Dart/Flutter
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