Skip to content

Instantly share code, notes, and snippets.

@iamranchojr
Created July 22, 2019 15:08
Show Gist options
  • Save iamranchojr/0a4d45861af512c1e68ad4a571300298 to your computer and use it in GitHub Desktop.
Save iamranchojr/0a4d45861af512c1e68ad4a571300298 to your computer and use it in GitHub Desktop.
Dog Flutter App
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),
],
),
);
}
}
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]);
},
);
}
}
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);
}
}
}
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