Last active
August 8, 2021 13:52
-
-
Save PetreaLoredana/dde5c9cc3caa78c8fa6e12d43ca53021 to your computer and use it in GitHub Desktop.
This code generates a screen with a custom bidirectional and infinite scrollable PageView in Flutter. Replace your own assets names. More details can be found on Medium. https://medium.com/p/dfff43649c23/edit
This file contains 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 'package:flutter/material.dart'; | |
import 'package:flutter/services.dart'; | |
void main() => runApp(CustomPageViewApp()); | |
class CustomPageViewApp extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
SystemChrome.setPreferredOrientations([ | |
DeviceOrientation.portraitUp, | |
DeviceOrientation.portraitDown, | |
]); | |
return MaterialApp( | |
title: 'Custom PageView', | |
home: CustomPageViewScreen(), | |
); | |
} | |
} | |
class CustomPageViewScreen extends StatefulWidget { | |
@override | |
_CustomPageViewScreenState createState() => new _CustomPageViewScreenState(); | |
} | |
class _CustomPageViewScreenState extends State<CustomPageViewScreen> { | |
List interests = [ | |
InterestsModel('Snowboarding', 'assets/ic_snowboarding_gray.png'), | |
InterestsModel('BMX', 'assets/ic_bike_gray.png'), | |
InterestsModel('Skateboarding', 'assets/ic_skateboarding_gray.png') | |
]; | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
body: Container( | |
color: Color.fromRGBO(36, 43, 47, 1), | |
child: Column( | |
mainAxisAlignment: MainAxisAlignment.center, | |
children: <Widget>[ | |
_buildTitle(), | |
_buildInterestsContent(), | |
_buildCheckIcon(), | |
_buildNextButton() | |
], | |
)), | |
); | |
} | |
Text _buildTitle() { | |
return Text( | |
"Choose your interests".toUpperCase(), | |
textAlign: TextAlign.center, | |
style: TextStyle( | |
color: Color.fromRGBO(243, 243, 243, 1), | |
fontSize: 19, | |
fontFamily: 'RadikalMedium'), | |
); | |
} | |
Stack _buildInterestsContent() { | |
return Stack( | |
children: <Widget>[ | |
_buildInterestsPageView(), | |
Row( | |
mainAxisAlignment: MainAxisAlignment.spaceBetween, | |
children: <Widget>[ | |
Image.asset('assets/bg_gradient_left.png'), | |
Image.asset('assets/bg_gradient_right.png'), | |
], | |
), | |
], | |
); | |
} | |
List selectedInterests = []; | |
PageController pageController = | |
PageController(viewportFraction: 0.45, initialPage: 4240); | |
Container _buildInterestsPageView() { | |
return Container( | |
height: 210, | |
child: PageView.builder( | |
itemBuilder: (context, int currentIdx) { | |
int crt = currentIdx; | |
if (crt > 2) { | |
if (crt % 3 == 0) { | |
crt = 0; | |
} else if ((crt + 1) % 3 == 0) { | |
crt = 2; | |
} else if ((crt - 1) % 3 == 0) { | |
crt = 1; | |
} | |
} | |
return Container( | |
margin: const EdgeInsets.only(top: 31.0), | |
child: _buildPageViewItem(interests[crt], crt), | |
); | |
}, | |
controller: pageController, | |
), | |
); | |
} | |
GestureDetector _buildPageViewItem(InterestsModel data, int crt) { | |
bool active = selectedInterests.contains(crt); | |
final String backgroundAsset = active | |
? 'assets/bg_yellow_bordered.png' | |
: 'assets/bg_gray_bordered.png'; | |
return GestureDetector( | |
onTap: () { | |
setState(() { | |
if (selectedInterests.contains(crt)) | |
selectedInterests.remove(crt); | |
else { | |
selectedInterests.add(crt); | |
} | |
}); | |
}, | |
child: Column( | |
children: <Widget>[ | |
Text(data.title.toUpperCase(), | |
style: TextStyle( | |
color: Color.fromRGBO(243, 243, 243, 1), | |
fontFamily: 'RadikalThin', | |
fontSize: 11.0, | |
)), | |
SizedBox( | |
height: 129, | |
width: 129, | |
child: Container( | |
margin: const EdgeInsets.only(top: 5), | |
decoration: BoxDecoration( | |
image: DecorationImage(image: AssetImage(backgroundAsset))), | |
child: Image.asset(data.imageAsset), | |
)), | |
], | |
), | |
); | |
} | |
Container _buildCheckIcon() { | |
String buttonAsset = selectedInterests.isEmpty | |
? 'assets/ic_check_gray.png' | |
: 'assets/ic_check_yellow_rounded.png'; | |
return Container( | |
child: Image.asset(buttonAsset), | |
); | |
} | |
Container _buildNextButton() { | |
return Container( | |
alignment: Alignment.center, | |
margin: const EdgeInsets.only(left: 71, right: 71, top: 21), | |
child: SizedBox( | |
width: double.infinity, | |
height: 45, | |
child: RaisedButton( | |
child: Text( | |
"Next".toUpperCase(), | |
style: TextStyle( | |
color: Color.fromRGBO(40, 48, 52, 1), | |
fontFamily: 'RadikalMedium', | |
fontSize: 19), | |
), | |
color: Colors.white, | |
elevation: 4.0, | |
onPressed: () {}, | |
), | |
), | |
); | |
} | |
} | |
class InterestsModel { | |
String imageAsset; | |
String title; | |
InterestsModel(this.title, this.imageAsset); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment