use flutter whats new package - dart

i am trying to use the whats new package in my flutter application but I change th version and nothing happens, i implemmented it in the initstate of the class like this .Is it right??:
void initState() {
super.initState();
WhatsNewPage(
title: Text(
"What's New",
textScaleFactor: 1.0,
textAlign: TextAlign.center,
style: TextStyle(
// Text Style Needed to Look like iOS 11
fontSize: 22.0,
fontWeight: FontWeight.bold,
),
),
buttonText: Text(
'Continue',
textScaleFactor: 1.0,
style: TextStyle(
color: Colors.white,
),
),
items: <ListTile>[
ListTile(
leading: Icon(Icons.color_lens),
title: Text(
'Dark Theme',
textScaleFactor: 1.0,
), //Title is the only Required Item
subtitle: Text(
'Black and grey theme (Tap to Change)',
textScaleFactor: 1.0,
),
onTap: () {
// You Can Navigate to Locations in the App
Navigator.of(context).pop();
},
),
], //Required
home: HomePage(),
showNow: false,
showOnVersionChange: true,
);}

Ok, it seems like the documentation is not clear, you can use that widget inside your build method, like my example below, replace NewPage() widget by the widget you want use after user press 'continue'
class TestingPackage extends StatefulWidget {
#override
TestingPackageState createState() => TestingPackageState();
}
class TestingPackageState extends State<TestingPackage> {
double textScaleFactor = 1.0;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: WhatsNewPage(
title: Text(
"What's New",
textScaleFactor: textScaleFactor,
textAlign: TextAlign.center,
style: TextStyle(
// Text Style Needed to Look like iOS 11
fontSize: 22.0,
fontWeight: FontWeight.bold,
),
),
buttonText: Text(
'Continue',
textScaleFactor: textScaleFactor,
style: TextStyle(
color: Colors.white,
),
),
// Create a List of WhatsNewItem for use in the Whats New Page
// Create as many as you need, it will be scrollable
items: <ListTile>[
ListTile(
leading: Icon(Icons.color_lens),
title: Text(
'Dark Theme',
textScaleFactor: textScaleFactor,
), //Title is the only Required Item
subtitle: Text(
'Black and grey theme (Tap to Change)',
textScaleFactor: textScaleFactor,
),
onTap: () {
// You Can Navigate to Locations in the App
Navigator.of(context).pushNamed("/settings");
},
),
ListTile(
leading: Icon(Icons.map),
title: Text(
'Google Maps',
textScaleFactor: textScaleFactor,
),
subtitle: Text(
'Open Address Links in Google Maps instead of Apple Maps (Tap to Change)',
textScaleFactor: textScaleFactor,
),
onTap: () {
// You Can Navigate to Locations in the App
Navigator.of(context).pushNamed("/settings");
},
),
ListTile(
leading: Icon(Icons.person_outline),
title: Text(
'Loan Contacts Enhancements',
textScaleFactor: textScaleFactor,
),
subtitle: Text(
'Updated look for faster navigation',
textScaleFactor: textScaleFactor,
),
onTap: () {
WhatsNewPage.showDetailPopUp(
context,
'Info',
"Navigate to any loan then select the bottom right icon to go to the contacts. You can press the dropdown arrow for contact information.",
);
},
),
], //Required
home:
NewPage(), // Where the Button will Navigate (Usually the Login or Home Screen)
showNow:
false, // Show now regarless of version change (Useful for showing from the main menu)
showOnVersionChange:
true, //Show only if the version changes or the user reinstalls the app
),
);
}
}
class NewPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Container(
child: Text("new page"),
),
);
}
}

Related

Listview scrolling incorrectly only on IOS emulator

The following code works fine where the scrolling of the list view scrolls properly without running over into other widgets
when tested on Andoird emulator (on Windows).
But when tested on IOS emulator (on a MAC), the list over scrolls to the top and runs over the widgets on top of it.
Is there anything speific that needs to be done when it comes to IOS to address this?
Please see following video which I recorded to show the issue in scrolling.
https://imgur.com/a/1SbsNBL
I've added the whole block of code below in the event other widgets are causing this.
App bar code is held in another file but it is not affected by this issue anyway.
The listview widget is at the end of following code block within the Expanded widget. Thanks.
import 'dart:io';
import 'package:amex/dialog.dart';
import 'package:flutter/material.dart';
import 'account_details.dart';
import 'app_bar.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
int navIndex = 0;
selectTab(int index) {
setState(() {
navIndex = index;
});
}
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
backgroundColor: Color(0xff020B2A),
bottomNavigationBar: BottomNavigationBar(
onTap: selectTab,
backgroundColor: Color(0xff2A2E3B),
selectedItemColor: Color(0xff2F6DC8),
unselectedItemColor: Color(0xff868993),
currentIndex: navIndex,
type: BottomNavigationBarType.fixed,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
),
BottomNavigationBarItem(
icon: Icon(Icons.money),
label: 'Statements',
),
BottomNavigationBarItem(
icon: Icon(Icons.star),
label: 'Membership',
),
BottomNavigationBarItem(
icon: Icon(Icons.account_balance),
label: 'Account',
),
],
),
appBar: getAppBar(),
body: Column(
children: [
Center(
child: Column(
children: [
SizedBox(height: 30),
Text(
'Good Evening',
style: TextStyle(
color: Colors.white,
fontSize: 12,
),
),
SizedBox(height: 18),
Text(
'NAME',
style: TextStyle(
color: Colors.white,
fontSize: 28,
),
),
SizedBox(height: 18),
Text(
'Member Since \'18\'',
style: TextStyle(
color: Colors.white70,
fontSize: 10,
),
),
],
),
),
SizedBox(height: 30),
Align(
alignment: Alignment.centerLeft,
child: Padding(
padding: const EdgeInsets.only(left: 16.0, bottom: 16.0),
child: Text(
'Account',
style: TextStyle(
color: Colors.white70,
fontSize: 16,
),
),
),
),
Expanded(
child: ListView.builder(
itemCount: accountTitles.length,
itemBuilder: (context, index) {
String title = accountTitles[index].title;
return Container(
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
width: 0.5,
color: Color(0xff868993),
),
),
),
child: ListTile(
tileColor: Color(0xff1B223E),
onTap: () => Platform.isIOS
? showDialogForIOS(context, title)
: showDialogForAndroid(context, title),
leading: Icon(
accountTitles[index].leadingIcon,
color: Colors.white,
),
title: Text(
accountTitles[index].title,
style: TextStyle(color: Colors.white),
),
trailing: Icon(accountTitles[index].trailingIcon,
color: Colors.white),
),
);
},
),
),
],
),
),
);
}
}

I need to close my application when double tap /clicked the onBack button in flutter [duplicate]

This question already has answers here:
How to write a double back button pressed to exit app using flutter
(14 answers)
Closed 3 years ago.
I'm new to flutter, and I saw many android apps can exit when double press back button.
The first time press back button, app shows a toast"press again to exit app". The following second press, app exits. Of course, the time between two press must be not long.
I used this code but its not working.Help me out from this.
Future<bool> _onWillPop() {
return showDialog(
context: ctx,
builder: (ctx) => new AlertDialog(
title: new Text('Confirm Exit?',
style: new TextStyle(color: Colors.black, fontSize: 20.0)),
content: new Text(
'Are you sure you want to exit the app? Tap \'Yes\' to exit \'No\' to cancel.'),
actions: <Widget>[
new FlatButton(
onPressed: () {
// this line exits the app.
SystemChannels.platform
.invokeMethod('SystemNavigator.pop');
},
child:
new Text('Yes', style: new TextStyle(fontSize: 18.0)),
),
new FlatButton(
onPressed: () => Navigator.pop(ctx), // this line dismisses the dialog
child: new Text('No', style: new TextStyle(fontSize: 18.0)),
)
],
),
) ??
true;
}
This is an example code: it is using - "fluttertoast" for showing a toast.
DateTime currentBackPressTime = DateTime.now();
Future<bool> onWillPop() {
DateTime now = DateTime.now();
if (now.difference(currentBackPressTime) > Duration(seconds: 2)) {
currentBackPressTime = now;
Fluttertoast.showToast(msg: 'Tap Again to Exit'); // you can use snackbar too here
return Future.value(false);
}
return Future.value(true);
}
Its work perfectly.
Future<bool> _onWillPop() {
return showDialog(
barrierDismissible: false,
context: ctx,
builder: (context) => new AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12.0)),
content: new Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Icon(
Icons.exit_to_app,
color: MyColor.PrimaryColor,
size: 25.0,
),
SizedBox(width: 8.0),
Expanded(
child: Text(
"Do you want to exit this App",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 17.0,
color: Colors.black),
),
),
],
),
actions: <Widget>[
new FlatButton(
onPressed: ()
{
Navigator.of(context).pop(false); },
child: new Text('No',style: TextStyle(color: MyColor.PrimaryColor,fontSize: 17.0)),
),
new FlatButton(
onPressed: () {
Navigator.pop(context,true);
Navigator.of(context).pop(true);},
child: new Text('Yes',style: TextStyle(color:MyColor.PrimaryColor,fontSize: 17.0)),
),
],
),
) ?? false;
}

How to make reusable AlertDialog?

Flutter example for AlertDialog is:
Future<void> neverSatisfied() async {
return showDialog<void>(
context: context,
barrierDismissible: false, // user must tap button!
builder: (BuildContext context) {
return AlertDialog(
title: Text('Rewind and remember'),
content: SingleChildScrollView(
child: ListBody(
children: <Widget>[
Text('You will never be satisfied.'),
Text('You\’re like me. I’m never satisfied.'),
],
),
),
actions: <Widget>[
FlatButton(
child: Text('Regret'),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
}
But I want make this reusable so I can call it and pass in custom text for example:
await neverSatisfied(context, text: text);
How can do?
Thanks!
You can create an alert dialog in separate class like below and can use that any where you want:
Note: pass context with "GlobalKey()" like used in
below class otherwise alert dialog will not display and give you error
such as "The specific widget that could not find a
MaterialLocalizations ancestor was"
Declare separate Utility class that will help to display dialog:
Utility
import 'package:flutter/material.dart';
class Utility{
static Utility utility = null;
static Utility getInstance(){
if(utility == null){
utility = Utility();
}
return utility;
}
showAlertDialog(BuildContext context, String alertTitle, String alertMessage){
// set up the buttons
Widget cancelButton = FlatButton(
child: Text("Cancel"),
onPressed: () {
Navigator.pop(context);
},
);
Widget continueButton = FlatButton(
child: Text("Continue"),
onPressed: () {
Navigator.pop(context);
},
);
// set up the AlertDialog
AlertDialog alert = AlertDialog(
title: Text(alertTitle),
content: SingleChildScrollView(
child: ListBody(
children: <Widget>[
Text(alertMessage)
],
),
),
actions: [
cancelButton,
continueButton,
],
);
// show the dialog
showDialog(
context: context,
builder: (BuildContext context) {
return alert;
},
);
}
}
Use that dialog in main.dart as below:
Main.dart
import 'package:flutter/material.dart';
import 'package:flutter_demo_app/Utility.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
final navigatorKey = GlobalKey<NavigatorState>();
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
navigatorKey: navigatorKey,
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
appBar: AppBar(title: Text('AlertDialog')),
body: Column(
children: <Widget>[
RaisedButton(
child: Text('Get AlertDialog 1'),
onPressed: () {
Utility.getInstance().showAlertDialog(navigatorKey.currentState.overlay.context, 'Rewind and remember', 'You will never be satisfied.');
},
),
RaisedButton(
child: Text('Get AlertDialog 2'),
onPressed: () {
Utility.getInstance().showAlertDialog(navigatorKey.currentState.overlay.context, 'RememberRewinded', 'You\’re like me. I’m never satisfied.');
},
)
],
),
),
);
}
}
to refer alertTitle and alertMessage, add { } in showAlertDialog fields
example:
Utility
showAlertDialog(
{BuildContext context, String alertTitle, String alertMessage}).....
and call:
Main.dart
AlertWidget.getInstance().showAlertDialog(context: context, alertTitle: 'alert', alertMessage: "message",
);
This is how I created a reusable custom dialog...I made a new dart file and made a stateless widget called CustomAlert which takes an onPress and a message as parameter.
import 'dart:ui';
import 'package:flutter/material.dart';
class CustomAlert extends StatelessWidget {
final String? message;
final onPress;
CustomAlert({this.message, this.onPress});
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async => false,
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0),
child: Padding(
padding: const EdgeInsets.only(top: 48.0),
child: AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(20.0))),
contentPadding: EdgeInsets.only(left: 40, right: 40, top: 20),
actionsPadding: EdgeInsets.only(top: 15, bottom: 30),
actionsAlignment: MainAxisAlignment.center,
actions: [
ElevatedButton(
child: Text(
"RETRY",
style: TextStyle(
fontSize: 12,
letterSpacing: 7,
wordSpacing: 5,
color: Colors.black,
fontWeight: FontWeight.bold),
),
style: ButtonStyle(
elevation: MaterialStateProperty.all(4),
padding: MaterialStateProperty.all(EdgeInsets.only(
right: 30, left: 30, top: 10, bottom: 10)),
backgroundColor: MaterialStateProperty.all(Colors.white),
textStyle: MaterialStateProperty.all(
const TextStyle(
fontSize: 10,
fontWeight: FontWeight.bold,
color: Colors.white),
),
),
onPressed: onPress),
],
content: Text(message!,
style: TextStyle(
fontWeight: FontWeight.w500,
fontSize: 16,
color: Colors.black)),
),
),
),
);
}
}
After this, I just called it on another file using showDialog.
showDialog(
context: this.context,
builder: (ctx) => CustomAlert(
message:
"Hello there",
onPress: () {
Navigator.pop(this.context);
},
));

Making a Text Widget visible after button click

I have a basic login page that consists of an 'email', 'password' and a 'SwitchListTile' (Switch) that users will select to confirm reading of legal documents. On 'Login', I would like the 'Text' to show. Default is invisible.
I implemented the visibility of the Text using the 'Visibility' class. Now I would like to make it visible using an 'if-else' check.
SwitchListTile(
value: _acceptTerms,
onChanged: (bool value) {
setState(() {
_acceptTerms = value;
});
},
title: Text('Accept T&Cs'),
),
SizedBox(height: 5.0),
Visibility(
visible: false,
child: Text(
'Please accept Terms & Conditions!',
style: TextStyle(color: Colors.red),
)),
SizedBox(
height: 10.0,
),
RaisedButton(
color: Theme.of(context).primaryColor,
textColor: Colors.white,
child: Text('LOGIN'),
onPressed: () {
print(_emailValue);
print(_passwordValue);
if(_acceptTerms) {
Navigator.pushReplacementNamed(context, '/products');
} else {
//code to make invisible text visible
}
},
),
I'm still new to Flutter and Dart development. Thanks.
The only way to do this in flutter is to create a variable
var tcVisibility = false
set the visibility of the text box to the variable
Visibility(
visible: tcVisibility,
child: Text(
'Please accept Terms & Conditions!',
style: TextStyle(color: Colors.red),
)),
then in the code update the variable
if(_acceptTerms) {
Navigator.pushReplacementNamed(context, '/products');
} else {
setState(() {
tcVisibility = true;
});
}
Answer Updated

Flutter - Implementing a listView search feature

I've been trying to implement a search bar into my app for bringing selected listView items to the top of a list. The list contains quite a few items, around approximately 1700 so the addition of a search bar is essential. I'd like the listView search box to appear from a search icon on the right hand side of the top appBar. Below is a picture of the current view for reference.
When you click the search iconButton a search field should replace the title in the appBar. It's going to be evident to the user that this is for the crypto listView as I'll add a hint in the search view identifying this.
I'm not including all my code as this would be cumbersome for a stack question, but below is my home_page.dart file, where as the rest of my classes for the bottom crypto listView can be found at this GitHub repo.
This is what my 'home_page.dart` looks like;
import 'package:cryptick/cryptoData/crypto_data.dart';
import 'package:cryptick/cryptoData/trending_data.dart';
import 'package:cryptick/modules/crypto_presenter.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'background.dart';
//FOLLOWING DART CODE COPYRIGHT OF 2017 - 2018 SQUARED SOFTWARE LONDON
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => new _HomePageState();
}
class ServerStatusScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
iconTheme: new IconThemeData(color: Colors.white),
centerTitle: true,
backgroundColor: Colors.black,
title: new Text(
'API Server Status',
textAlign: TextAlign.center,
style: new TextStyle(
color: Colors.white, fontSize: 27.5, fontFamily: 'Kanit'),
),
),
body: new Center(
child: new Column(
children: [
new Divider(color: Colors.white),
new Text(
'News Feed: ',
textAlign: TextAlign.center,
style: new TextStyle(
color: Colors.black,
fontSize: 27.5,
fontFamily: 'Kanit',
),
),
new Divider(),
new Text(
'Crypto Feed: ',
textAlign: TextAlign.center,
style: new TextStyle(
color: Colors.black,
fontSize: 27.5,
fontFamily: 'Kanit',
),
),
new Divider(),
new Wrap(
alignment: WrapAlignment.center,
children: <Widget>[
new Chip(
backgroundColor: Colors.black,
label: new Text(
'© 2017-2018 Squared Software',
style: new TextStyle(
fontSize: 15.0,
fontFamily: 'Poppins',
color: Colors.white,
),
),
),
],
),
],
),
),
);
}
}
class MoreInfoScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
final ThemeData themeData = Theme.of(context);
final TextStyle aboutTextStyle = themeData.textTheme.body2;
final TextStyle linkStyle =
themeData.textTheme.body2.copyWith(color: themeData.accentColor);
return new Scaffold(
appBar: new AppBar(
iconTheme: new IconThemeData(color: Colors.white),
centerTitle: true,
backgroundColor: Colors.black,
title: new Text(
'More Info',
textAlign: TextAlign.center,
style: new TextStyle(
color: Colors.white, fontSize: 27.5, fontFamily: 'Kanit'),
),
),
body: new Center(
child: new Column(
children: [
new Divider(color: Colors.white),
new ListTile(
title: new Text('Squared Software',
style: new TextStyle(
fontWeight: FontWeight.w500,
fontFamily: 'Poppins',
)
),
leading: new CircleAvatar(
radius: 30.0,
backgroundImage: new AssetImage(
'images/sqinterlock.png'
)
)
),
new Divider(),
new Text('Where do we get our information?',
style: new TextStyle(
color: Colors.black,
fontFamily: 'Poppins',
fontSize: 16.5,
)
),
new Divider(color: Colors.white),
new Text(
"News Feed: bit.ly/2MFpzHX",
style: new TextStyle(
fontFamily: 'Poppins',
fontSize: 16.5,
),
),
new Divider(color: Colors.white),
new Text(
"Crypto Feed: bit.ly/2iIdJht",
style: new TextStyle(
fontFamily: 'Poppins',
fontSize: 16.5,
),
),
new Divider(color: Colors.white),
new Wrap(
alignment: WrapAlignment.center,
children: <Widget>[
new Chip(
backgroundColor: Colors.black,
label: new Text(
'© 2017-2018 Squared Software',
style: new TextStyle(
fontSize: 15.0,
fontFamily: 'Poppins',
color: Colors.white,
),
),
),
],
),
],
),
),
);
}
}
class _HomePageState extends State<HomePage> implements CryptoListViewContract {
CryptoListPresenter _presenter;
List<Crypto> _currencies;
bool _isLoading;
final List<MaterialColor> _colors = [Colors.blue, Colors.indigo, Colors.red];
_HomePageState() {
_presenter = new CryptoListPresenter(this);
}
#override
void onLoadTrendingComplete(Trending trending) {
// TODO:
articlesMap = trending.articles;
for (Map articleMap in articlesMap) {
articles.add(Articles.fromMap(articleMap));
}
if (mounted) setState(() {});
}
#override
void onLoadTrendingError() {
// TODO:
}
List articlesMap = [];
List<Articles> articles = [];
#override
void initState() {
super.initState();
_isLoading = true;
_presenter.loadCurrencies();
_presenter.loadTrending();
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(
"Cryp - Tick Exchange",
style: new TextStyle(
color: Colors.white,
fontFamily: 'Poppins',
fontSize: 22.5,
),
),
iconTheme: new IconThemeData(color: Colors.white),
backgroundColor: const Color(0xFF273A48),
elevation: 0.0,
centerTitle: true,
),
drawer: new Drawer(
child: new ListView(padding: EdgeInsets.zero, children: <Widget>[
new DrawerHeader(
child: new CircleAvatar(
child: new Image.asset('images/ctavatar.png'),
),
decoration: new BoxDecoration(
color: Colors.black,
),
),
new MaterialButton(
child: new Text(
'Server Status',
textAlign: TextAlign.center,
style: new TextStyle(fontSize: 27.5, fontFamily: 'Kanit'),
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ServerStatusScreen()),
);
}),
new Divider(),
new MaterialButton(
child: new Text(
'More Info',
textAlign: TextAlign.center,
style: new TextStyle(fontSize: 27.5, fontFamily: 'Kanit'),
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => MoreInfoScreen()),
);
}),
new Divider(),
new Wrap(
alignment: WrapAlignment.center,
children: <Widget>[
new Chip(
backgroundColor: Colors.black,
label: new Text(
'v0.0.1',
style: new TextStyle(
fontSize: 15.0,
fontFamily: 'Poppins',
color: Colors.white,
),
),
),
],
),
]),
),
body: _isLoading
? new Center(child: new CupertinoActivityIndicator(radius: 15.0))
: _allWidget());
}
Widget _allWidget() {
final _width = MediaQuery.of(context).size.width;
final _height = MediaQuery.of(context).size.height;
//CRYPTO FEED CRYPTO FEED CRYPTO FEED CRYPTO FEED CRYPTO FEED CRYPTO FEED CRYPTO FEED CRYPTO FEED CRYPTO FEED CRYPTO FEED CRYPTO FEED CRYPTO FEED CRYPTO FEED CRYPTO FEED
final headerList = new ListView.builder(
itemBuilder: (context, index) {
EdgeInsets padding = index == 0
? const EdgeInsets.only(
left: 20.0, right: 10.0, top: 4.0, bottom: 30.0)
: const EdgeInsets.only(
left: 10.0, right: 10.0, top: 4.0, bottom: 30.0);
return new Padding(
padding: padding,
child: new InkWell(
onTap: () {
print('#url');
},
child: new Container(
decoration: new BoxDecoration(
borderRadius: new BorderRadius.circular(10.0),
color: const Color(0xFF273A48),
boxShadow: [
new BoxShadow(
color: Colors.black.withAlpha(70),
offset: const Offset(3.0, 10.0),
blurRadius: 15.0)
],
image: new DecorationImage(
image: new NetworkImage(articles[index].urlToImage),
fit: BoxFit.fitHeight,
),
),
height: 200.0,
width: 275.0,
child: new Stack(
children: <Widget>[
new Align(
alignment: Alignment.bottomCenter,
child: new Container(
padding: new EdgeInsets.only(left: 10.0),
decoration: new BoxDecoration(
color: const Color(0xFF273A48),
borderRadius: new BorderRadius.only(
bottomLeft: new Radius.circular(10.0),
bottomRight: new Radius.circular(10.0)),
),
height: 50.0,
child: new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Expanded(child: new Text(
articles[index].title,
overflow: TextOverflow.ellipsis,
maxLines: 2,
style: new TextStyle(
color: Colors.white,
fontFamily: 'Poppins',
),
),
),
],
)
),
)
],
),
),
),
);
},
scrollDirection: Axis.horizontal,
itemCount: articles.length,
);
final body = new Scaffold(
backgroundColor: Colors.transparent,
body: new Container(
child: new Stack(
children: <Widget>[
new Padding(
padding: new EdgeInsets.only(top: 10.0),
child: new Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
new Align(
alignment: Alignment.centerLeft,
child: new Padding(
padding: new EdgeInsets.only(
left: 10.0,
),
child: new Text(
"Trending News",
style: new TextStyle(
letterSpacing: 0.8,
fontFamily: 'Kanit',
fontSize: 17.5,
color: Colors.white,
),
)),
),
new Container(
height: 300.0, width: _width, child: headerList),
new Expanded(child: ListView.builder(
itemBuilder: (BuildContext context, int index) {
final int i = index;
final Crypto currency = _currencies[i];
final MaterialColor color = _colors[i % _colors.length];
return new ListTile(
title: new Column(
children: <Widget>[
new Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new Container(
height: 72.0,
width: 72.0,
decoration: new BoxDecoration(
color: Colors.white,
boxShadow: [
new BoxShadow(
color: Colors.black.withAlpha(80),
offset: const Offset(2.0, 2.0),
blurRadius: 15.0)
],
borderRadius: new BorderRadius.all(
new Radius.circular(35.0)),
image: new DecorationImage(
image: new ExactAssetImage(
"cryptoiconsBlack/" +
currency.symbol.toLowerCase() +
"#2x.png",
),
fit: BoxFit.cover,
)),
),
new SizedBox(
width: 8.0,
),
new Expanded(
child: new Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new Text(
currency.name,
style: new TextStyle(
fontSize: 15.0,
fontFamily: 'Poppins',
color: Colors.black87,
fontWeight: FontWeight.bold),
),
_getSubtitleText(currency.price_usd,
currency.percent_change_1h),
],
)),
],
),
new Divider(),
],
),
);
}))
],
),
),
],
),
),
);
return new Container(
decoration: new BoxDecoration(
color: const Color(0xFF273A48),
),
child: new Stack(
children: <Widget>[
new CustomPaint(
size: new Size(_width, _height),
painter: new Background(),
),
body,
],
),
);
}
// CRYPTO FEED CRYPTO FEED CRYPTO FEED CRYPTO FEED CRYPTO FEED CRYPTO FEED CRYPTO FEED CRYPTO FEED CRYPTO FEED CRYPTO FEED CRYPTO FEED CRYPTO FEED CRYPTO FEED CRYPTO FEED
Widget _getSubtitleText(String priceUSD, String percentageChange) {
TextSpan priceTextWidget = new TextSpan(
text: "\$$priceUSD\n",
style: new TextStyle(
color: Colors.black,
fontSize: 14.0,
));
String percentageChangeText = "1 hour: $percentageChange%";
TextSpan percentageChangeTextWidget;
if (double.parse(percentageChange) > 0) {
percentageChangeTextWidget = new TextSpan(
text: percentageChangeText,
style: new TextStyle(
color: Colors.green,
fontFamily: 'PoppinsMediumItalic',
));
} else {
percentageChangeTextWidget = new TextSpan(
text: percentageChangeText,
style: new TextStyle(
color: Colors.red,
fontFamily: 'PoppinsMediumItalic',
));
}
return new RichText(
text: new TextSpan(
children: [priceTextWidget, percentageChangeTextWidget]));
}
//Works with cryptoListViewContract implimentation in _MyHomePageState
#override
void onLoadCryptoComplete(List<Crypto> items) {
// TODO: implement onLoadCryptoComplete
setState(() {
_currencies = items;
_isLoading = false;
});
}
#override
void onLoadCryptoError() {
// TODO: implement onLoadCryptoError
}
}
Thanks for the help, Jake
There are probably many ways to implement this based on the resulting experience you want. A simple solution is to create activeSearch state that toggles a 'search app bar' and a 'normal app bar'
Here's the normal app bar:
return AppBar(
title: Text("My App"),
actions: <Widget>[
IconButton(
icon: Icon(Icons.search),
onPressed: () => setState(() => activeSearch = true),
),
],
);
And here's the search app bar:
return AppBar(
leading: Icon(Icons.search),
title: TextField(
decoration: InputDecoration(
hintText: "here's a hint",
),
),
actions: <Widget>[
IconButton(
icon: Icon(Icons.close),
onPressed: () => setState(() => activeSearch = false),
)
],
);
Note: if you don't want to have a leading icon when search is active you may want to disable the default behavior for a drawer and back button icon with:
automaticallyImplyLeading: false
Full example:
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
bool activeSearch;
#override
void initState() {
super.initState();
activeSearch = false;
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: _appBar(),
drawer: _drawer(),
);
}
PreferredSizeWidget _appBar() {
if (activeSearch) {
return AppBar(
leading: Icon(Icons.search),
title: TextField(
decoration: InputDecoration(
hintText: "here's a hint",
),
),
actions: <Widget>[
IconButton(
icon: Icon(Icons.close),
onPressed: () => setState(() => activeSearch = false),
)
],
);
} else {
return AppBar(
title: Text("My App"),
actions: <Widget>[
IconButton(
icon: Icon(Icons.search),
onPressed: () => setState(() => activeSearch = true),
),
],
);
}
}
Widget _drawer() {
return Container();
}
}
UPDATE: Here's a hint at handling results
return AppBar(
...
title: TextField(
onChanged: _search,
),
);
And what _search could look like:
List<MyResultObject> _results;
void _search(String queryString) {
// do some searching and sorting
// then call setState() with the results
// and then in your ListView you can read from results
// (handle empty, default case as well in view)
setState(() {
_results = ...
});
}
List<Widget> _resultWidgets() {
if (_results.isEmpty) return _defaultWidgets();
_results.map((r) => _buildRowWidget(s)).toList();
}
Can u refer a simple search view in this answer. In that example, as the user types, the list will get filtered.

Resources