آموزش انیمیشن در برنامه نویسی فلاتر

3 سال پیش

آموزش انیمیشن در برنامه نویسی فلاتر

در این درس از آموزش های برنامه نویسی سایت سورس باران، به آموزش انیمیشن در برنامه نویسی فلاتر خواهیم پرداخت.

انیمیشن یک رویه پیچیده در هر برنامه موبایلی است. علیرغم پیچیدگی، انیمیشن تجربه کاربر را به سطح جدیدی ارتقا می دهد و تعامل غنی کاربر را فراهم می کند. به دلیل غنی بودن، انیمیشن به بخشی جدایی ناپذیر از برنامه های موبایل مدرن تبدیل می شود. فریم ورک فلاتر اهمیت انیمیشن را تشخیص می دهد و یک چارچوب ساده و بصری را برای توسعه انواع انیمیشن ها فراهم می کند.

مقدمه

انیمیشن فرایندی است برای نشان دادن یک سری تصاویر / عکس به ترتیب خاص در مدت زمان خاص برای ایجاد توهم حرکت. مهمترین جنبه های انیمیشن به شرح زیر است –

  • انیمیشن دو مقدار مشخص دارد: مقدار شروع و مقدار پایان. انیمیشن از مقدار Start شروع می شود و از یک سری مقادیر میانی عبور می کند و در نهایت در مقادیر End خاتمه می یابد. به عنوان مثال، برای متحرک کردن ویجت برای محو شدن، مقدار اولیه تار بودن کامل و مقدار نهایی تار بودن صفر خواهد بود.
  • مقادیر میانی ممکن است ماهیت خطی یا غیر خطی (منحنی) داشته و بتوانند پیکربندی شوند. بدانید که انیمیشن همانطور که پیکربندی شده است کار می کند. هر پیکربندی احساس متفاوتی را برای انیمیشن ایجاد می کند. به عنوان مثال، محو کردن یک عنصر ماهیت خطی دارد در حالی که تقابل با توپ ماهیتی غیر خطی دارد.
  • مدت زمان روند انیمیشن بر سرعت (کندی یا سرعت) انیمیشن تأثیر می گذارد.
  • توانایی کنترل روند انیمیشن مانند شروع انیمیشن ، متوقف کردن انیمیشن تکرار انیمیشن برای تنظیم تعداد بار، معکوس کردن روند انیمیشن و غیره ،
  • در برنامه نویسی فلاتر، سیستم انیمیشن هیچ انیمیشن واقعی را انجام نمی دهد. در عوض، فقط مقادیر مورد نیاز در هر فریم برای ارائه تصاویر را فراهم می کند.

 

کلاسهای مبتنی بر انیمیشن

سیستم انیمیشندر برنامه نویسی فلاتر براساس  objects Animation ساخته شده است. کلاسهای اصلی انیمیشن و کاربرد آن به شرح زیر است –

انیمیشن

مقادیر درون یابی شده را برای مدت زمان معینی تولید می کند. رایج ترین کلاس های انیمیشن عبارتند از –

  • <Animation<double مقادیر بین دو عدد اعشاری را درون یابی کنید
  • <Animation<Color – بین دو رنگ از یکدیگر استفاده کنید
  • <Animation <Size – اندازه های بین دو اندازه را درون یابی کنید
  • AnimationController – شی ویژه انیمیشن برای کنترل خود انیمیشن. هر زمان که برنامه برای یک قاب جدید آماده باشد، مقادیر جدیدی ایجاد می کند. از انیمیشن مبتنی بر خط پشتیبانی می کند و مقدار آن از ۰٫۰ تا ۱٫۰ شروع می شود
controller = AnimationController(duration: const Duration(seconds: 2), vsync: this);

 

در اینجا، کنترل کننده انیمیشن را کنترل می کند و گزینه مدت زمان فرایند انیمیشن را کنترل می کند. vsync گزینه ویژه ای است که برای بهینه سازی منابع مورد استفاده در انیمیشن استفاده می شود.

 

CurvedAnimation

مشابه AnimationController اما از انیمیشن غیر خطی پشتیبانی می کند. انیمیشن را می توان به صورت زیر به همراه شی متحرک استفاده کرد –

ontroller = AnimationController(duration: const Duration(seconds: 2), vsync: this); 
animation = CurvedAnimation(parent: controller, curve: Curves.easeIn)

 

Tween<T>

از Animatable <T> گرفته شده و برای تولید اعداد بین هر دو عدد غیر از ۰ و ۱ مورد استفاده قرار می گیرد. می توان آن را همراه با شی Animation با استفاده از متد animate و عبور شی واقعی Animation استفاده کرد.

AnimationController controller = AnimationController( 
   duration: const Duration(milliseconds: 1000), 
vsync: this); Animation<int> customTween = IntTween(
   begin: 0, end: 255).animate(controller);

 

Tween همچنین می تواند همراه با CurvedAnimation به صورت زیر استفاده شود –

AnimationController controller = AnimationController(
   duration: const Duration(milliseconds: 500), vsync: this); 
final Animation curve = CurvedAnimation(parent: controller, curve: Curves.easeOut); 
Animation<int> customTween = IntTween(begin: 0, end: 255).animate(curve);

 

در اینجا، کنترل کننده، کنترل کننده واقعی انیمیشن است. منحنی نوع غیرخطی و customTween دامنه سفارشی از ۰ تا ۲۵۵ را فراهم می کند.

جریان کار انیمیشن  در برنامه نویسی فلاتر

جریان کار انیمیشن به شرح زیر است –

کنترل کننده انیمیشن را در initState از StatefulWidget تعریف و شروع کنید.

AnimationController(duration: const Duration(seconds: 2), vsync: this); 
animation = Tween<double>(begin: 0, end: 300).animate(controller); 
controller.forward();

 

برای تغییر حالت ویجت، انیمیشن مبتنی بر addListener ،listener اضافه کنید.

animation = Tween<double>(begin: 0, end: 300).animate(controller) ..addListener(() {
   setState(() { 
      // The state that has changed here is the animation object’s value. 
   }); 
});

 

برای رد کردن این فرآیند می توان از ویجت های توکار، AnimatedWidget و AnimatedBuilder استفاده کرد. هر دو ویجت شی متحرک را می پذیرد و مقادیر فعلی مورد نیاز انیمیشن را دریافت می کند.

مقادیر انیمیشن را در طی مراحل ساخت ویجت دریافت کنید و سپس آن را برای عرض، ارتفاع یا هر خاصیت مربوطه به جای مقدار اصلی اعمال کنید.

child: Container( 
   height: animation.value, 
   width: animation.value, 
   child: <Widget>, 
)

 

برنامه کاربردی

اجازه دهید برای درک مفهوم انیمیشن در فریم ورک فلاتر، یک برنامه ساده مبتنی بر انیمیشن بنویسیم.

  • یک برنامه فلاتر جدید در Android studio ، product_animation_app ایجاد کنید.
  • پوشه assets را از Product_nav_app به Product_animation_app کپی کرده و assets را در داخل فایل pubspec.yaml اضافه کنید.
flutter: 
   assets: 
   - assets/appimages/floppy.png 
   - assets/appimages/iphone.png 
   - assets/appimages/laptop.png 
   - assets/appimages/pendrive.png 
   - assets/appimages/pixel.png 
   - assets/appimages/tablet.png

 

  • کد راه اندازی پیش فرض را حذف کنید (main.dart).
  • import و تابع اصلی را اضافه کنید.
import 'package:flutter/material.dart'; 
void main() => runApp(MyApp());

 

  • ویجت MyApp مشتق شده از StatefulWidgtet را ایجاد کنید.
class MyApp extends StatefulWidget { 
   _MyAppState createState() => _MyAppState(); 
}

 

  • ویجت _MyAppState را ایجاد کنید و علاوه بر متد ساخت پیش فرض، initState را پیاده سازی و دفع کنید.
class _MyAppState extends State<MyApp> with SingleTickerProviderStateMixin { 
   Animation<double> animation; 
   AnimationController controller; 
   @override void initState() {
      super.initState(); 
      controller = AnimationController(
         duration: const Duration(seconds: 10), vsync: this
      ); 
      animation = Tween<double>(begin: 0.0, end: 1.0).animate(controller); 
      controller.forward(); 
   } 
   // This widget is the root of your application. 
   @override 
   Widget build(BuildContext context) {
      controller.forward(); 
      return MaterialApp(
         title: 'Flutter Demo',
         theme: ThemeData(primarySwatch: Colors.blue,), 
         home: MyHomePage(title: 'Product layout demo home page', animation: animation,)
      ); 
   } 
   @override 
   void dispose() {
      controller.dispose();
      super.dispose();
   }
}

 

  • در متد initState، ما یک شی کنترلر انیمیشن (کنترل کننده)، یک شی انیمیشن ایجاد کرده ایم و انیمیشن را با استفاده از کنترلر آغاز کرده ایم.
  • در متد dispose، ما شی کنترلر انیمیشن (کنترل کننده) را از بین برده ایم.
  • در متد ساخت، انیمیشن را از طریق سازنده به ویجت MyHomePage ارسال کنید. اکنون، ویجت MyHomePage می تواند از شی متحرک برای متحرک سازی محتوای آن استفاده کند.
  • اکنون، ویجت ProductBox را اضافه کنید
class ProductBox extends StatelessWidget {
   ProductBox({Key key, this.name, this.description, this.price, this.image})
      : super(key: key);
   final String name; 
   final String description; 
   final int price; 
   final String image; 
   
   Widget build(BuildContext context) {
      return Container(
         padding: EdgeInsets.all(2), 
         height: 140, 
         child: Card( 
            child: Row( 
               mainAxisAlignment: MainAxisAlignment.spaceEvenly, 
               children: <Widget>[ 
                  Image.asset("assets/appimages/" + image), 
                  Expanded( 
                     child: Container( 
                        padding: EdgeInsets.all(5), 
                        child: Column( 
                           mainAxisAlignment: MainAxisAlignment.spaceEvenly, 
                           children: <Widget>[ 
                              Text(this.name, style: 
                                 TextStyle(fontWeight: FontWeight.bold)), 
                              Text(this.description), 
                                 Text("Price: " + this.price.toString()), 
                           ], 
                        )
                     )
                  )
               ]
            )
         )
      ); 
   }
}

 

یک ویجت جدید ایجاد کنید، MyAnimatedWidget برای انجام محو شدن انیمیشن با استفاده از تار شدن.

class MyAnimatedWidget extends StatelessWidget { 
   MyAnimatedWidget({this.child, this.animation}); 
      
   final Widget child; 
   final Animation<double> animation; 
   
   Widget build(BuildContext context) => Center( 
   child: AnimatedBuilder(
      animation: animation, 
      builder: (context, child) => Container( 
         child: Opacity(opacity: animation.value, child: child), 
      ), 
      child: child), 
   ); 
}

 

در اینجا، ما از AniatedBuilder برای انجام انیمیشن خود استفاده کرده ایم. AnimatedBuilder یک ویجت است که محتوای خود را هنگام ساخت انیمیشن به طور همزمان می سازد. این یک شی انیمیشن را می پذیرد تا مقدار انیمیشن فعلی را دریافت کند. ما برای تنظیم تار بودن ویجت کودک از مقدار انیمیشن، animation.value استفاده کرده ایم. در واقع، ویجت کودک را با استفاده از مفهوم تار شدن متحرک می کند.

در آخر، ویجت MyHomePage را ایجاد کنید و از شی متحرک برای متحرک سازی هر یک از محتوای آن استفاده کنید.

class MyHomePage extends StatelessWidget {
   MyHomePage({Key key, this.title, this.animation}) : super(key: key); 
   
   final String title; 
   final Animation<double> 
   animation; 
   
   @override 
   Widget build(BuildContext context) {
      return Scaffold(
         appBar: AppBar(title: Text("Product Listing")),body: ListView(
            shrinkWrap: true,
            padding: const EdgeInsets.fromLTRB(2.0, 10.0, 2.0, 10.0), 
            children: <Widget>[
               FadeTransition(
                  child: ProductBox(
                     name: "iPhone", 
                     description: "iPhone is the stylist phone ever", 
                     price: 1000, 
                     image: "iphone.png"
                  ), opacity: animation
               ), 
               MyAnimatedWidget(child: ProductBox(
                  name: "Pixel", 
                  description: "Pixel is the most featureful phone ever", 
                  price: 800, 
                  image: "pixel.png"
               ), animation: animation), 
               ProductBox(
                  name: "Laptop", 
                  description: "Laptop is most productive development tool", 
                  price: 2000, 
                  image: "laptop.png"
               ), 
               ProductBox(
                  name: "Tablet", 
                  description: "Tablet is the most useful device ever for meeting", 
                  price: 1500, 
                  image: "tablet.png"
               ), 
               ProductBox(
                  name: "Pendrive", 
                  description: "Pendrive is useful storage medium", 
                  price: 100, 
                  image: "pendrive.png"
               ),
               ProductBox(
                  name: "Floppy Drive", 
                  description: "Floppy drive is useful rescue storage medium", 
                  price: 20, 
                  image: "floppy.png"
               ),
            ],
         )
      );
   }
}

 

در اینجا، از FadeAnimation و MyAnimationWidget برای متحرک سازی دو مورد اول در لیست استفاده کرده ایم. FadeAnimation یک کلاس ساخت انیمیشن است که ما با استفاده از مفهوم opacity کودک خود را متحرک سازی کردیم.

کد کامل به شرح زیر است –

import 'package:flutter/material.dart'; 
void main() => runApp(MyApp()); 

class MyApp extends StatefulWidget { 
   _MyAppState createState() => _MyAppState(); 
} 
class _MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {
   Animation<double> animation; 
   AnimationController controller; 
   
   @override 
   void initState() {
      super.initState(); 
      controller = AnimationController(
         duration: const Duration(seconds: 10), vsync: this); 
      animation = Tween<double>(begin: 0.0, end: 1.0).animate(controller); 
      controller.forward(); 
   } 
   // This widget is the root of your application. 
   @override 
   Widget build(BuildContext context) {
      controller.forward(); 
      return MaterialApp( 
         title: 'Flutter Demo', theme: ThemeData(primarySwatch: Colors.blue,), 
         home: MyHomePage(title: 'Product layout demo home page', animation: animation,) 
      ); 
   } 
   @override 
   void dispose() {
      controller.dispose();
      super.dispose(); 
   } 
}
class MyHomePage extends StatelessWidget { 
   MyHomePage({Key key, this.title, this.animation}): super(key: key);
   final String title; 
   final Animation<double> animation; 
   
   @override 
   Widget build(BuildContext context) {
      return Scaffold(
         appBar: AppBar(title: Text("Product Listing")), 
         body: ListView(
            shrinkWrap: true, 
            padding: const EdgeInsets.fromLTRB(2.0, 10.0, 2.0, 10.0), 
            children: <Widget>[
               FadeTransition(
                  child: ProductBox(
                     name: "iPhone", 
                     description: "iPhone is the stylist phone ever", 
                     price: 1000, 
                     image: "iphone.png"
                  ), 
                  opacity: animation
               ), 
               MyAnimatedWidget(
                  child: ProductBox( 
                     name: "Pixel", 
                     description: "Pixel is the most featureful phone ever", 
                     price: 800, 
                     image: "pixel.png"
                  ), 
                  animation: animation
               ), 
               ProductBox( 
                  name: "Laptop", 
                  description: "Laptop is most productive development tool", 
                  price: 2000, 
                  image: "laptop.png"
               ), 
               ProductBox(
                  name: "Tablet",
                  description: "Tablet is the most useful device ever for meeting",
                  price: 1500, 
                  image: "tablet.png"
               ), 
               ProductBox(
                  name: "Pendrive", 
                  description: "Pendrive is useful storage medium", 
                  price: 100, 
                  image: "pendrive.png"
               ), 
               ProductBox(
                  name: "Floppy Drive", 
                  description: "Floppy drive is useful rescue storage medium", 
                  price: 20, 
                  image: "floppy.png"
               ), 
            ], 
         )
      ); 
   } 
} 
class ProductBox extends StatelessWidget { 
   ProductBox({Key key, this.name, this.description, this.price, this.image}) :
      super(key: key);
   final String name; 
   final String description; 
   final int price; 
   final String image; 
   Widget build(BuildContext context) {
      return Container(
         padding: EdgeInsets.all(2), 
         height: 140, 
         child: Card(
            child: Row(
               mainAxisAlignment: MainAxisAlignment.spaceEvenly, 
               children: <Widget>[ 
                  Image.asset("assets/appimages/" + image), 
                  Expanded(
                     child: Container( 
                        padding: EdgeInsets.all(5), 
                        child: Column( 
                           mainAxisAlignment: MainAxisAlignment.spaceEvenly, 
                           children: <Widget>[ 
                              Text(
                                 this.name, style: TextStyle(
                                    fontWeight: FontWeight.bold
                                 )
                              ), 
                              Text(this.description), Text(
                                 "Price: " + this.price.toString()
                              ), 
                           ], 
                        )
                     )
                  ) 
               ]
            )
         )
      ); 
   } 
}
class MyAnimatedWidget extends StatelessWidget { 
   MyAnimatedWidget({this.child, this.animation}); 
   final Widget child; 
   final Animation<double> animation; 
 
   Widget build(BuildContext context) => Center( 
      child: AnimatedBuilder(
         animation: animation, 
         builder: (context, child) => Container( 
            child: Opacity(opacity: animation.value, child: child), 
         ), 
         child: child
      ), 
   ); 
}

برای دیدن نتایج، برنامه را کامپایل و اجرا کنید. نسخه اولیه و نهایی برنامه به شرح زیر است

Initial Version

Final Version

منبع.

لیست جلسات قبل آموزش برنامه نویسی فلاتر

  1. معرفی برنامه نویسی فلاتر
  2. آموزش نصب فلاتر
  3. اصول ایجاد یک برنامه فلاتر در Android Studio
  4. معماری فریم ورک برنامه نویسی فلاتر
  5. مقدمه ای بر برنامه نویسی دارت
  6. مقدمه ای بر ویجت ها در برنامه نویسی فلاتر
  7. آموزش طرح بندی در برنامه نویسی فلاتر 
  8. ژست های حرکتی در برنامه نویسی فلاتر 
  9. مدیریت State در برنامه نویسی فلاتر
0
برچسب ها :
نویسنده مطلب erfan molaei

دیدگاه شما

بدون دیدگاه