In this article, we will look into how to make a beautiful Login and OTP and Farmer Dashboard screen and authenticate the mobile number with OTP after successfully validating and then opening the navigation farmer dashboard screen. What needs the farmer app?, How to develop the farmer app?
Why do we need a farmer app. how to develop this app and what are the farmer requirements? for example – cattle management, cattle feed, cattle breeding, Health of cattle, milk production, frame shard, cattle insurance, pregnancy of the cattle check, and much more issues resolve on this app. So I have developed a farmer app in a flutter framework and provided a push notification to the farmer with this app.
This app is useful for milk production and selling details to their retail customers and farmers to ensure crop management.
Login – Every app used this screen as per the requirement of their services to create and authentication access is given to our users.
OTP– this screen checks the mobile number OTP validation for the valid OTP and number after that is open the next screen to the farmer dashboard.
Have used the flutter formwork and dart programming to develop this app screen some parts.
Environment
- 1.71.0 (Universal)
- Dart Programming
- Flutter 3.0.5+ Version
- Build iOS
- Build Android
- Run iPhone 11 Pro
- Android SDK
- XCODE
- Terminal (on Mac/Linux) or CMD (on Windows)
- IDE (Android Studio/IntelliJ/Visual Studio Code)
Features structure
- MVC structure
- The navigation screen each other
- Validation covers
- Delegate pass value
- ListView UI Design
- Widgets – Button / text field / link / Text
- Scrolling with full screen
- Google map implementation
Pods(Pub.dev)
- path_provider: ^2.0.8
- http: ^0.13.0
- shared_preferences: ^2.0.7
- fluttertoast: ^8.0.8
- flutter_spinkit: ^5.1.0
- intl_utils: ^2.7.0
- package_info: ^2.0.0
- permission_handler: ^6.0.1+1
- google_fonts: ^2.1.0
- progress_dialog_null_safe: ^1.0.6
- intl_phone_field: ^3.1.0
- pin_code_fields: ^7.4.0
To get started using all Pods Plugin open the pubspec.yaml file and under dev_dependencies paste the following, using the same indentation as below
Use Layout (Screens):
Login:- The login screen most important used scenario of any mobile app and website page or an entry page to a web/mobile application that requires user identification and authentication, regularly performed by entering a username and password combination as per the required combination.
Mobile Number Enter screen:- Show the mobile number enter the screen and fill in the number by the user.
OTP Screen:
This screen fills the 6-digit PIN number verification on the enter previous screen its shows on the mobile number pin box. Pin number validation is set by the user giving the error message on the invalid and blank value and pressing the button.
The user is not getting any message on the fill previous mobile number then clicks resend button and it defines the 15 sent on the reload of the screen and gets the OTP by using the mobile number. If 6 digits enter correctly and the REST API check validation shows the next screen now the farmer dashboard screen is open.
Success Screen / Message / Login Screen:
As per the requirer to use a message/screen / and images, this screen shows the Success massage and show the logo of the company (app) and the bottom button is add the login button click this then go to the main login screen and user fill their ID and Password then login again of the application and used for any app.
Farmer Dashboard:
Have shown the farmer dashboard screen below on this article this screen is based on everything in the app word and shows the summary of the screen like all offers, total cattle, today’s milk collection, avg milk production cattle master, and health check of the farmer cattle and after 6th box below much more information for the farmer like push notification payment summary, and advisory for the cattle health and much more on this app.
Let’s get started on the main steps!
User Module Class
import 'dart:convert';
LoginModel userResponceFromJson(String str) => LoginModel.fromJson(json.decode(str));
String userResponceToJson(LoginModel data) => json.encode(data.toJson());
class LoginModel {
LoginModel({
this.status = "",
this.accountId = "",
this.accountName = "",
this.phone = "",
this.accessToken = "",
});
String status;
String accountId;
String accountName;
String phone;
String accessToken;
factory LoginModel.fromJson(Map<String, dynamic> json) => LoginModel(
status: json["Status"],
accountId: json["AccountId"],
accountName: json["AccountName"],
phone: json["phone"],
accessToken: json["AccessToken"],
);
Map<String, dynamic> toJson() => {
"Status": status,
"AccountId": accountId,
"AccountName": accountName,
"phone": phone,
"AccessToken": accessToken,
};
}
Login screen code
import 'package:auto_size_text/auto_size_text.dart';
import 'package:farmerapp/src/Module/userRespo.dart';
import 'package:farmerapp/src/Pages/loginScreen/controllers_page.dart';
import 'package:farmerapp/src/Pages/loginScreen/otp_verification_screen.dart';
import 'package:farmerapp/src/Utility/apptheme.dart';
import 'package:farmerapp/src/Utility/common_screen.dart';
import 'package:farmerapp/src/Utility/validate_inputs.dart';
import 'package:farmerapp/src/Utility/validator_class.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:page_transition/page_transition.dart';
import 'package:fluttertoast/fluttertoast.dart';
class myAppLogin extends StatefulWidget {
const myAppLogin(String text);
@override
_myAppLoginState createState() => _myAppLoginState();
}
class _myAppLoginState extends State<myAppLogin> {
bool isUserNameValidate = false;
var loginData = new LoginModel();
var LoginFUrl = "https://api.xxxxx.in/Login";
final textFieldFocusNode = FocusNode();
bool _obscured = false;
@override
Widget build(BuildContext context) {
double height = MediaQuery.of(context).size.height / 19;
double width = MediaQuery.of(context).size.width;
return GestureDetector(
onTap: () {
FocusScope.of(context).requestFocus(new FocusNode());
},
child: Scaffold(
backgroundColor: Colors.white,
key: ValidationData.scaffoldKeyMobileScreen,
body: Form(
key: ValidationData.formKeyValidateMobileScreen,
child: Container(
child: SingleChildScrollView(
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
TopContainer(),
Container(
height: height,
color: Colors.white,
),
Padding(
padding: EdgeInsets.only(left: 35),
child: AutoSizeText(
"",
style: GoogleFonts.montserrat(
fontSize: 18,
color: WidgetColors.MainTitleColor,
),
),
),
Container(
height: height / 1.5,
),
Padding(
padding: EdgeInsets.only(left: 43),
child: AutoSizeText(
"Phone number",
style: GoogleFonts.montserrat(
fontSize: 14,
color: WidgetColors.TextColor,
),
),
),
Container(
height: height / 3.5,
),
Padding(
padding: EdgeInsets.only(left: 30, right: 35),
child: Container(
child: Row(
children: <Widget>[
Container(
width: 0,
),
Expanded(
child: TextFormField(
controller: AllControllers.phoneController,
keyboardType: TextInputType.number,
validator: ValidationData.MobileValidator,
decoration: InputDecoration(
isDense: true,
errorStyle: TextStyle(height: 0
// fontSize: 14.0,
// color: WidgetColors.errorTextColor
),
contentPadding:
const EdgeInsets.all(13.0),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.transparent),
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: WidgetColors.TextfieldColor),
),
// errorBorder: OutlineInputBorder(
// // borderSide:
// // BorderSide(color: Colors.red)
// ),
hintText: "Your Phone Number",
hintStyle: GoogleFonts.montserrat(
color: WidgetColors.HintColor,
fontSize: 14)),
inputFormatters: [
new LengthLimitingTextInputFormatter(10)
],
),
)
],
),
height: 50,
decoration: BoxDecoration(
color: WidgetColors.TextfieldColor,
borderRadius: BorderRadius.circular(5)),
)),
Container(
height: height / 5,
),
Padding(
padding: EdgeInsets.only(left: 50),
child: AutoSizeText(
"You will receive OTP on this number",
style: GoogleFonts.montserrat(
fontSize: 10,
color: WidgetColors.PhoneNumberBelowColor),
),
),
Container(
height: height / 2,
),
Padding(
padding: EdgeInsets.only(left: 35, right: 35),
child: Container(
// height: 1.2 * (MediaQuery.of(context).size.height / 16),
// width: 5 * (MediaQuery.of(context).size.width / 10),
margin: EdgeInsets.only(bottom: 20.0),
child: RaisedButton(
elevation: 5.0,
color: AppTheme.mainColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
onPressed: () {
if (ValidationData
.formKeyValidateMobileScreen.currentState
.validate()) {
print('ok');
setState(() async {
ValidateInputs.validateMobileInputs(
'9807608488', context);
Navigator.push(
context,
PageTransition(
type: PageTransitionType.fade,
alignment: Alignment.center,
child: OtpVerificationScreen(
actualCode: "verificationId",
mobileNumber: AllControllers
.phoneController.text,
countryCode: '+91',
)));
ValidateInputs.validateInputs(
'222999', context);
});
} else {
print('not ok');
Fluttertoast.showToast(
msg: "Please enter your mobile number.",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
timeInSecForIosWeb: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 16.0);
}
},
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
"Send OTP",
style: TextStyle(
color: Colors.white,
letterSpacing: 1.5,
fontSize: MediaQuery.of(context)
.size
.height /
40,
),
)
],
),
),
],
),
),
),
),
)
],
),
))),
))
);
}
}
TopContainer Class
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
class TopContainer extends StatelessWidget {
final String assetName = 'assets/images/your images ----->.png';
@override
Widget build(BuildContext context) {
double width = MediaQuery.of(context).size.width;
return SizedBox(
height: MediaQuery.of(context).size.height / 1.8,
width: width,
child: Stack(
children: <Widget>[
SizedBox(
width: MediaQuery.of(context).size.width,
child: Image.asset(
assetName,
fit: BoxFit.fill,
height: MediaQuery.of(context).size.height / 1.8,
width: MediaQuery.of(context).size.width,
),
),
),
],
),
);
}
}
OTP Screen
// ignore_for_file: avoid_unnecessary_containers, unused_local_variable, prefer_const_constructors
import 'dart:async';
import 'package:auto_size_text/auto_size_text.dart';
import 'package:farmerapp/src/pages/home/homeMenu/home.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:farmerapp/src/Module/userRespo.dart';
import 'package:farmerapp/src/pages/loginScreen/controllers_page.dart';
import 'package:farmerapp/src/Services/api_manager.dart';
import 'package:farmerapp/src/Utility/apptheme.dart';
import 'package:farmerapp/src/Utility/common_screen.dart';
import 'package:farmerapp/src/Utility/validate_inputs.dart';
import 'package:farmerapp/src/Utility/validator_class.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:progress_dialog_null_safe/progress_dialog_null_safe.dart';
// ignore: import_of_legacy_library_into_null_safe
//import 'package:progress_dialog/progress_dialog.dart';
class OtpVerificationScreen extends StatefulWidget {
var actualCode;
var mobileNumber;
var countryCode;
OtpVerificationScreen({this.actualCode, this.mobileNumber, this.countryCode});
@override
_OtpVerificationScreenState createState() => _OtpVerificationScreenState();
}
class _OtpVerificationScreenState extends State<OtpVerificationScreen> {
bool _loading;
ProgressDialog prg;
List<LoginModel> tempLoginData = [];
var getMobile = "";
@override
void initState() {
AllControllers.teOtpDigitOne.text = "";
AllControllers.teOtpDigitTwo.text = "";
AllControllers.teOtpDigitThree.text = "";
AllControllers.teOtpDigitFour.text = "";
AllControllers.teOtpDigitFive.text = "";
AllControllers.teOtpDigitSix.text = "";
super.initState();
getMobile = widget.mobileNumber;
setState(() {
startTimer();
});
}
@override
void dispose() {
super.dispose();
_timer.cancel();
AllControllers.focusNodeDigitTwo.dispose();
AllControllers.focusNodeDigitThree.dispose();
AllControllers.focusNodeDigitFour.dispose();
AllControllers.focusNodeDigitFive.dispose();
AllControllers.focusNodeDigitSix.dispose();
AllControllers.focusNodeDigitOne.dispose();
}
Timer _timer;
int _start = 15;
void startTimer() {
const oneSec = Duration(seconds: 1);
// ignore: unnecessary_new
_timer = new Timer.periodic(
oneSec,
(Timer timer) => setState(
() {
if (_start < 1) {
timer.cancel();
} else {
_start = _start - 1;
}
},
),
);
}
Future<void> resendM() async {
_start = 15;
setState(() {
startTimer();
});
textWidget();
prg.show();
await API_Manager.mobileNoPostParms(widget.mobileNumber).then((OTPResult) {
setState(() {
prg.hide();
});
});
}
buildLoading(BuildContext context) {
return showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return Center(
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(Colors.blue),
),
);
});
}
Widget textWidget() {
if (_start > 0) {
print(_start);
return AutoSizeText(
"Wait $_start",
style: GoogleFonts.montserrat(
fontSize: 12,
color: WidgetColors.TextColor,
),
);
} else {
return InkWell(
child: AutoSizeText(
"Resend", //
style: GoogleFonts.montserrat(
fontSize: 12,
color: WidgetColors.MainTitleColor,
),
),
onTap: () {
//startTimer();
resendM();
},
);
}
}
Widget _box1() {
return Center(
child: Container(
margin: EdgeInsets.symmetric(vertical: 5, horizontal: 3),
alignment: Alignment.center,
height: MediaQuery.of(context).size.height / 15,
width: MediaQuery.of(context).size.width / 10,
child: TextFormField(
autofocus: true,
textAlign: TextAlign.center,
keyboardType: TextInputType.number,
controller: AllControllers.teOtpDigitOne,
textInputAction: TextInputAction.next,
onChanged: (_) => FocusScope.of(context).nextFocus(), // focus to next
maxLength: 1,
decoration: InputDecoration(
//border: InputBorder.none,
errorStyle: TextStyle(height: 0),
counterText: '',
contentPadding: const EdgeInsets.all(5)),
validator: (value) {
if (value == null || value.isEmpty) {
Fluttertoast.showToast(
msg: "Please Enter OTP",
toastLength: Toast.LENGTH_LONG,
gravity: ToastGravity.TOP,
timeInSecForIosWeb: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 13.0);
return '';
}
return null;
},
),
decoration: BoxDecoration(
border: Border(
left: BorderSide(
// <--- left side
color: Colors.white,
width: 3.0,
),
top: BorderSide(
// <--- top side
color: Colors.white,
width: 3.0,
),
),
),
),
);
}
//...
//2 to 5 create your self in same code
//...
Widget _box6() {
return Center(
child: Container(
// width: 10.0,
margin: EdgeInsets.symmetric(vertical: 5, horizontal: 3),
alignment: Alignment.center,
height: MediaQuery.of(context).size.height / 15,
width: MediaQuery.of(context).size.width / 10,
child: TextFormField(
textAlign: TextAlign.center,
autofocus: true,
// autovalidate: true,
keyboardType: TextInputType.number,
controller: AllControllers.teOtpDigitSix,
textInputAction: TextInputAction.done,
onChanged: (_) => FocusScope.of(context).unfocus(), // Unfocus an
maxLength: 1,
decoration: InputDecoration(
// border: InputBorder.none,
errorStyle: TextStyle(height: 0),
//color: Colors.red,
// wordSpacing: 1.0,
counterText: '',
contentPadding: const EdgeInsets.all(5)),
validator: (value) {
if (value == null || value.isEmpty) {
Fluttertoast.showToast(
msg: "Please Enter OTP.",
toastLength: Toast.LENGTH_LONG,
gravity: ToastGravity.TOP,
timeInSecForIosWeb: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 13.0);
return '';
}
return null;
},
),
// decoration: BoxDecoration(border: Border.all(color: Colors.blue,width: 1)),
decoration: BoxDecoration(
border: Border(
left: BorderSide(
// <--- left side
color: Colors.white,
width: 3.0,
),
top: BorderSide(
// <--- top side
color: Colors.white,
width: 3.0,
),
),
)),
);
}
@override
Widget build(BuildContext context) {
double height = MediaQuery.of(context).size.height;
double width = MediaQuery.of(context).size.width;
prg = ProgressDialog(context, type: ProgressDialogType.normal);
prg.style(
message: 'Please wait.......',
borderRadius: 4.0,
backgroundColor: Colors.grey,
progressWidget: CircularProgressIndicator(),
maxProgress: 1.0,
);
var otpBox = Padding(
padding: EdgeInsets.only(left: 50.0, right: 50.0),
child: Row(
children: <Widget>[
_box1(),
_box2(),
_box3(),
_box4(),
_box5(),
_box6(),
],
));
//remove keyboard
return GestureDetector(
onTap: () {
FocusScope.of(context).requestFocus(FocusNode());
},
child: Scaffold(
appBar: AppBar(
title: Text('OTP Verification'),
flexibleSpace: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: const FractionalOffset(0.0, 0.0),
end: const FractionalOffset(1.0, 1.0),
// ignore: prefer_const_literals_to_create_immutables
colors: <Color>[
const Color(0xFF4BA198),
const Color(0xFF4BA198),
],
stops: const <double>[0.0, 1.0],
tileMode: TileMode.clamp,
),
),
),
),
backgroundColor: Colors.white,
body: Form(
key: ValidationData.formKeyValidateOTPScreen,
//autovalidate: true,
child: Container(
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
TopContainer(),
Container(
height: height / 12,
),
Center(
child: RichText(
text: TextSpan(
text: 'Please enter the OTP sent to - ',
style: GoogleFonts.montserrat(
fontSize: 14,
color: WidgetColors.TextColor,
),
children: <TextSpan>[
TextSpan(
text: widget.mobileNumber,
style: GoogleFonts.montserrat(
fontSize: 14,
color: WidgetColors.mainBtnColor,
),
),
],
),
),
),
Container(
height: height * 0.02,
),
otpBox,
Container(
height: height * 0.02,
),
Padding(
padding: EdgeInsets.only(left: 70, right: 70),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
AutoSizeText(
"",
style: GoogleFonts.montserrat(
fontSize: 12,
color: WidgetColors.didntColor,
),
),
Container(
width: width / 9.9,
),
textWidget()
],
),
),
Container(
height: height * 0.05,
),
Container(
margin: EdgeInsets.only(
left: 40, top: 10, right: 40, bottom: 5),
child: RaisedButton(
elevation: 9.0,
color: AppTheme.mainColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
onPressed: () {
if (ValidationData
.formKeyValidateOTPScreen.currentState
.validate()) {
//print('ok');
var myOTPNumer =
AllControllers.teOtpDigitOne.text +
AllControllers.teOtpDigitTwo.text +
AllControllers.teOtpDigitThree.text +
AllControllers.teOtpDigitFour.text +
AllControllers.teOtpDigitFive.text +
AllControllers.teOtpDigitSix.text;
// ignore: non_constant_identifier_names
ValidateInputs.validateMobileInputs(
widget.mobileNumber, context);
vBaseUrl =
'https://api.xxxxx.in/base/';
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (context) => const HomePage()),
ModalRoute.withName("/home"));
} else {
print('not ok');
prg.hide();
//
}
},
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Center(
child: Text(
"Verify and Proceed",
style: TextStyle(
color: Colors.white,
letterSpacing: 1.5,
fontSize:
MediaQuery.of(context).size.height / 40,
),
),
),
),
),
)
],
),
),
))),
);
}
}
Farmer dashboard
// ignore_for_file: prefer_const_literals_to_create_immutables
import 'package:farmerapp/src/pages/home/homeMenu/topoffer.dart';
import 'package:farmerapp/src/utility/menu/drawer.dart';
import 'package:flutter/material.dart';
class ProductCardWidget extends StatefulWidget {
@override
_ProductCardWidgetState createState() => _ProductCardWidgetState();
}
class _ProductCardWidgetState extends State<ProductCardWidget> {
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
drawer: myDrawer(),
appBar: AppBar(
title: const Text("Farmer Dashboard"),
flexibleSpace: Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: FractionalOffset(0.0, 0.0),
end: FractionalOffset(1.0, 1.0),
colors: <Color>[
Color(0xFF4BA198),
Color(0xFF4BA198),
],
stops: <double>[0.0, 1.0],
tileMode: TileMode.clamp,
),
),
),
),
body: Stack(
children: <Widget>[
Padding(
// ignore: prefer_const_constructors
padding: EdgeInsets.only(left: 10.0, right: 10.0, top: 8.0),
child: TopMenus(),
),
Padding(
padding: const EdgeInsets.only(top: 50),
child: Container(
child: Padding(
// ignore: prefer_const_constructors
padding: EdgeInsets.only(left: 10.0, right: 10.0, top: 40.0),
child: GridView.count(
crossAxisCount: 2,
children: <Widget>[
Card(
color: Colors.blue,
// ignore: prefer_const_constructors
margin: EdgeInsets.only(
left: 10.0, right: 5.0, top: 20.0, bottom: 20.0),
elevation: 3.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0)),
child: InkWell(
splashColor: Colors.blue.withAlpha(30),
onTap: () {
print('Total Cattle List card');
Navigator.pushReplacementNamed(context, "/profile");
},
child: Align(
alignment: Alignment.center,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(
flex: 8,
child: Padding(
padding: const EdgeInsets.only(top: 20.0),
child: Image.asset(
'assets/images/dashbord_icon/cows1.png',
color: Colors.white),
),
),
const Expanded(
flex: 2,
child: Text(
'Total Cattle: 10',
style: TextStyle(
color: Colors.white,
fontSize: 14.0,
fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
),
),
],
),
)),
),
Card(
color: Colors.blue,
margin: EdgeInsets.only(
left: 5.0, right: 10.0, top: 20.0, bottom: 20.0),
elevation: 10.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0)),
child: InkWell(
splashColor: Colors.blue.withAlpha(30),
onTap: () {
print('milk collection click card');
Navigator.pushReplacementNamed(context, "/milkCollection");
},
child: Align(
alignment: Alignment.center,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(
flex: 8,
child: Padding(
padding: const EdgeInsets.only(top: 30.0),
child: Image.asset(
'assets/images/dashbord_icon/milkcol.png',
color: Colors.white),
)),
const Expanded(
flex: 2,
child: Text(
'Milk Collection: 20',
style: TextStyle(
color: Colors.white,
fontSize: 14.0,
fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
),
),
],
)),
),
),
Card(
color: Colors.blue,
margin: const EdgeInsets.only(
left: 10.0, right: 5.0, top: 10.0, bottom: 20.0),
elevation: 10.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0)),
child: InkWell(
splashColor: Colors.blue.withAlpha(30),
onTap: () {
print('avg collection milk click card');
},
child: Align(
alignment: Alignment.center,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(
flex: 8,
child: Padding(
padding: const EdgeInsets.only(top: 30.0),
child: Image.asset(
'assets/images/dashbord_icon/milkcol.png',
color: Colors.white),
),
),
const Expanded(
flex: 2,
child: Text(
'Kgs Av.Milk/Cow: 100', // +
style: TextStyle(
color: Colors.white,
fontSize: 14.0,
fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
),
),
],
)),
),
),
Card(
margin: const EdgeInsets.only(
left: 5.0, right: 10.0, top: 10.0, bottom: 20.0),
color: Colors.blue,
elevation: 10.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0)),
child: InkWell(
splashColor: Colors.blue.withAlpha(30),
onTap: () {
print('cattle master click card');
},
child: Align(
alignment: Alignment.center,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(
flex: 8,
child: Padding(
padding:
const EdgeInsets.only(top: 30.0),
child: Image.asset(
'assets/images/dashbord_icon/cowmaster.png',
color: Colors.white),
)),
const Expanded(
flex: 2,
child: Text(
'Cattle Master',
style: TextStyle(
color: Colors.white,
fontSize: 14.0,
fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
),
),
],
)),
),
),
Card(
margin: const EdgeInsets.only(
left: 5.0, right: 10.0, top: 10.0, bottom: 20.0),
color: Colors.blue,
elevation: 10.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0)),
child: InkWell(
splashColor: Colors.blue.withAlpha(30),
onTap: () {
print('health check click card');
},
child: Align(
alignment: Alignment.center,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(
flex: 8,
child: Padding(
padding:
const EdgeInsets.only(top: 30.0),
child: Image.asset(
'assets/images/dashbord_icon/healthcheck.png',
color: Colors.white),
)),
const Expanded(
flex: 2,
child: Text(
'Health Check: 120', // +
style: TextStyle(
color: Colors.white,
fontSize: 14.0,
fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
),
),
],
)),
),
),
],
),
),
),
),
],
));
}
}
Main Screen
import 'package:farmerapp/src/pages/home/homeMenu/home.dart';
import 'package:farmerapp/src/pages/add_request/otp.dart';
import 'package:farmerapp/src/pages/loginScreen/login_screen.dart';
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Farmer App',
debugShowCheckedModeBanner: false,
home: MySharedPreferences.instance.getBooleanValue("loggedIn") == true
? const HomePageFB()
: const myAppLogin(""),
routes: {
"/login": (context) => const myAppLogin(""),
"/otp": (context) => OTP(),
"/home": (context) => const HomePage(),
},
);
}
}
If you need an iOS and Android app development so contact to an app development company
Final output
I hope it was a useful article, please share and subscribe to my channel, Thanks for reading and if you have any questions or comments, See you soon.