I had a case where I was asked to change the position of “DotsIndicator” on my on_boarding page in an application I made with Flutter. I tried various ways to match the design.
This my code
import 'package:flutter_svg/flutter_svg.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:introduction_screen/introduction_screen.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:dots_indicator/dots_indicator.dart';
// another import
// ignore: must_be_immutable
class WalkthroughPage extends StatefulWidget {
WalkthroughPage({Key? key}) : super(key: key);
SharedPreferences prefs = serviceLocator.get<SharedPreferences>();
@override
_WalkthroughPageState createState() => _WalkthroughPageState();
}
class _WalkthroughPageState extends State<WalkthroughPage> {
final introKey = GlobalKey<IntroductionScreenState>();
bool lastPage = false;
double pageposition = 0;
void _onIntroEnd(context) {
_setPreference();
BlocProvider.of<AuthenticationBloc>(context).add(ShowLogin());
}
void _nextPage() {
introKey.currentState!.controller
.nextPage(duration: Duration(milliseconds: 250), curve: Curves.easeIn);
}
Widget _buildImage(String assetName, [double width = 350]) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: Image.asset('assets/images/$assetName', width: width),
);
}
@override
void initState() {
super.initState();
}
void _setPreference() async {
await widget.prefs.setBool('seen', true);
}
@override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
const pageDecoration = const PageDecoration(
titleTextStyle: TextStyle(
fontSize: 28.0,
fontWeight: FontWeight.w800,
color: Colors.white,
fontFamily: 'Nunito'),
bodyPadding: EdgeInsets.fromLTRB(16.0, 0.0, 16.0, 16.0),
imagePadding: EdgeInsets.only(
top: 40,
),
bodyTextStyle:
TextStyle(fontSize: 14.0, color: Colors.white, fontFamily: 'Nunito'),
);
var introList = [
PageViewModel(
image: _buildImage("walk1.png"),
titleWidget: Container(
padding: EdgeInsets.only(left: 15, top: 15),
child: Align(
alignment: Alignment.center,
child: Text(
"Food ESTE ! Ready to roll",
textScaler: TextScaler.noScaling,
textAlign: TextAlign.center,
style: TextPalette.registerTitleStyle,
),
),
),
bodyWidget: Container(
height: Screen(size).hp(68),
child: Column(children: [
Align(
alignment: Alignment.center,
child: Text(
"Digitalisasi Food ESTE !",
textScaler: TextScaler.noScaling,
textAlign: TextAlign.center,
style: TextPalette.registerSubtitleStyle),
),
Flexible(child: SizedBox(height: 65)),
InkWell(
onTap: () {
_nextPage();
},
child: Center(
child: Container(
child: KmpFlatButton(
minWidth: 230,
onPressed: (){
_nextPage();
},
buttonType: ButtonType.secondary,
title: "Mulai",
),
),
),
),
]),
),
decoration: pageDecoration,
),
PageViewModel(
image: _buildImage("walk2.png"),
titleWidget: Container(
padding: EdgeInsets.only(left: 15, top: 15),
child: Align(
alignment: Alignment.center,
child: Text(
"Branding Food ESTE",
textScaler: TextScaler.noScaling,
textAlign: TextAlign.center,
style: TextPalette.registerTitleStyle,
),
),
),
bodyWidget: Container(
height: Screen(size).hp(68),
child: Column(children: [
Align(
alignment: Alignment.center,
child: Text(
"Food ESTE For Future",
textScaler: TextScaler.noScaling,
textAlign: TextAlign.center,
style: TextPalette.registerSubtitleStyle),
),
Flexible(child: SizedBox(height: 65)),
InkWell(
onTap: () {
_nextPage();
},
child: Container(
child: Container(
child: KmpFlatButton(
minWidth: 230,
onPressed: (){
_nextPage();
},
buttonType: ButtonType.secondary,
title: "Mulai",
),
),
),
),
]),
),
decoration: pageDecoration,
),
PageViewModel(
image: _buildImage("walk3.png"),
titleWidget: Container(
padding: EdgeInsets.only(left: 15, top: 15),
child: Align(
alignment: Alignment.center,
child: Text(
"Pembinaan Food ESTE",
textScaler: TextScaler.noScaling,
textAlign: TextAlign.center,
style: TextPalette.registerTitleStyle,
),
),
),
bodyWidget: Container(
height: Screen(size).hp(68),
child: Column(children: [
Align(
alignment: Alignment.center,
child: Text(
"Food ESTE Quick",
textScaler: TextScaler.noScaling,
textAlign: TextAlign.center,
style: TextPalette.registerSubtitleStyle),
),
Flexible(child: SizedBox(height: 30)),
KmpFlatButton(
minWidth: 230,
buttonType: ButtonType.secondary,
onPressed: () => _onIntroEnd(context),
title: 'Mulai',
),
]),
),
decoration: pageDecoration,
),
];
return Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [Colors.white, Colors.white])),
child: Scaffold(
backgroundColor: Colors.transparent,
body: SafeArea(
child: IntroductionScreen(
globalBackgroundColor: Colors.transparent,
onChange: (page) {
pageposition = page.toDouble();
setState(() {});
if (page == introList.length - 1) {
setState(() {
lastPage = true;
});
} else {
setState(() {
lastPage = false;
});
}
},
key: introKey,
globalHeader: Container(
padding: EdgeInsets.only(left: 20, right: 20, top: 5),
width: double.infinity,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
DotsIndicator(
position: pageposition.toInt(),
dotsCount: introList.length,
decorator: DotsDecorator(
size: Size(10.0, 10.0),
color: Colors.black38,
activeColor: Colors.black,
activeSize: Size(21.0, 10.0),
activeShape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(25.0)),
),
),
),
],
),
),
pages: introList,
onDone: () => _onIntroEnd(context),
showNextButton: false,
showDoneButton: false,
isProgress: false,
),
),
),
);
}
}
and this is the result of my code after I run it
and this is the design of the screen that I want
can anyone help me to make the “DotsIndicator” to the position as in the design?