Created
July 22, 2019 15:08
-
-
Save iamranchojr/0a4d45861af512c1e68ad4a571300298 to your computer and use it in GitHub Desktop.
Dog Flutter App
This file contains hidden or 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 'package:flutter/material.dart'; | |
import 'dog_model.dart'; | |
class DogCard extends StatefulWidget { | |
final Dog dog; | |
DogCard(this.dog); | |
@override | |
_DogCardState createState() => _DogCardState(); | |
} | |
class _DogCardState extends State<DogCard> { | |
// A class property that represents the URL flutter will render | |
// from the Dog class. | |
String renderUrl; | |
// State classes run this method when the state is created. | |
// You shouldn't do async work in initState, so we'll defer it | |
// to another method. | |
void initState() { | |
super.initState(); | |
renderDogPic(); | |
} | |
void renderDogPic() async { | |
// this makes the service call | |
await widget.dog.getImageUrl(); | |
// setState tells Flutter to re render anything that's been changed. | |
// setState cannot be async, so we use a variable that can be overwritten | |
if (mounted) { // Avoid calling `setState` if the widget is no longer in the widget tree. | |
setState(() { | |
renderUrl = widget.dog.imageUrl; | |
}); | |
} | |
} | |
Widget get dogImage { | |
return Container( | |
// You can explicitly set heights and widths on Containers. | |
// Otherwise they take up as much space as their children. | |
width: 100.0, | |
height: 100.0, | |
margin: EdgeInsets.only(left: 20.0), | |
// Decoration is a property that lets you style the container. | |
// It expects a BoxDecoration. | |
decoration: BoxDecoration( | |
// BoxDecorations have many possible properties. | |
// Using BoxShape with a background image is the | |
// easiest way to make a circle cropped avatar style image. | |
shape: BoxShape.circle, | |
color: Colors.white, | |
image: DecorationImage( | |
fit: BoxFit.cover, | |
// A NetworkImage widget is a widget that | |
// takes a URL to an image. | |
// ImageProviders (such as NetworkImage) are ideal | |
// when your image needs to be loaded or can change. | |
// Use the null check to avoid an error. | |
image: NetworkImage(renderUrl ?? ''), | |
), | |
), | |
); | |
} | |
Widget get dogCard { | |
// A new container | |
// The height and width are arbitrary numbers for styling. | |
return Container( | |
width: 320.0, | |
height: 115.0, | |
child: Card( | |
color: Colors.black87, | |
// Wrap children in a Padding widget in order to give padding. | |
child: Padding( | |
// The class that controls padding is called 'EdgeInsets' | |
// The EdgeInsets.only constructor is used to set | |
// padding explicitly to each side of the child. | |
padding: const EdgeInsets.only( | |
top: 8.0, | |
bottom: 8.0, | |
left: 64.0, | |
right: 8.0 | |
), | |
// Column is another layout widget -- like stack -- that | |
// takes a list of widgets as children, and lays the | |
// widgets out from top to bottom. | |
child: Column( | |
crossAxisAlignment: CrossAxisAlignment.start, | |
mainAxisAlignment: MainAxisAlignment.spaceAround, | |
children: <Widget>[ | |
Text(widget.dog.name, | |
// Themes are set in the MaterialApp widget at the root of your app. | |
// They have default values -- which we're using because we didn't set our own. | |
// They're great for having consistent, app-wide styling that's easily changed. | |
style: Theme.of(context).textTheme.headline,), | |
Text(widget.dog.location, style: Theme.of(context).textTheme.subhead), | |
Row( | |
children: <Widget>[ | |
Icon( | |
Icons.star, | |
), | |
Text(' ${widget.dog.rating} / 10') | |
], | |
) | |
], | |
), | |
), | |
), | |
); | |
} | |
@override | |
Widget build(BuildContext context) { | |
// Start with a container so we can add layout and style props: | |
return Container( | |
// Arbitrary number that I decided looked good: | |
height: 115.0, | |
child: Stack( | |
// A stack takes children, with a list of widgets. | |
children: <Widget>[ | |
// position our dog image | |
Positioned( | |
left: 70.0, | |
child: dogCard, | |
), | |
Positioned(top: 7.5, child: dogImage), | |
], | |
), | |
); | |
} | |
} |
This file contains hidden or 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 'package:flutter/material.dart'; | |
import 'dog_card.dart'; | |
import 'dog_model.dart'; | |
class DogList extends StatelessWidget { | |
final List<Dog> dogs; | |
DogList(this.dogs); | |
// Builder methods rely on a set of data, such as a list. | |
@override | |
Widget build(BuildContext context) { | |
return _buildList(context); | |
} | |
// A builder method almost always returns a ListView. | |
// A ListView is a widget similar to Column or Row. | |
// It knows whether it needs to be scrollable or not. | |
// It has a constructor called builder, which it knows will | |
// work with a List. | |
ListView _buildList(context) { | |
return ListView.builder( | |
// Must have an item count equal to the number of items! | |
itemCount: dogs.length, | |
// A callback that will return a widget. | |
itemBuilder: (context, index) { | |
// In our case, a DogCard for each dog. | |
return DogCard(dogs[index]); | |
}, | |
); | |
} | |
} |
This file contains hidden or 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'; | |
// Dog model class | |
class Dog { | |
final String name; | |
final String location; | |
final String description; | |
String imageUrl; | |
// All dogs start out at 10, because they're good dogs. | |
int rating = 10; | |
// constructor | |
Dog({this.name, this.location, this.description}); | |
Future getImageUrl() async { | |
// Null check so our app isn't doing extra work. | |
// If there's already an image, we don't need to get one. | |
if (imageUrl != null) return; | |
// This is how http calls are done in flutter: | |
HttpClient http = HttpClient(); // this class is found inside the dart:io package | |
try { | |
// Use darts Uri builder | |
var uri = Uri.http('dog.ceo', '/api/breeds/image/random'); | |
var request = await http.getUrl(uri); | |
var response = await request.close(); | |
var responseBody = await response.transform(utf8.decoder).join(); | |
// The dog.ceo API returns a JSON object with a property | |
// called 'message', which actually is the URL. | |
// here, we decode it using json and store it inside our imageUrl variable | |
imageUrl = json.decode(responseBody)['message']; | |
} catch (ex) { | |
print(ex); | |
} | |
} | |
} |
This file contains hidden or 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 'package:flutter/material.dart'; | |
import 'dog_list.dart'; | |
import 'dog_model.dart'; | |
void main() => runApp(MyApp()); | |
class MyApp extends StatelessWidget { | |
/// MaterialApp is the base Widget for your Flutter Application | |
/// Gives us access to routing, context, and meta info functionality. | |
@override | |
Widget build(BuildContext context) { | |
return MaterialApp( | |
title: 'Flutter Demo', | |
// Make all our text default to white | |
// and backgrounds default to dark | |
theme: ThemeData(brightness: Brightness.dark), | |
home: MyHomePage(title: 'We Rate Dogs'), | |
); | |
} | |
} | |
class MyHomePage extends StatefulWidget { | |
final String title; | |
MyHomePage({Key key, this.title}) : super(key: key); | |
@override | |
State<StatefulWidget> createState() => _MyHomePageState(); | |
} | |
class _MyHomePageState extends State<MyHomePage> { | |
/// let's create a handful of dogs so we have something to work with. | |
List<Dog> initialDogs = [ | |
Dog( | |
name: 'Ruby', | |
location: 'Accra, Ghana', | |
description: 'Ruby is a very good girl. Yes: Fetch, loungin\'. No: Dogs who get on furniture.' | |
), | |
Dog( | |
name: 'Rex', | |
location: 'Kumasi, Ghana', | |
description: 'Best in Show 1999' | |
), | |
Dog( | |
name: 'Rod Stewart', | |
location: 'Takoradi, Ghana', | |
description: 'Star good boy on international snooze team.' | |
), | |
Dog( | |
name: 'Herbert', | |
location: 'Cape Coast, Ghana', | |
description: 'A Very Good Boy' | |
), | |
Dog( | |
name: 'Buddy', | |
location: 'Tema, Ghana', | |
description: 'Self proclaimed human lover.' | |
), | |
Dog( | |
name: 'Sunny', | |
location: 'Ho, Ghana', | |
description: 'Very big' | |
) | |
]; | |
@override | |
Widget build(BuildContext context) { | |
/// Scaffold is the base for a page. | |
/// It gives an AppBar for the top, | |
/// Space for the main body, bottom navigation, and more. | |
return Scaffold( | |
/// App bar has a ton of functionality, but for now lets | |
/// just give it a color and a title. | |
appBar: AppBar( | |
/// Access this widgets properties with 'widget' | |
title: Text(widget.title), | |
backgroundColor: Colors.black87, | |
), | |
/// Container is a convenience widget that lets us style it's | |
/// children. It doesn't take up any space itself, so it | |
/// can be used as a placeholder in your code. | |
body: Container( | |
// Add box decoration | |
decoration: BoxDecoration( | |
// Box decoration takes a gradient | |
gradient: LinearGradient( | |
begin: Alignment.topRight, | |
end: Alignment.bottomLeft, | |
// Add one stop for each color. Stops should increase from 0 to 1 | |
stops: [0.1, 0.5, 0.7, 0.9], | |
colors: [ | |
// Colors are easy thanks to Flutter's Colors class | |
Colors.indigo[800], | |
Colors.indigo[700], | |
Colors.indigo[600], | |
Colors.indigo[400], | |
] | |
) | |
), | |
child: DogList(initialDogs), | |
), | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment