elCaribe app - customization and branding
This commit is contained in:
196
news-app/lib/ui/screens/introSlider.dart
Normal file
196
news-app/lib/ui/screens/introSlider.dart
Normal file
@@ -0,0 +1,196 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:news/ui/screens/auth/Widgets/svgPictureWidget.dart';
|
||||
import 'package:news/ui/styles/colors.dart';
|
||||
import 'package:news/ui/widgets/customTextBtn.dart';
|
||||
import 'package:news/ui/widgets/customTextLabel.dart';
|
||||
import 'package:news/utils/uiUtils.dart';
|
||||
import 'package:news/app/routes.dart';
|
||||
import 'package:news/cubits/settingCubit.dart';
|
||||
|
||||
class Slide {
|
||||
final String? imageUrl;
|
||||
final String? title;
|
||||
final String? description;
|
||||
|
||||
Slide({@required this.imageUrl, @required this.title, @required this.description});
|
||||
}
|
||||
|
||||
class IntroSliderScreen extends StatefulWidget {
|
||||
const IntroSliderScreen({super.key});
|
||||
|
||||
@override
|
||||
GettingStartedScreenState createState() => GettingStartedScreenState();
|
||||
}
|
||||
|
||||
class GettingStartedScreenState extends State<IntroSliderScreen> with TickerProviderStateMixin {
|
||||
PageController pageController = PageController();
|
||||
|
||||
int currentIndex = 0;
|
||||
|
||||
late List<Slide> slideList = [
|
||||
Slide(imageUrl: 'onboarding1', title: UiUtils.getTranslatedLabel(context, 'welTitle1'), description: UiUtils.getTranslatedLabel(context, 'welDes1')),
|
||||
Slide(imageUrl: 'onboarding2', title: UiUtils.getTranslatedLabel(context, 'welTitle2'), description: UiUtils.getTranslatedLabel(context, 'welDes2')),
|
||||
Slide(imageUrl: 'onboarding3', title: UiUtils.getTranslatedLabel(context, 'welTitle3'), description: UiUtils.getTranslatedLabel(context, 'welDes3')),
|
||||
];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
bottomNavigationBar: nextButton(),
|
||||
appBar: AppBar(automaticallyImplyLeading: false, centerTitle: false, actions: [setSkipButton()], title: SvgPictureWidget(assetName: "intro_icon", fit: BoxFit.cover)),
|
||||
body: _buildIntroSlider());
|
||||
}
|
||||
|
||||
gotoNext() {
|
||||
context.read<SettingsCubit>().changeShowIntroSlider(false);
|
||||
Navigator.of(context).pushReplacementNamed(Routes.login);
|
||||
}
|
||||
|
||||
void onPageChanged(int index) {
|
||||
setState(() {
|
||||
currentIndex = index; //update current index for Next button
|
||||
});
|
||||
}
|
||||
|
||||
Widget _buildIntroSlider() {
|
||||
return PageView.builder(
|
||||
onPageChanged: onPageChanged,
|
||||
controller: pageController,
|
||||
itemCount: slideList.length,
|
||||
itemBuilder: (context, index) {
|
||||
final size = MediaQuery.of(context).size;
|
||||
final imagePath = slideList[index].imageUrl;
|
||||
|
||||
return SizedBox(
|
||||
width: size.width * 0.99,
|
||||
height: size.height * 0.75,
|
||||
child: Transform(
|
||||
alignment: Alignment.center,
|
||||
transform: Matrix4.identity()
|
||||
..setEntry(3, 2, 0.001)
|
||||
..rotateX(0.1),
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned(
|
||||
left: size.width * 0.3,
|
||||
right: size.width * 0.3,
|
||||
top: size.height * 0.71,
|
||||
child: Container(
|
||||
height: 7,
|
||||
decoration: BoxDecoration(
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: UiUtils.getColorScheme(context).primary.withOpacity(0.3),
|
||||
blurRadius: 20,
|
||||
spreadRadius: 5,
|
||||
offset: Offset.zero,
|
||||
),
|
||||
],
|
||||
shape: BoxShape.rectangle,
|
||||
),
|
||||
),
|
||||
),
|
||||
Card(
|
||||
color: secondaryColor,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(40.0)),
|
||||
elevation: 0,
|
||||
margin: const EdgeInsets.fromLTRB(24, 30, 24, 20),
|
||||
child: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(20),
|
||||
child: imagePath != null ? SvgPictureWidget(assetName: imagePath, fit: BoxFit.contain) : SizedBox.shrink(),
|
||||
),
|
||||
),
|
||||
titleText(index),
|
||||
subtitleText(index),
|
||||
progressIndicator(index),
|
||||
const SizedBox(height: 25),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget setSkipButton() {
|
||||
return (currentIndex != slideList.length - 1)
|
||||
? CustomTextButton(
|
||||
onTap: () {
|
||||
gotoNext();
|
||||
},
|
||||
color: UiUtils.getColorScheme(context).primaryContainer.withOpacity(0.7),
|
||||
text: UiUtils.getTranslatedLabel(context, 'skip'))
|
||||
: const SizedBox.shrink();
|
||||
}
|
||||
|
||||
Widget titleText(int index) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.only(left: 20, right: 10),
|
||||
margin: const EdgeInsets.only(bottom: 20.0, left: 10, right: 10),
|
||||
alignment: Alignment.center,
|
||||
child: CustomTextLabel(text: slideList[index].title!, textStyle: Theme.of(context).textTheme.headlineSmall?.copyWith(color: darkSecondaryColor, fontWeight: FontWeight.bold, letterSpacing: 0.5)),
|
||||
);
|
||||
}
|
||||
|
||||
Widget subtitleText(int index) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.only(left: 10),
|
||||
margin: const EdgeInsets.only(bottom: 55.0, left: 10, right: 10),
|
||||
child: CustomTextLabel(
|
||||
text: slideList[index].description!,
|
||||
textAlign: TextAlign.left,
|
||||
textStyle: Theme.of(context).textTheme.titleMedium?.copyWith(color: darkSecondaryColor.withOpacity(0.5), fontWeight: FontWeight.normal, letterSpacing: 0.5),
|
||||
maxLines: 3,
|
||||
overflow: TextOverflow.ellipsis));
|
||||
}
|
||||
|
||||
Widget progressIndicator(int index) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: List<Widget>.generate(
|
||||
slideList.length,
|
||||
(index) => Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 5),
|
||||
child: InkWell(
|
||||
onTap: () => pageController.animateToPage(index, duration: const Duration(seconds: 1), curve: Curves.fastLinearToSlowEaseIn),
|
||||
child: (currentIndex == index)
|
||||
? ClipRRect(borderRadius: BorderRadius.circular(10.0), child: Container(height: 10, width: 40.0, color: darkSecondaryColor))
|
||||
: CircleAvatar(radius: 5, backgroundColor: darkSecondaryColor.withOpacity(0.6))))));
|
||||
}
|
||||
|
||||
Widget nextButton() {
|
||||
return MaterialButton(
|
||||
splashColor: Colors.transparent,
|
||||
highlightColor: Colors.transparent,
|
||||
padding: EdgeInsets.symmetric(horizontal: MediaQuery.of(context).size.width * 0.28, vertical: 20),
|
||||
onPressed: () {
|
||||
if (currentIndex == slideList.length - 1 && currentIndex != 0) {
|
||||
gotoNext();
|
||||
} else {
|
||||
currentIndex += 1;
|
||||
pageController.animateToPage(currentIndex, duration: const Duration(seconds: 1), curve: Curves.fastLinearToSlowEaseIn);
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
height: 50,
|
||||
width: 162,
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(color: Theme.of(context).primaryColor, borderRadius: BorderRadius.circular(14)),
|
||||
child: CustomTextLabel(
|
||||
text: (currentIndex == (slideList.length - 1)) ? 'loginBtn' : 'nxt',
|
||||
textStyle: Theme.of(context).textTheme.bodyLarge!.copyWith(color: secondaryColor, fontWeight: FontWeight.bold),
|
||||
textAlign: TextAlign.center)));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user