update: improve onbaording looks

This commit is contained in:
pahmiudahgede 2025-05-16 21:28:25 +07:00
parent 71c7e498b6
commit cbcb250be3
9 changed files with 341 additions and 251 deletions

View File

@ -9,6 +9,6 @@ export 'package:rijig_mobile/features/auth/presentation/screen/inputpin_screen.d
export 'package:rijig_mobile/features/auth/presentation/screen/login_screen.dart'; export 'package:rijig_mobile/features/auth/presentation/screen/login_screen.dart';
export 'package:rijig_mobile/features/auth/presentation/screen/otp_screen.dart'; export 'package:rijig_mobile/features/auth/presentation/screen/otp_screen.dart';
export 'package:rijig_mobile/features/auth/presentation/screen/verifpin_screen.dart'; export 'package:rijig_mobile/features/auth/presentation/screen/verifpin_screen.dart';
export 'package:rijig_mobile/features/launch/onboardingpage_screen.dart'; export 'package:rijig_mobile/features/launch/screen/onboardingpage_screen.dart';
export 'package:rijig_mobile/features/launch/splash_screen.dart'; export 'package:rijig_mobile/features/launch/screen/splash_screen.dart';
export 'package:rijig_mobile/features/home/presentation/components/about_detail_comp.dart'; export 'package:rijig_mobile/features/home/presentation/components/about_detail_comp.dart';

View File

@ -3,6 +3,7 @@ import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:carousel_slider/carousel_slider.dart'; import 'package:carousel_slider/carousel_slider.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:rijig_mobile/core/router.dart'; import 'package:rijig_mobile/core/router.dart';
import 'package:rijig_mobile/core/utils/guide.dart';
import 'package:rijig_mobile/features/home/presentation/viewmodel/about_vmod.dart'; import 'package:rijig_mobile/features/home/presentation/viewmodel/about_vmod.dart';
import 'package:rijig_mobile/features/requestpick/presentation/screen/requestpickup_screen.dart'; import 'package:rijig_mobile/features/requestpick/presentation/screen/requestpickup_screen.dart';
@ -83,11 +84,11 @@ class AboutComponentState extends State<AboutComponent> {
horizontal: 12, horizontal: 12,
vertical: 6, vertical: 6,
), ),
color: Colors.black.withOpacity(0.5), color: blackNavyColor.withValues(alpha: 0.5),
child: Text( child: Text(
imageData["title"], imageData["title"],
style: TextStyle( style: TextStyle(
color: Colors.white, color: whiteColor,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
), ),

View File

@ -0,0 +1,49 @@
import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import 'package:rijig_mobile/features/launch/model/onboard_model.dart';
class OnboardingView extends StatelessWidget {
const OnboardingView({super.key, required this.data});
final OnboardingModel data;
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.width,
child: Padding(
padding: const EdgeInsets.only(top: 40.0),
child: Image.network(data.imagePath, fit: BoxFit.contain),
),
),
Padding(
padding: const EdgeInsets.all(15),
child: Column(
children: [
Text(
data.headline,
style: Theme.of(context).textTheme.titleLarge?.copyWith(
fontWeight: FontWeight.bold,
fontSize: 24,
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 15.0),
child: Text(
data.description,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 16),
),
),
],
),
),
Gap(100),
],
);
}
}

View File

@ -0,0 +1,24 @@
import 'package:rijig_mobile/features/launch/model/onboard_model.dart';
class OnboardingData {
static List<OnboardingModel> items = [
OnboardingModel(
imagePath: "https://i.imgur.com/X2G11k0.png",
headline: 'Browse all the category',
description:
'In aliquip aute exercitation ut et nisi ut mollit. Deserunt dolor elit pariatur aute .',
),
OnboardingModel(
imagePath: "https://i.imgur.com/X2G11k0.png",
headline: 'Amazing Discounts & Offers',
description:
'In aliquip aute exercitation ut et nisi ut mollit. Deserunt dolor elit pariatur aute .',
),
OnboardingModel(
imagePath: "https://i.imgur.com/X2G11k0.png",
headline: 'Delivery in 30 Min',
description:
'In aliquip aute exercitation ut et nisi ut mollit. Deserunt dolor elit pariatur aute .',
),
];
}

View File

@ -0,0 +1,63 @@
import 'dart:convert';
class OnboardingModel {
String imagePath;
String headline;
String description;
OnboardingModel({
required this.imagePath,
required this.headline,
required this.description,
});
OnboardingModel copyWith({
String? imagePath,
String? headline,
String? description,
}) {
return OnboardingModel(
imagePath: imagePath ?? this.imagePath,
headline: headline ?? this.headline,
description: description ?? this.description,
);
}
Map<String, dynamic> toMap() {
return {
'imagePath': imagePath,
'headline': headline,
'description': description,
};
}
factory OnboardingModel.fromMap(Map<String, dynamic> map) {
return OnboardingModel(
imagePath: map['imagePath'] ?? '',
headline: map['headline'] ?? '',
description: map['description'] ?? '',
);
}
String toJson() => json.encode(toMap());
factory OnboardingModel.fromJson(String source) =>
OnboardingModel.fromMap(json.decode(source));
@override
String toString() =>
'OnboardingData(imagePath: $imagePath, headline: $headline, description: $description)';
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
return other is OnboardingModel &&
other.imagePath == imagePath &&
other.headline == headline &&
other.description == description;
}
@override
int get hashCode =>
imagePath.hashCode ^ headline.hashCode ^ description.hashCode;
}

View File

@ -1,137 +0,0 @@
import 'package:concentric_transition/concentric_transition.dart';
import 'package:flutter/material.dart';
import 'package:rijig_mobile/core/utils/guide.dart';
import 'package:rijig_mobile/core/router.dart';
final pages = [
const PageData(
icon: Icons.food_bank_outlined,
title: "Search for your favourite food",
bgColor: Color(0xff3b1791),
textColor: Colors.white,
),
const PageData(
icon: Icons.shopping_bag_outlined,
title: "Add it to cart",
bgColor: Color(0xfffab800),
textColor: Color(0xff3b1790),
),
const PageData(
icon: Icons.delivery_dining,
title: "Order and wait",
bgColor: Color(0xffffffff),
textColor: Color(0xff3b1790),
),
];
class OnboardingPageScreen extends StatefulWidget {
const OnboardingPageScreen({super.key});
@override
OnboardingPageScreenState createState() => OnboardingPageScreenState();
}
class OnboardingPageScreenState extends State<OnboardingPageScreen> {
final PageController _controller = PageController();
int _currentIndex = 0;
@override
void initState() {
super.initState();
_controller.addListener(() {
setState(() {
_currentIndex = _controller.page!.round();
});
});
}
@override
Widget build(BuildContext context) {
final screenWidth = MediaQuery.of(context).size.width;
return Scaffold(
body: ConcentricPageView(
colors: pages.map((p) => p.bgColor).toList(),
pageController: _controller,
radius: screenWidth * 0.1,
nextButtonBuilder: (context) {
if (_currentIndex == pages.length - 1) {
return InkWell(
onTap: () => router.go('/login'),
child: Center(
child: Text(
"Go to Login",
style: TextStyle(
fontSize: screenWidth * 0.04,
color: whiteColor,
),
// textAlign: TextAlign.center,
),
),
);
}
return Padding(
padding: const EdgeInsets.only(left: 3),
child: Icon(Icons.navigate_next, size: screenWidth * 0.08),
);
},
itemCount: pages.length,
scaleFactor: 2,
duration: Duration(milliseconds: 500),
itemBuilder: (index) {
final page = pages[index];
return SafeArea(child: _Page(page: page, index: index));
},
),
);
}
}
class PageData {
final String? title;
final IconData? icon;
final Color bgColor;
final Color textColor;
const PageData({
this.title,
this.icon,
this.bgColor = Colors.white,
this.textColor = Colors.black,
});
}
class _Page extends StatelessWidget {
final PageData page;
final int index;
const _Page({required this.page, required this.index});
@override
Widget build(BuildContext context) {
final screenHeight = MediaQuery.of(context).size.height;
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
padding: const EdgeInsets.all(16.0),
margin: const EdgeInsets.all(16.0),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: page.textColor,
),
child: Icon(page.icon, size: screenHeight * 0.1, color: page.bgColor),
),
Text(
page.title ?? "",
style: TextStyle(
color: page.textColor,
fontSize: screenHeight * 0.035,
fontWeight: FontWeight.bold,
),
textAlign: TextAlign.center,
),
],
);
}
}

View File

@ -0,0 +1,72 @@
import 'package:concentric_transition/concentric_transition.dart';
import 'package:flutter/material.dart';
import 'package:rijig_mobile/core/router.dart';
import 'package:rijig_mobile/core/utils/guide.dart';
import 'package:rijig_mobile/features/launch/components/onboarding_comp.dart';
import 'package:rijig_mobile/features/launch/model/onboard_data.dart';
class OnboardingPageScreen extends StatefulWidget {
const OnboardingPageScreen({super.key});
@override
OnboardingPageScreenState createState() => OnboardingPageScreenState();
}
class OnboardingPageScreenState extends State<OnboardingPageScreen> {
final PageController _controller = PageController();
int _currentIndex = 0;
@override
void initState() {
super.initState();
_controller.addListener(() {
setState(() {
_currentIndex = _controller.page!.round();
});
});
}
@override
Widget build(BuildContext context) {
final screenWidth = MediaQuery.of(context).size.width;
return Scaffold(
body: ConcentricPageView(
colors: [
_currentIndex == 0 ? whiteColor : primaryColor,
_currentIndex == 1 ? whiteColor : primaryColor,
_currentIndex == 2 ? whiteColor : primaryColor,
],
pageController: _controller,
radius: screenWidth * 0.1,
nextButtonBuilder: (context) {
if (_currentIndex == OnboardingData.items.length - 1) {
return InkWell(
onTap: () => router.go('/login'),
child: Center(
child: Text(
"Go to Login",
style: TextStyle(
fontSize: screenWidth * 0.04,
color: whiteColor,
),
),
),
);
}
return Padding(
padding: const EdgeInsets.only(left: 3),
child: Icon(Icons.navigate_next, size: screenWidth * 0.08),
);
},
itemCount: OnboardingData.items.length,
scaleFactor: 2,
duration: Duration(milliseconds: 500),
itemBuilder: (index) {
final page = OnboardingData.items[index];
return SafeArea(child: OnboardingView(data: page));
},
),
);
}
}

View File

@ -6,12 +6,13 @@ class PaymentItem extends StatelessWidget {
final IconData iconData; final IconData iconData;
final String amount; final String amount;
const PaymentItem( const PaymentItem({
{super.key, super.key,
required this.title, required this.title,
this.category, this.category,
required this.iconData, required this.iconData,
required this.amount}); required this.amount,
});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -19,20 +20,23 @@ class PaymentItem extends StatelessWidget {
height: 100, height: 100,
padding: const EdgeInsets.all(10), padding: const EdgeInsets.all(10),
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: const BorderRadius.all(Radius.circular(20)), borderRadius: const BorderRadius.all(Radius.circular(20)),
color: const Color(0xFF2c3135), color: const Color(0xFF2c3135),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: Colors.white.withOpacity(0.05), color: Colors.white.withValues(alpha: 0.05),
offset: const Offset(-10, -10), offset: const Offset(-10, -10),
spreadRadius: 0, spreadRadius: 0,
blurRadius: 10), blurRadius: 10,
BoxShadow( ),
color: Colors.black87.withOpacity(0.3), BoxShadow(
offset: const Offset(10, 10), color: Colors.black87.withValues(alpha: 0.3),
spreadRadius: 0, offset: const Offset(10, 10),
blurRadius: 10) spreadRadius: 0,
]), blurRadius: 10,
),
],
),
child: Row( child: Row(
children: [ children: [
SizedBox( SizedBox(
@ -43,46 +47,46 @@ class PaymentItem extends StatelessWidget {
outerShadow: true, outerShadow: true,
backgroundColor: const Color(0xFF2c3135), backgroundColor: const Color(0xFF2c3135),
shadowColor: Colors.black87, shadowColor: Colors.black87,
highlightColor: Colors.white.withOpacity(0.05), highlightColor: Colors.white.withValues(alpha: 0.05),
child: Icon( child: Icon(iconData, size: 28, color: Colors.white),
iconData,
size: 28,
color: Colors.white,
),
), ),
), ),
const SizedBox( const SizedBox(width: 16),
width: 16,
),
Expanded( Expanded(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Text( Text(
title, title,
style: const TextStyle( style: const TextStyle(
color: Colors.white, color: Colors.white,
fontSize: 18, fontSize: 18,
fontWeight: FontWeight.w600), fontWeight: FontWeight.w600,
), ),
const SizedBox( ),
height: 4, const SizedBox(height: 4),
), (category == null)
(category == null) ? const SizedBox.shrink()
? const SizedBox.shrink() : Text(
: Text(category!, category!,
style: TextStyle( style: TextStyle(
color: Colors.yellow.shade200.withOpacity(0.7), color: Colors.yellow.shade200.withValues(alpha: 0.7),
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.w600)) fontWeight: FontWeight.w600,
], ),
)), ),
Text(amount, ],
style: const TextStyle( ),
color: Colors.white, ),
fontSize: 18, Text(
fontWeight: FontWeight.w600)) amount,
style: const TextStyle(
color: Colors.white,
fontSize: 18,
fontWeight: FontWeight.w600,
),
),
], ],
), ),
); );
@ -97,55 +101,65 @@ class NeumorphicCircle extends StatelessWidget {
final Color backgroundColor; final Color backgroundColor;
final Widget? child; final Widget? child;
const NeumorphicCircle( const NeumorphicCircle({
{super.key, super.key,
required this.innerShadow, required this.innerShadow,
required this.outerShadow, required this.outerShadow,
required this.highlightColor, required this.highlightColor,
required this.shadowColor, required this.shadowColor,
required this.backgroundColor, required this.backgroundColor,
this.child}); this.child,
});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Stack(alignment: Alignment.center, children: [ return Stack(
Container( alignment: Alignment.center,
children: [
Container(
decoration: BoxDecoration( decoration: BoxDecoration(
color: backgroundColor, color: backgroundColor,
shape: BoxShape.circle, shape: BoxShape.circle,
boxShadow: (outerShadow) boxShadow:
? [ (outerShadow)
? [
BoxShadow( BoxShadow(
color: highlightColor, color: highlightColor,
offset: const Offset(-10, -10), offset: const Offset(-10, -10),
blurRadius: 20, blurRadius: 20,
spreadRadius: 0), spreadRadius: 0,
),
BoxShadow( BoxShadow(
color: shadowColor, color: shadowColor,
offset: const Offset(10, 10), offset: const Offset(10, 10),
blurRadius: 20, blurRadius: 20,
spreadRadius: 0) spreadRadius: 0,
),
] ]
: null)), : null,
(innerShadow) ),
? ClipPath( ),
(innerShadow)
? ClipPath(
clipper: HighlightClipper(), clipper: HighlightClipper(),
child: CircleInnerHighlight( child: CircleInnerHighlight(
highlightColor: highlightColor, highlightColor: highlightColor,
backgroundColor: backgroundColor, backgroundColor: backgroundColor,
)) ),
: const SizedBox.shrink(), )
(innerShadow) : const SizedBox.shrink(),
? ClipPath( (innerShadow)
? ClipPath(
clipper: ShadowClipper(), clipper: ShadowClipper(),
child: CircleInnerShadow( child: CircleInnerShadow(
shadowColor: shadowColor, shadowColor: shadowColor,
backgroundColor: backgroundColor, backgroundColor: backgroundColor,
), ),
) )
: const SizedBox.shrink(), : const SizedBox.shrink(),
(child != null) ? child! : const SizedBox.shrink() (child != null) ? child! : const SizedBox.shrink(),
]); ],
);
} }
} }
@ -153,8 +167,11 @@ class CircleInnerShadow extends StatelessWidget {
final Color shadowColor; final Color shadowColor;
final Color backgroundColor; final Color backgroundColor;
const CircleInnerShadow( const CircleInnerShadow({
{super.key, required this.shadowColor, required this.backgroundColor}); super.key,
required this.shadowColor,
required this.backgroundColor,
});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -162,10 +179,7 @@ class CircleInnerShadow extends StatelessWidget {
decoration: BoxDecoration( decoration: BoxDecoration(
shape: BoxShape.circle, shape: BoxShape.circle,
gradient: RadialGradient( gradient: RadialGradient(
colors: [ colors: [backgroundColor, shadowColor],
backgroundColor,
shadowColor,
],
center: const AlignmentDirectional(0.05, 0.05), center: const AlignmentDirectional(0.05, 0.05),
focal: const AlignmentDirectional(0, 0), focal: const AlignmentDirectional(0, 0),
radius: 0.5, radius: 0.5,
@ -175,12 +189,14 @@ class CircleInnerShadow extends StatelessWidget {
), ),
child: Container( child: Container(
decoration: BoxDecoration( decoration: BoxDecoration(
shape: BoxShape.circle, shape: BoxShape.circle,
gradient: LinearGradient( gradient: LinearGradient(
begin: Alignment.topLeft, begin: Alignment.topLeft,
end: Alignment.bottomRight, end: Alignment.bottomRight,
stops: const [0, 0.45], stops: const [0, 0.45],
colors: [backgroundColor.withOpacity(0), backgroundColor])), colors: [backgroundColor.withValues(alpha: 0), backgroundColor],
),
),
), ),
); );
} }
@ -190,8 +206,11 @@ class CircleInnerHighlight extends StatelessWidget {
final Color highlightColor; final Color highlightColor;
final Color backgroundColor; final Color backgroundColor;
const CircleInnerHighlight( const CircleInnerHighlight({
{super.key, required this.highlightColor, required this.backgroundColor}); super.key,
required this.highlightColor,
required this.backgroundColor,
});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -199,10 +218,7 @@ class CircleInnerHighlight extends StatelessWidget {
decoration: BoxDecoration( decoration: BoxDecoration(
shape: BoxShape.circle, shape: BoxShape.circle,
gradient: RadialGradient( gradient: RadialGradient(
colors: [ colors: [backgroundColor, highlightColor],
backgroundColor,
highlightColor,
],
center: const AlignmentDirectional(-0.05, -0.05), center: const AlignmentDirectional(-0.05, -0.05),
focal: const AlignmentDirectional(-0.05, -0.05), focal: const AlignmentDirectional(-0.05, -0.05),
radius: 0.6, radius: 0.6,
@ -212,12 +228,14 @@ class CircleInnerHighlight extends StatelessWidget {
), ),
child: Container( child: Container(
decoration: BoxDecoration( decoration: BoxDecoration(
shape: BoxShape.circle, shape: BoxShape.circle,
gradient: LinearGradient( gradient: LinearGradient(
begin: Alignment.topLeft, begin: Alignment.topLeft,
end: Alignment.bottomRight, end: Alignment.bottomRight,
stops: const [0.55, 1], stops: const [0.55, 1],
colors: [backgroundColor, backgroundColor.withOpacity(0)])), colors: [backgroundColor, backgroundColor.withValues(alpha: 0)],
),
),
), ),
); );
} }