4 changed files with 176 additions and 3 deletions
-
8lib/common_ui/resources/my_text_style.dart
-
40lib/features/intro/presentation/ui/intro_page.dart
-
129lib/features/intro/presentation/ui/widgets/intro_loading_widget.dart
-
2lib/features/level/presentation/ui/widgets/level_widget.dart
@ -1,10 +1,48 @@ |
|||||
import 'package:flutter/material.dart'; |
import 'package:flutter/material.dart'; |
||||
|
import 'package:hadi_hoda_flutter/common_ui/resources/my_assets.dart'; |
||||
|
import 'package:hadi_hoda_flutter/core/utils/my_image.dart'; |
||||
|
import 'package:hadi_hoda_flutter/core/utils/screen_size.dart'; |
||||
|
import 'package:hadi_hoda_flutter/features/intro/presentation/ui/widgets/intro_loading_widget.dart'; |
||||
|
|
||||
class IntroPage extends StatelessWidget { |
class IntroPage extends StatelessWidget { |
||||
const IntroPage({super.key}); |
const IntroPage({super.key}); |
||||
|
|
||||
@override |
@override |
||||
Widget build(BuildContext context) { |
Widget build(BuildContext context) { |
||||
return const Scaffold(); |
|
||||
|
return Scaffold( |
||||
|
body: Container( |
||||
|
height: context.heightScreen, |
||||
|
width: context.widthScreen, |
||||
|
decoration: BoxDecoration( |
||||
|
gradient: LinearGradient( |
||||
|
begin: Alignment.topCenter, |
||||
|
end: Alignment.bottomCenter, |
||||
|
colors: [Color(0XFF00154C), Color(0XFF150532)], |
||||
|
), |
||||
|
image: DecorationImage( |
||||
|
image: AssetImage(MyAssets.pattern), |
||||
|
scale: 3, |
||||
|
repeat: ImageRepeat.repeat, |
||||
|
colorFilter: ColorFilter.mode( |
||||
|
Colors.white.withValues(alpha: 0.2), |
||||
|
BlendMode.srcIn, |
||||
|
), |
||||
|
), |
||||
|
), |
||||
|
child: Stack( |
||||
|
alignment: Alignment.center, |
||||
|
children: [_image(), _loading(context)], |
||||
|
), |
||||
|
), |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
MyImage _image() => MyImage(image: MyAssets.hadiHoda, size: 200); |
||||
|
|
||||
|
Positioned _loading(BuildContext context) { |
||||
|
return Positioned( |
||||
|
bottom: MediaQuery.viewPaddingOf(context).bottom, |
||||
|
child: IntroLoadingWidget(percent: 80), |
||||
|
); |
||||
} |
} |
||||
} |
} |
@ -0,0 +1,129 @@ |
|||||
|
import 'package:flutter/material.dart'; |
||||
|
import 'package:hadi_hoda_flutter/common_ui/resources/my_spaces.dart'; |
||||
|
import 'package:hadi_hoda_flutter/common_ui/resources/my_text_style.dart'; |
||||
|
|
||||
|
|
||||
|
class IntroLoadingWidget extends StatelessWidget { |
||||
|
const IntroLoadingWidget({ |
||||
|
super.key, |
||||
|
this.percent, |
||||
|
}); |
||||
|
|
||||
|
final double? percent; |
||||
|
|
||||
|
@override |
||||
|
Widget build(BuildContext context) { |
||||
|
return ClipPath( |
||||
|
clipper: BubbleClip(), |
||||
|
child: Container( |
||||
|
width: 300, |
||||
|
height: 60, |
||||
|
padding: EdgeInsets.symmetric( |
||||
|
vertical: MySpaces.s4, |
||||
|
horizontal: MySpaces.s2, |
||||
|
), |
||||
|
decoration: const BoxDecoration( |
||||
|
gradient: LinearGradient( |
||||
|
begin: Alignment(0, 1), // bottom |
||||
|
end: Alignment(0, -1), // top |
||||
|
colors: [ |
||||
|
Color(0xFFCADCFF), // #CADCFF |
||||
|
Colors.white, // #FFFFFF |
||||
|
], |
||||
|
), |
||||
|
), |
||||
|
child: Row( |
||||
|
children: [ |
||||
|
Expanded( |
||||
|
flex: 85, |
||||
|
child: ClipPath( |
||||
|
clipper: BubbleClip(), |
||||
|
child: AnimatedContainer( |
||||
|
duration: const Duration(milliseconds: 300), |
||||
|
padding: EdgeInsetsDirectional.only( |
||||
|
end: 260 - ((percent ?? 0) * 260 / 100), |
||||
|
), |
||||
|
decoration: BoxDecoration( |
||||
|
color: Color(0xFF1F59BD).withValues(alpha: 0.25), |
||||
|
), |
||||
|
child: ClipPath( |
||||
|
clipper: BubbleClip(), |
||||
|
child: Container( |
||||
|
decoration: BoxDecoration( |
||||
|
gradient: RadialGradient( |
||||
|
radius: 2, |
||||
|
colors: [ |
||||
|
Color(0xFFFFBD00), // #CADCFF |
||||
|
Color(0xFFFF772C), // #CADCFF |
||||
|
], |
||||
|
), |
||||
|
), |
||||
|
), |
||||
|
), |
||||
|
), |
||||
|
), |
||||
|
), |
||||
|
Expanded( |
||||
|
flex: 15, |
||||
|
child: Center( |
||||
|
child: Text( |
||||
|
'${percent?.toInt() ?? 0}%', |
||||
|
style: MyTextStyle.normal17.copyWith( |
||||
|
color: Color(0XFF6E83A8), |
||||
|
), |
||||
|
), |
||||
|
), |
||||
|
), |
||||
|
], |
||||
|
), |
||||
|
), |
||||
|
); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
class BubbleClip extends CustomClipper<Path> { |
||||
|
@override |
||||
|
Path getClip(Size size) { |
||||
|
// Original SVG viewBox: 334 x 60 |
||||
|
const double w0 = 334.0; |
||||
|
const double h0 = 60.0; |
||||
|
final sx = size.width / w0; |
||||
|
final sy = size.height / h0; |
||||
|
|
||||
|
// SVG path: |
||||
|
// M9.82057 10.3597 |
||||
|
// C -1.70838 17.1589 -3.47995 44.4301 6.60447 53.1719 |
||||
|
// C 16.0075 61.291 305.076 61.9385 323.201 53.4956 |
||||
|
// C 341.326 45.0527 332.116 8.04571 324.829 5.7273 |
||||
|
// C 307.985 -2.06805 28.6539 -0.77294 9.82057 10.3597 |
||||
|
// Z |
||||
|
final p = Path() |
||||
|
..moveTo(9.82057 * sx, 10.3597 * sy) |
||||
|
..cubicTo( |
||||
|
-1.70838 * sx, 17.1589 * sy, |
||||
|
-3.47995 * sx, 44.4301 * sy, |
||||
|
6.60447 * sx, 53.1719 * sy, |
||||
|
) |
||||
|
..cubicTo( |
||||
|
16.0075 * sx, 61.291 * sy, |
||||
|
305.076 * sx, 61.9385 * sy, |
||||
|
323.201 * sx, 53.4956 * sy, |
||||
|
) |
||||
|
..cubicTo( |
||||
|
341.326 * sx, 45.0527 * sy, |
||||
|
332.116 * sx, 8.04571 * sy, |
||||
|
324.829 * sx, 5.7273 * sy, |
||||
|
) |
||||
|
..cubicTo( |
||||
|
307.985 * sx, -2.06805 * sy, |
||||
|
28.6539 * sx, -0.77294 * sy, |
||||
|
9.82057 * sx, 10.3597 * sy, |
||||
|
) |
||||
|
..close(); |
||||
|
|
||||
|
return p; |
||||
|
} |
||||
|
|
||||
|
@override |
||||
|
bool shouldReclip(covariant CustomClipper<Path> oldClipper) => false; |
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue