تصميم صفحة sign in و sign up بإستخدام animation في flutter
ما يميز فلاتر انه تتوفر على الكثير من الشروحات وايضا هيا من ابسط التكنولوجي في البرمجه ومع ذلك فهي قوية جدا وتتميز بقوة في الanimation والمؤثرات وفي مقالة اليوم سوف نقدم لكم تصميم لتسجيل الدخول وتسجيل حساب في التطبيق مع انميشن بسيط للانتقال من صفحة للاخرى كما هو موضح في الصورة الخاصه بالمقالة .
بسم الله الرحمن الرحيم , في هذا الدرس نقوم لكم صفحة signIn و signUp في flutter وعمل انميشن للانتقال من صفحة الى , حيث ان التصميم بالكامل سوف يكون في نفس الصفحة وهذا الدرس من دروس تصاميم في flutter , ويوجد قسم خاص بهذه التصاميم في موقعنا اذا كنت تريد ان تحسن مستواك في التصميم والتعامل مع الwedgets المختلفه فنحن نقدم كل بين كل فتره والاخرى مجموعة تصاميم يمكنك اخذ منها افكار في تطوير تطبيقات الجوال التي تعملها عليها .
تصميم صفحة login
بدلا من كتابة الكود كامل في صفحة واحده قمنا بتقسيمه الى 4 اجزاء , في هذا الجزء يكون الlogin وهو عباره عن مربع نصي ومربع نصي اخر يمكنك استخدامهم في كتابة اسم المستخدم وكلمة المرور وهذا هو التصميم بكل بساطة
login.dart
class LoginForm extends StatelessWidget {
const LoginForm({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.symmetric(
horizontal: MediaQuery.of(context).size.width * 0.13),
child: Form(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Spacer(),
TextFormField(
decoration: InputDecoration(
hintText: "Email",
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 16),
child: TextFormField(
obscureText: true,
decoration: InputDecoration(
hintText: "Password",
),
),
),
TextButton(
onPressed: () {},
child: Text(
"Forgot Password?",
style: TextStyle(color: Colors.white),
),
),
Spacer(flex: 2),
],
),
),
);
}
}
صفحة register
الجزء الثاني وهو تصميم لصفحة تسجيل حساب وهنا وضعنا 3 مربعات نصيه لادخال الاميل وكلمة السر واعادة كلمة السر والمميز انك تسطتيع استخدام هذة الصفحات في اي مكان وتغيير المحتويات التي تريدها منها بكل بساطة وليس فقط مقيده على الاستخدام في مكان واحد .
sign_up_form.dart
class SignUpForm extends StatelessWidget {
const SignUpForm({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.symmetric(
horizontal: MediaQuery.of(context).size.width * 0.13),
child: Form(
child: Column(
children: [
Spacer(),
TextFormField(
decoration: InputDecoration(
hintText: "Email",
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 16),
child: TextFormField(
obscureText: true,
decoration: InputDecoration(
hintText: "Password",
),
),
),
TextFormField(
obscureText: true,
decoration: InputDecoration(
hintText: "Confirm Password",
),
),
Spacer(flex: 2)
],
),
),
);
}
}
صفحة مواقع التواصل الاجتماعي
الجزء الاخير من الصفحات التي قمنا بعملها وهو تصميم لصفحة مواقع التواصل الاجتماعي وهنا قمنا بعمل صفحة تحتوي فقط على ثلاث عناصر وهم مواقع التواصل الاجتماعي يمكنك تغييرها باي عناصر اخرى او تركها في نهايه الامر القرار يرجع لك .
social.dart
class SocalButtns extends StatelessWidget {
const SocalButtns({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(onPressed: () {}, icon: Image.asset("assets/fb.png")),
IconButton(onPressed: () {}, icon: Image.asset("assets/linkedin.png")),
IconButton(onPressed: () {}, icon: Image.asset("assets/twitter.png")),
],
);
}
}
تصميم login و register وعمل انتقال بينهم بشكل جديد
class CodeLess extends StatefulWidget {
CodeLess({Key? key}) : super(key: key);
@override
State<CodeLess> createState() => _CodeLessState();
}
class _CodeLessState extends State<CodeLess> with SingleTickerProviderStateMixin {
bool isShowSignUp = false;
late AnimationController animationController;
late Animation<double> animationTextRotate;
void setUpAnimation() {
animationController = AnimationController(vsync: this , duration:const Duration(milliseconds: 300),);
animationTextRotate = Tween<double>(begin: 0 , end: 90).animate(animationController);
}
@override
void initState() {
setUpAnimation();
super.initState();
}
void updateView(){
setState(() {
isShowSignUp = !isShowSignUp;
});
isShowSignUp ? animationController.forward() : animationController.reverse();
}
@override
void dispose() {
animationController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final size = MediaQuery.of(context).size;
return Scaffold(
body: AnimatedBuilder(
animation: animationController,
builder: (context, snapshot) {
return Stack(
children: [
// login screen
AnimatedPositioned(
duration: Duration(milliseconds: 300),
// width = %88 from screen
width: size.width * 0.88,
height: size.height,
left: isShowSignUp ? -size.width * 0.76 : 0 ,
child: Container(
color: Colors.amber,
child: const LoginForm(),
),
),
// register Screen
AnimatedPositioned(
duration: Duration(milliseconds: 300),
// width = %88 from screen
width: size.width * 0.88,
height: size.height,
left: isShowSignUp ? size.width * 0.12 : size.width * 0.88,
child: GestureDetector(
onTap: (){
},
child: Container(
color: Colors.teal,
child: SignUpForm(),
),
),
),
// logo
AnimatedPositioned(
duration: Duration(milliseconds: 300),
// top = 10% from screen
top: size.height * 0.1,
left: 0,
right: isShowSignUp ? - size.width * 0.06 : size.width * 0.06,
child: CircleAvatar(
backgroundColor: Colors.white38,
radius: 25,
child: isShowSignUp ?
SvgPicture.asset(
"assets/login.svg",
color: Colors.amber,
) :
SvgPicture.asset(
"assets/login.svg",
color: Colors.teal,
),
),
),
// SocialMedia icons
AnimatedPositioned(
duration: Duration(milliseconds: 300),
width: size.width,
bottom: size.height * 0.1,
right: isShowSignUp ? - size.width * 0.06 : size.width * 0.05,
child: SocalButtns()),
//login text
AnimatedPositioned(
duration: const Duration(milliseconds: 300),
bottom: isShowSignUp ? size.height / 2 - 80 : size.height * 0.3,
left: isShowSignUp ? 0 : size.width * 0.44 - 80, // 88 / 2 = 44
child: AnimatedDefaultTextStyle(
duration: const Duration(milliseconds: 300),
textAlign:TextAlign.center,
style:TextStyle(
fontSize: isShowSignUp ? 20 : 32 ,
fontWeight: FontWeight.bold ,
color: isShowSignUp ? Colors.white : Colors.white38),
child: Transform.rotate(
angle: -animationTextRotate.value * pi / 180,
alignment: Alignment.topLeft,
child: InkWell(
onTap:(){
if (isShowSignUp) {
updateView();
} else {
// login
}
},
child: Container(
padding: const EdgeInsets.symmetric(vertical: 16 * 0.75),
width: 160,
child: Text('Login'.toUpperCase(),)),
),
),
)),
// signUp text
AnimatedPositioned(
duration: const Duration(milliseconds: 300),
bottom: !isShowSignUp ? size.height / 2 - 80 : size.height * 0.3,
right: isShowSignUp ? size.width * 0.44 - 80 : 0, // 88 / 2 = 44
child: AnimatedDefaultTextStyle(
duration: const Duration(milliseconds: 300),
textAlign:TextAlign.center,
style:TextStyle(
fontSize: !isShowSignUp ? 20 : 32 ,
fontWeight: FontWeight.bold ,
color: isShowSignUp ? Colors.white38 : Colors.white),
child: Transform.rotate(
angle: (90 - animationTextRotate.value) * pi / 180,
alignment: Alignment.topRight,
child: InkWell(
onTap:(){
if (!isShowSignUp) {
updateView();
}else {
// sign up
}
},
child: Container(
padding: const EdgeInsets.symmetric(vertical: 16 * 0.75),
width: 170,
child: Text('Register'.toUpperCase(),)),
),
),
)),
],
);
}
));
}
}
تغيير الtheme الخاص بالالوان في صفحة main
الجزء الاخير وهو تحسين الالوان والتصميم وذلك سوف ننتقل معكم الى صفحة Main لكي نكمل معكم الكود ونقوم بعمل ثيم مخصص للتصميم الذي نعمل عليه , قد لا تحتاج اليه اذا لم يعجبك التصميم الحالي للعناصر ويمكنك عمل تصميم لكل عنصر كما ترغب الامر متروك لك .
فيديو الشرح
لمزيد من المقالات
- شرح كيفية الحصول على البيانات الاخبار من الapi بإستخدام DIO في Flutter
- شرح إنشاء تطبيق إخباري بأسخدام Apis في flutter بسهوله
- تصميم تطبيق BMI Calcoluter في Flutter مع الكود المصدر
- إضافة الDarkmode الى تطبيقك وحفظ التغيير في shared preferences بإستخدام Flutter
- كيفية حذف بيانات من Database بإستخدام Flutter عن طريق السحب
- نقل البيانات بين مختلف صفحات التطبيق في Flutter