Last active
March 31, 2024 06:02
-
-
Save Andrious/7ac920dc3077d080dc6ba36d9e66cbe3 to your computer and use it in GitHub Desktop.
Write Your First App example using both the Marterial design or the Cupertino design.
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:io' show Platform; | |
import 'package:flutter/foundation.dart' show kIsWeb; | |
import 'package:english_words/english_words.dart'; | |
import 'package:flutter/material.dart'; | |
import 'package:flutter/cupertino.dart'; | |
void main() => runApp(MyApp( | |
switchUI: true, | |
)); | |
class MyApp extends StatelessWidget { | |
MyApp({ | |
this.key, | |
this.android = false, | |
this.iOS = false, | |
this.switchUI = false, | |
}) { | |
_useMaterial = android; | |
_useCupertino = iOS; | |
_switchUI = switchUI; | |
} | |
final Key key; | |
final bool android; | |
final bool iOS; | |
final bool switchUI; | |
static bool _useMaterial; | |
static bool _useCupertino; | |
static bool _switchUI; | |
@override | |
Widget build(BuildContext context) { | |
String title = 'Startup Name Generator'; | |
Widget home = RandomWords(key: key); | |
if (useCupertino) { | |
return CupertinoApp( | |
title: title, | |
home: home, | |
); | |
} else { | |
return MaterialApp( | |
title: title, | |
home: home, | |
); | |
} | |
} | |
// Use Material UI when explicitly specified or even when running in iOS | |
static bool get useMaterial => | |
(_useMaterial && !_useCupertino) || | |
(Platform.isAndroid && !_switchUI && !_useCupertino) || | |
(Platform.isIOS && _switchUI) || | |
(kIsWeb && !_switchUI); | |
// Use Cupertino UI when explicitly specified or even when running in Android | |
static bool get useCupertino => | |
(_useCupertino && !_useMaterial) || | |
(Platform.isIOS && !_switchUI && !_useMaterial) || | |
(Platform.isAndroid && _switchUI) || | |
(kIsWeb && _switchUI); | |
} | |
class RandomWords extends StatefulWidget { | |
RandomWords({ | |
Key key, | |
this.useMaterial = false, | |
this.useCupertino = false, | |
this.switchUI = false, | |
}) : super(key: key); | |
final bool useMaterial; | |
final bool useCupertino; | |
final bool switchUI; | |
@override | |
State createState() => | |
MyApp.useMaterial ? RandomWordsAndroid() : RandomWordsApple(); | |
} | |
class RandomWordsAndroid extends State<RandomWords> { | |
RandomWordsAndroid() { | |
wordPair = _WordPair(this); | |
} | |
_WordPair wordPair; | |
final _biggerFont = const TextStyle(fontSize: 18.0); | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
appBar: AppBar( | |
title: Text('Startup Name Generator'), | |
), | |
body: ListView.builder( | |
padding: const EdgeInsets.all(16.0), | |
itemBuilder: (context, i) { | |
if (i.isOdd) return Divider(); | |
wordPair.build(i); | |
return ListTile( | |
title: Text( | |
wordPair.current.asPascalCase, | |
style: _biggerFont, | |
), | |
trailing: wordPair.icon, | |
onTap: () { | |
wordPair.onTap(i); | |
}, | |
); | |
}), | |
); | |
} | |
} | |
class RandomWordsApple extends State<RandomWords> { | |
RandomWordsApple() { | |
wordPair = _WordPair(this); | |
} | |
_WordPair wordPair; | |
@override | |
Widget build(BuildContext context) { | |
return CupertinoPageScaffold( | |
child: CustomScrollView( | |
slivers: <Widget>[ | |
const CupertinoSliverNavigationBar( | |
largeTitle: Text('Startup Name Generator'), | |
), | |
SliverSafeArea( | |
top: false, | |
minimum: const EdgeInsets.only(top: 8), | |
sliver: SliverList( | |
delegate: SliverChildBuilderDelegate( | |
(context, i) { | |
if (i.isOdd) return Divider(); | |
wordPair.build(i); | |
return CupertinoListTile( | |
title: wordPair.current.asPascalCase, | |
trailing: wordPair.icon, | |
onTap: () { | |
wordPair.onTap(i); | |
}, | |
); | |
}, | |
), | |
), | |
) | |
], | |
), | |
); | |
} | |
} | |
class _WordPair { | |
_WordPair(this.state); | |
final State state; | |
final suggestions = <WordPair>[]; | |
final Set<WordPair> saved = <WordPair>{}; | |
int index; | |
void build(int i) { | |
index = i ~/ 2; | |
if (index >= suggestions.length) { | |
suggestions.addAll(generateWordPairs().take(10)); | |
} | |
} | |
WordPair get current => suggestions[index]; | |
Icon get icon { | |
bool alreadySaved = saved.contains(suggestions[index]); | |
return Icon( | |
alreadySaved ? Icons.favorite : Icons.favorite_border, | |
color: alreadySaved ? Colors.red : null, | |
); | |
} | |
void onTap(int i) => state.setState(() { | |
int index = i ~/ 2; | |
WordPair pair = suggestions[index]; | |
if (pair == null) return; | |
if (saved.contains(suggestions[index])) { | |
saved.remove(pair); | |
} else { | |
saved.add(pair); | |
} | |
}); | |
} | |
/// Cupertino needs a ListTile equivalent | |
/// https://github.com/flutter/flutter/issues/50668#issuecomment-593060684 | |
class CupertinoListTile extends StatefulWidget { | |
const CupertinoListTile({ | |
Key key, | |
this.leading, | |
this.title, | |
this.subtitle, | |
this.trailing, | |
this.onTap, | |
}) : super(key: key); | |
final Widget leading; | |
final String title; | |
final String subtitle; | |
final Widget trailing; | |
final Function onTap; | |
@override | |
_StatefulStateCupertino createState() => _StatefulStateCupertino(); | |
} | |
class _StatefulStateCupertino extends State<CupertinoListTile> { | |
@override | |
Widget build(BuildContext context) { | |
Widget leading; | |
if (widget.leading == null) { | |
leading = const SizedBox(); | |
} else { | |
leading = widget.leading; | |
} | |
Widget trailing; | |
if (widget.trailing == null) { | |
trailing = const SizedBox(); | |
} else { | |
trailing = widget.trailing; | |
} | |
return GestureDetector( | |
onTap: () { | |
if (widget.onTap != null) widget.onTap(); | |
}, | |
child: Row( | |
mainAxisAlignment: MainAxisAlignment.spaceBetween, | |
children: <Widget>[ | |
Row( | |
children: <Widget>[ | |
leading, | |
SizedBox(width: 10), | |
Column( | |
crossAxisAlignment: CrossAxisAlignment.start, | |
children: columnChildren(context), | |
), | |
], | |
), | |
trailing, | |
], | |
), | |
); | |
} | |
List<Widget> columnChildren(BuildContext context) { | |
List<Widget> children = List(); | |
bool isDark = MediaQuery.of(context).platformBrightness == Brightness.dark; | |
Widget title = widget.title != null | |
? Text( | |
widget.title, | |
style: TextStyle( | |
fontSize: 25.0, color: isDark ? Colors.white : Colors.black), | |
) | |
: const SizedBox(); | |
children.add(title); | |
if (widget.subtitle != null) | |
children.add(Text(widget.subtitle, | |
style: TextStyle(color: CupertinoColors.systemGrey))); | |
return children; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment