الگوی صفحه چینی فرم لاگین

تعداد بازدید ها : 1,694 بازدید
 الگوی صفحه چینی فرم لاگین

جهت صفحه چینی فرم های اپلیکیشن ، شما راه حل های زیادی را پیش روی خود دارید . در این مطلب یک روش ساخت یافته و اصولی جهت صفحه چینی فرم لاگین خدمت شما ارائه می دهم .جهت این منظور من از ویجت های Container ، ویجت Stack ، ویجت Column ، ویجت Form و ویجت TextFormField به ترتیبی که در تصویر زیر قابل مشاهده است ، استفاده کرده ام .

LoginForm_Layoutدر این پروژه از انیمیشن ها ، قابلیت ذخیره در Shared Preferences و اتصال به سرور استفاده شده است . جهت ایجاد این پروژه ، ابتدا یک پروژه جدید ایجاد نمایید ، سپس فایل های زیر را ایجاد و کدهای هر فایل را در آن کپی نمایید . حال پروژه را اجرا و خروجی را مشاهده نمایید .

کدهای مربوط به فایل اصلی صفحه لاگین ( فایلی به نام LoginUser.dart ) :

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:whatsapp_roocket/WebServices/Auth_Service.dart';
import 'package:whatsapp_roocket/animations/SingIn_animation.dart';
import 'package:whatsapp_roocket/components/FormContainer.dart' as form;

class LoginUser extends StatefulWidget {
  @override
  _LoginUserState createState() => _LoginUserState();
}

class _LoginUserState extends State<LoginUser>
    with SingleTickerProviderStateMixin {
  AnimationController _loginButtonController;

  final formKey = GlobalKey<FormState>(); // کلید فرم ورود
  final scaffoldKey = GlobalKey<ScaffoldState>(); // کلید اسکفولد

  var _emailValue;
  var _passwordValue;

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    _loginButtonController = AnimationController(
        vsync: this, duration: Duration(milliseconds: 3000));
  }

  @override
  void dispose() {
    // TODO: implement dispose
    _loginButtonController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final sizeScreen = MediaQuery.of(context).size;

    return Scaffold(
      key: scaffoldKey,
      resizeToAvoidBottomPadding: false,
      body: Container(
        //width: sizeScreen.width,
        //height: sizeScreen.height,
        decoration: BoxDecoration(
          gradient: LinearGradient(colors: <Color>[
            Color(0xFF456c7d),
            Color(0xFF113746),
          ], begin: Alignment.topCenter, end: Alignment.bottomCenter),
        ),
        child: Stack(
          alignment: Alignment.bottomCenter,
          children: <Widget>[
            Opacity(
              opacity: 0.1,
              child: Container(
                width: sizeScreen.width,
                height: sizeScreen.height,
                decoration: BoxDecoration(
                  image: DecorationImage(
                    image: NetworkImage(
                        'https://javareshkian.ir/wp-content/uploads/2020/04/icon-background.png'),
                    repeat: ImageRepeat.repeat,
                  ),
                ),
              ),
            ),
            Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Padding(
                  padding: const EdgeInsets.only(bottom: 70),
                  child: Image(
                    width: 100,
                    height: 100,
                    image: NetworkImage(
                        'https://javareshkian.ir/wp-content/uploads/2020/03/javareshkian4.png'),
                  ),
                ),
                form.FormContainer(
                  formKey: formKey,
                  emailOnSaved: (String value) {
                    _emailValue = value;
                    //print(_emailValue);
                  },
                  passwordOnSaved: (String value) {
                    _passwordValue = value;
                  },
                ),
                FlatButton(
                  onPressed: null,
                  child: Text(
                    'حساب کاربری ندارید ؟!  ثبت نام',
                    style: TextStyle(
                        color: Colors.white70,
                        fontWeight: FontWeight.w300,
                        letterSpacing: 1.5),
                  ),
                )
              ],
            ),
            GestureDetector(
                onTap: () async {
                  if (formKey.currentState.validate()) {
                    formKey.currentState.save();
                    await checkUserForServer();
                  }
                },
                child: SingInAnimation(
                  controller: _loginButtonController.view,
                  sizeWidthScreen: sizeScreen.width,
                ))
          ],
        ),
      ),
    );
  }

  checkUserForServer() async {
    await _loginButtonController.animateTo(0.350);
    var response = await (new AuthService())
        .checkLoginUser({'email': _emailValue, 'password': _passwordValue});
    if (response['status'] == 'success') {
      // ذخیره اطلاعات در شیردرفرنسز
      await storeUserData(response['data']);

      await _loginButtonController.forward();
      Navigator.pushReplacementNamed(context, '/');
    } else {
      await _loginButtonController.reverse();
      scaffoldKey.currentState.showSnackBar(new SnackBar(
          content: Text(
        response['data'],
        style: TextStyle(fontFamily: 'Vazir'),
      )));
    }
  }

  // تابع ذخیره اطلاعات در شیردرفرنسز
  storeUserData(Map userData) async {
    SharedPreferences sharedUserData = await SharedPreferences.getInstance();
    sharedUserData.setString('user.api_token', userData['api_token']);
    sharedUserData.setInt('user.user_id', userData['user_id']);
  }
}

کدهای مربوط به فایل FormContainer.dart :

import 'package:flutter/material.dart';
import 'package:whatsapp_roocket/components/InputFieldArea.dart';
import 'package:validators/validators.dart' as validDart;

class FormContainer extends StatelessWidget {
  final formKey;
  final emailOnSaved;
  final passwordOnSaved;

  FormContainer(
      {@required this.formKey,
      @required this.emailOnSaved,
      @required this.passwordOnSaved,
      });

  @override
  Widget build(BuildContext context) {
    return Container(
      margin: EdgeInsets.symmetric(horizontal: 50),
      child: Form(
        key: formKey,
        child: Column(
          children: <Widget>[
            new InputFieldArea(
              obscureText: false,
              hintText: 'ایمیل نام کاربری خود را وارد نمایید',
              hintFontSize: 15,
              hintColorText: Colors.grey[500],
              textColor: Colors.white,
              textFontSize: 15,
              iconInput: Icons.person_outline,
              iconColor: Colors.white,
              textValidator: null,
              // ignore: missing_return
              validate: (String value) {
                print('value : $value');
                print('contains : ${value.contains('@') && value.contains('.')}');
                if (value.contains('@') && value.contains('.')) {
                }else
                  return 'نام کاربری نامعتبر است !';
              },
              onSaved: emailOnSaved,
            ),
            new InputFieldArea(
              obscureText: true,
              hintText: 'رمز ورود خود را وارد نمایید',
              hintFontSize: 15,
              hintColorText: Colors.grey[500],
              textColor: Colors.white,
              textFontSize: 15,
              iconInput: Icons.lock_outline,
              iconColor: Colors.white,
              textValidator: null,
              // ignore: missing_return
              validate: (String value) {
                if (value.length < 6) {
                  return 'طول کلمه عبور باید حداقل ۶ کاراکتر باشد .';
                }
              },
              onSaved: passwordOnSaved,
            ),
          ],
        ),
      ),
    );
  }
}

کدهای مربوط به فایل InputFieldArea.dart :

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

class InputFieldArea extends StatelessWidget {
  final bool obscureText;
  final String hintText;
  final double hintFontSize;
  final Color hintColorText;
  final Color textColor;
  final double textFontSize;
  final IconData iconInput;
  final Color iconColor;
  final textValidator;
  final validate;
  final onSaved;

  InputFieldArea(
      {@required this.obscureText,
      @required this.hintText,
      @required this.hintFontSize,
      @required this.hintColorText,
      @required this.textColor,
      @required this.textFontSize,
      @required this.iconInput,
      @required this.iconColor,
      @required this.textValidator,
      @required this.validate,
      @required this.onSaved,
      });

  @override
  Widget build(BuildContext context) {
    return Container(
        margin: EdgeInsets.only(bottom: 10),
        child: TextFormField(
          // ignore: missing_return
          validator: validate,
          onSaved: onSaved,
          obscureText: obscureText,
          textAlign: TextAlign.center,
          style: TextStyle(color: textColor, fontSize: textFontSize,),
          decoration: InputDecoration(
              icon: Icon(
                iconInput,
                color: iconColor,
              ),
              hintText: hintText,
              hintStyle:
                  TextStyle(color: hintColorText, fontSize: hintFontSize),
              contentPadding: EdgeInsets.symmetric(vertical: 15, horizontal: 5),
              enabledBorder: UnderlineInputBorder(
                borderSide: BorderSide(color: Colors.white30),
              ),
            focusedBorder: UnderlineInputBorder(
              borderSide: BorderSide(color: Colors.white),
            ),
            errorBorder: UnderlineInputBorder(
              borderSide: BorderSide(color: Colors.yellow),
            ),
            focusedErrorBorder: UnderlineInputBorder(
              borderSide: BorderSide(color: Colors.yellow),
            ),
            errorStyle: TextStyle(color: Colors.yellow, fontSize: 12)
          ),
        ));
  }
}

