Aqua
Utility classes/functions to help with UI development using the Flutter framework.
It is recommended to use the as keyword with the import statement when importing the package to prevent name conflicts, for example...
import 'package:aqua/aqua.dart' as aqua
To log output to file
await aqua.log('data to log', logFile: 'path/to/file', clear: true, time: true);
To save data to device
Future<void> save() async {
var id = 'id';
var _value = 1920;
await aqua.Pref.set(id, value);
var value = await aqua.Pref.get(id);
}
To put a block of code in a try catch
// the argument for tryCatch could either be a callback to a function or a future
// as a function
Widget _buildWidget(){
// may fail to build for some reason
}
var child = await aqua.tryCatch(_buildWidget());
// as a future
Future<Widget> _buildWidget() async {
// may fail to build for some reason
}
var future = _buildWidget();
var child = await aqua.tryCatch(future);
if(child != null){
// proceed
}
When fetching data from server in json, or posting a query to server in json
// posting to an endpoint
var fromServer = await aqua.Client(
'192.168.1.100', //ip
8080, // port
'/test', // endpoint
query: {
'id': 1,
}, // post parameters
// verbose: true
).getResponse();
// a real end point would look like this
// the end point is free to use
// you can find the rest of the endpoints here: https://www.coingecko.com/en/api
var fromServer = await aqua.Client(
'api.coingecko.com',
443,
'/api/v3/coins/markets',
isSecured: true,
query: {
'vs_currency': 'usd',
'order': 'market_cap_desc',
'per_page': '20',
'page': '1',
'sparkline': 'true'
}
).getResponse(method: 'GET');
DESKTOP ONLY
To allow for mouse pointers to change to click icons on hovering on a clickable widget
@override
Widget build(BuildContext context){
// some code
// then
return aqua.MouseInteractivity(
child: child
);
}
To get a random index between a range of indexes
var index = aqua.getRandomNumber(min: 10, max: 10000);
To output info on screen with different colors
aqua.pretifyOutput('to print on screen'); // will print in green
aqua.pretifyOutput('to print on screen', color: 'red');
To add a shadowy effect on an image
@override
Widget build(BuildContext context){
return Stack(
children: [
_buildImage(),
aqua.Shadow(
width: width,
height: height,
)
]
);
}
A quick drop down widget
@override
Widget build(BuildContext context){
return aqua.DropDown(
initValue: 'one',
items: ['one', 'two', 'three', 'four', 'five', 'six']
);
}
A quick TabBar. Tabs without scaffold...
@override
Widget build(BuildContext context){
return Material(
child: DefaultTabController(
length: 3,
child: Column(
children: [
aqua.TabHeader(
tabListing: ['car', 'transit', 'bike'],
),
Expanded(
child: TabBarView(
children: [
Icon(Icons.directions_car),
Icon(Icons.directions_transit),
Icon(Icons.directions_bike),
],
),
)
],
),
)
);
}
To get screen dimensions in scale
@override
Widget build(BuildContext context){
aqua.Dimensions().init(context);
return Container(
width: aqua.Dimensions.width, // full width of screen
height: aqua.Dimensions.height, // full height of screen
color: Colors.red
);
}
To captilaize a word
var capitalized = aqua.capitalize('alphabet');
print('capitalized: $capitalized);
To create a file quickly (will also create the recursive directories on the path)
await aqua.createFile('/path/to/file');
// to clear a file/truncate a file
await aqua.createFile('/path/to/file', clear: true);
To generate a random ID
var id = aqua.generateUUID(length: 30);
To navigate
// some code
// then
aqua.Dimensions().init(context);
Widget viewOne = Container(
width: aqua.Dimensions.width,
height: aqua.Dimensions.height
color: Colors.blue
);
Widget viewTwo = Container(
width: aqua.Dimensions.width,
height: aqua.Dimensions.height
color: Colors.red
);
// to navigate to the next view without erasing the previous view from state
aqua.CustomNavigator(
context: context,
buildScreen: () = > viewOne
).navigateToPage();
// to navigate to the next view and erase the previous view from state
aqua.CustomNavigator(
context: context,
replaceSingle: true,
buildScreen: () = > viewOne
).navigateToPage();
// to navigate to the next view and erase ALL the previous views from state
aqua.CustomNavigator(
context: context,
replaceAll: true,
buildScreen: () = > viewOne
).navigateToPage();
// to navigate to the next view using a named route
aqua.CustomNavigator(
context: context,
namedRoute: '/home',
buildScreen: () = > viewOne
).navigateToPage();
To display loading icon
// render this widget as you see fit
Widget loadingIcon = aqua.LoadingIcon();
// to specify a loading type: check the different loading icons at this location
// https://github.com/jogboms/flutter_spinkit
import 'package:flutter_spinkit/flutter_spinkit.dart' as spinkitt;
Widget loadingIcon = aqua.LoadingIcon(
spinkitWidget: spinkitt.SpinKitWave(
color: Colors.blue,
size: 40.0,
),
);
To request focus from another widget
@override
Widget build(BuildContext context){
// some code
// then
Widget withFocus = aqua.requestFocus(child, context: context);
// make sure to return a widget
}
To add commas to numbers
String number = aqua.pretifyNumber('1000000');
print('number: $number');
To clip images into a circular widget
@override
Widget build(BuildContext context){
// some code
// then
Widget clippedImage = aqua.ClippedCircle(
child: child // some widget, could be an image, wrapped in a container,
color: Colors.blue // border of the circle
);
// make sure to return a widget
}
Custom Text Form Widget
class Play extends StatefulWidget {
@override
PlayState createState() => PlayState();
}
class PlayState extends State<Play>{
FocusNode focusNode;
TextEditingController textEditingController;
@override
void initState(){
super.initState();
focusNode = FocusNode();
textEditingController = TextEditingController();
}
@override
void dispose(){
focusNode?.dispose();
textEditingController?.dispose();
super.dispose();
}
@override
Widget build(BuildContext context){
aqua.Dimensions().init(context);
// more on this later ...
// check source code :)
return SizedBox(
width: aqua.Dimensions.width,
height: 100.0,
child: aqua.TextFormFieldCustom(
isOutlineBorder: true, // or false
focusNode: focusNode
controller: textEditingController,
)
);
}
}
FLUTTER DEVICES
Window Navigator, a bit of boilerplate code is needed for this to work ...
To setup your environment for mobile, click here
To setup your environment for desktop, click here
Copy paste the code below to render a screen like this:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:aqua/aqua.dart' as aqua;
class Shell extends StatefulWidget {
@override
ShellState createState() => ShellState();
}
class ShellState extends State<Shell>{
Widget selectedWidget;
aqua.NavigationStreamer mainNavStreamer;
StreamSubscription mainNavStreamSubscription;
@override
void initState(){
super.initState();
mainNavStreamer = aqua.NavigationStreamer();
mainNavStreamSubscription = mainNavStreamer.listen((data){
aqua.pretifyOutput('[SHELL] data from nav stream: $data');
selectedWidget = data['window'];
setState((){});
});
}
@override
void dispose(){
mainNavStreamSubscription.cancel();
mainNavStreamer.close();
super.dispose();
}
Widget _buildShell(BuildContext context){
aqua.Dimensions().init(context);
double navWidth = aqua.Dimensions.width * 0.15;
double contentWindowWidth = aqua.Dimensions.width - navWidth;
Map<String, Map<String, dynamic>> generatedRoutes = _buildGeneratedRoutes(
contentWindowWidth,
aqua.Dimensions.height
);
var textStyle = TextStyle(
fontSize: 30.0,
color: Colors.white,
fontWeight: FontWeight.bold
);
Widget firstWidget = Container(
width: contentWindowWidth,
height: aqua.Dimensions.height,
color: Colors.purple,
child: Center(
child: Text(
'Home',
style: textStyle
)
),
);
return Scaffold(
appBar: null,
body: SingleChildScrollView(
child: Container(
child: Row(
children: [
aqua.Navigation(
width: navWidth,
height: aqua.Dimensions.height,
header: Container(
width: navWidth,
height: 100.0,
color: Colors.red,
child: Center(
child: Text(
'Header',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold
),
),
),
),
routes: generatedRoutes,
bgColors: <Color>[
Colors.blue,
Colors.blueAccent
],
hoverColor: Colors.brown.withOpacity(0.5),
selectedColor: Colors.white.withOpacity(0.5),
navStreamer: mainNavStreamer,
),
Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
selectedWidget == null ? aqua.requestFocus(
firstWidget,
context: context
) : aqua.requestFocus(
selectedWidget,
context: context
)
],
),
)
]
)
),
),
);
}
@override
Widget build(BuildContext context) => _buildShell(context);
Map<String, Map<String, dynamic>> _buildGeneratedRoutes(double windowWidth, double windowHeight){
var textStyle = TextStyle(
fontSize: 30.0,
color: Colors.white,
fontWeight: FontWeight.bold
);
Function _buildIconHelper = (IconData iconData){
return Icon(iconData, color: Colors.black, size: 15.0,);
};
return {
'Home': {
'window': Container(
width: windowWidth,
height: windowHeight,
color: Colors.purple,
child: Center(
child: Text(
'Home',
style: textStyle
)
),
),
'icon': _buildIconHelper(Icons.home)
},
'Search': {
'window': Container(
width: windowWidth,
height: windowHeight,
child: Stack(
children: [
aqua.Shadow(
height: windowWidth,
width: windowHeight,
colors: [
Colors.green,
Colors.teal
],
),
Center(
child: Text(
'Search',
style: textStyle
)
),
],
)
),
'icon': _buildIconHelper(Icons.search)
},
'Settings': {
'window': Container(
width: windowWidth,
height: windowHeight,
color: Colors.indigo,
child: Center(
child: Text(
'Settings',
style: textStyle
)
),
),
'icon': _buildIconHelper(Icons.settings)
}
};
}
}