class MyText extends StatelessWidget {
  final onSaveValue;

  MyText({this.onSaveValue});

  @override
  Widget build(BuildContext context) {
    return TextFormField(
      onSaved: onSaveValue,
    );
  }
}

کدهای مربوط به فایل SingIn_animation.dart :

import 'package:flutter/material.dart';

class SingInAnimation extends StatelessWidget {
  final Animation<double> controller;
  final Animation<double> buttonSizeReduction; // انیمیشن کاهش سایز دکمه
  final Animation<double> buttonFullScreen; // انیمیشن تمام صفحه شدن دکمه
  final double sizeWidthScreen;

  SingInAnimation({this.controller, this.sizeWidthScreen})
      : buttonSizeReduction =
            Tween(begin: (sizeWidthScreen * 60) / 100, end: 60.0).animate(
                CurvedAnimation(
                    parent: controller,
                    curve: Interval(0.0, 0.350, curve: Curves.bounceOut))),
        buttonFullScreen = Tween(begin: 70.0, end: 1000.0).animate(
            CurvedAnimation(
                parent: controller,
                curve: Interval(0.700, 0.950, curve: Curves.easeOutSine)));

  Widget _animationBuilder(BuildContext context, Widget child) {
    return buttonFullScreen.value <= 300
        ? Container(
            margin: buttonFullScreen.value == 70
                ? EdgeInsets.only(bottom: 30)
                : buttonFullScreen.value <= 100
                    ? EdgeInsets.only(bottom: 20)
                    : buttonFullScreen.value <= 200
                        ? EdgeInsets.only(bottom: 10)
                        : EdgeInsets.only(bottom: 0),
            width: buttonFullScreen.value == 70.0
                ? buttonSizeReduction.value
                : buttonFullScreen.value,
            height:
                buttonFullScreen.value == 70.0 ? 60.0 : buttonFullScreen.value,
            alignment: Alignment.center,
            child: buttonSizeReduction.value >= 120
                ? Text(
                    'ورود',
                    style: TextStyle(
                      color: Colors.white,
                      fontSize: 20,
                      fontWeight: FontWeight.w300,
                    ),
                  )
                : buttonFullScreen.value <= 120
                    ? CircularProgressIndicator(
                        backgroundColor: Colors.white,
                      )
                    : null,
            decoration: BoxDecoration(
              color: Color(0xff2258a6),
//              borderRadius: BorderRadius.circular(30),
              borderRadius: buttonFullScreen.value <= 200
                  ? BorderRadius.circular(30)
                  : null,
            ),
          )
        : Container(
            width: buttonFullScreen.value,
            height: buttonFullScreen.value,
            decoration: BoxDecoration(
              shape: BoxShape.rectangle,
              color: Color(0xff2258a6),
            ),
          );
  }

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: controller,
      builder: _animationBuilder,
    );
  }
}

کدهای مربوط به فایل Auth_Service.dart :

import 'package:http/http.dart' as http;
import 'dart:convert';
import 'dart:async';

class AuthService {
  // تابع بررسی اطلاعات کاربری با سرور
  Future<Map> checkLoginUser(Map bodyValue) async {
    http.Response response = await http.post(
      'http://roocket.org/api/login',
      //headers: {"Content-Type": "application/json"},
      encoding: Encoding.getByName('utf-8'),
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/x-www-form-urlencoded'
      },
      body: bodyValue,
    );
    var userValue = json.decode(utf8.decode(response.bodyBytes));
    return userValue;
  }
  
  static Future<bool> checkApiToken(String userToken) async{
    http.Response response = await http.get('http://roocket.org/api/user?api_token=$userToken', headers: {'Accept' : 'aplication/json'});
    print((response.statusCode));
    return response.statusCode == 200;
  }
}

خروجی کدهای فوق به شکل زیر است :

می خوانم   کلاس BoxDecoration

LoginForm_Layoutامیدوارم این مطلب برای شما مفید باشد .

4+
محمدمجتبی جوارشکیان

محمدمجتبی جوارشکیان

من محمدمجتبی جوارشکیان ، کارشناس IT و فعال اجتماعی هستم و در حوزه معماری ، طراحی ، تحلیل گری ، مدلسازی و توسعه ی محیط های نرم افزاری فعالیت دارم . بسیار خوشحال می شوم من را از انتقادات ، پیشنهادات و نظرات خود مطلع فرمایید . آدرس ایمیل : info@javareshkian.ir

ارسال یک پاسخ

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

چهار + یک =