1. ভূমিকা
অ্যানিমেশনগুলি আপনার অ্যাপের ব্যবহারকারীর অভিজ্ঞতা উন্নত করার, ব্যবহারকারীর কাছে গুরুত্বপূর্ণ তথ্য যোগাযোগ করার এবং আপনার অ্যাপটিকে আরও সুন্দর এবং ব্যবহার করার জন্য উপভোগ্য করে তোলার একটি দুর্দান্ত উপায়৷
ফ্লটারের অ্যানিমেশন ফ্রেমওয়ার্কের ওভারভিউ
ফ্লটার প্রতিটি ফ্রেমে উইজেট গাছের একটি অংশ পুনঃনির্মাণ করে অ্যানিমেশন প্রভাব প্রদর্শন করে। এটি অ্যানিমেশন তৈরি এবং রচনা করা সহজ করতে পূর্ব-নির্মিত অ্যানিমেশন প্রভাব এবং অন্যান্য API প্রদান করে।
- অন্তর্নিহিত অ্যানিমেশনগুলি পূর্ব-নির্মিত অ্যানিমেশন প্রভাব যা সম্পূর্ণ অ্যানিমেশন স্বয়ংক্রিয়ভাবে চালায়। যখন অ্যানিমেশনের লক্ষ্য মান পরিবর্তিত হয়, তখন এটি বর্তমান মান থেকে লক্ষ্য মান পর্যন্ত অ্যানিমেশন চালায় এবং এর মধ্যে প্রতিটি মান প্রদর্শন করে যাতে উইজেটটি মসৃণভাবে অ্যানিমেট হয়। অন্তর্নিহিত অ্যানিমেশনের উদাহরণগুলির মধ্যে রয়েছে
AnimatedSize
,AnimatedScale
এবংAnimatedPositioned
। - স্পষ্ট অ্যানিমেশনগুলিও পূর্ব-নির্মিত অ্যানিমেশন প্রভাব, তবে কাজ করার জন্য একটি
Animation
অবজেক্ট প্রয়োজন। উদাহরণগুলির মধ্যে রয়েছেSizeTransition
,ScaleTransition
বাPositionedTransition
। - অ্যানিমেশন হল একটি শ্রেণী যা একটি চলমান বা থামানো অ্যানিমেশনকে উপস্থাপন করে, এবং অ্যানিমেশনটি যে লক্ষ্য মানটি চালাচ্ছে তা প্রতিনিধিত্ব করে এবং স্থিতি , যা অ্যানিমেশন যে কোনো নির্দিষ্ট সময়ে স্ক্রিনে প্রদর্শিত বর্তমান মানকে উপস্থাপন করে। এটি
Listenable
এর একটি সাবক্লাস, এবং অ্যানিমেশন চলাকালীন অবস্থার পরিবর্তন হলে এর শ্রোতাদের অবহিত করে। - AnimationController হল একটি অ্যানিমেশন তৈরি করার এবং এর অবস্থা নিয়ন্ত্রণ করার একটি উপায়। এটির পদ্ধতি যেমন
forward()
,reset()
,stop()
, এবংrepeat()
অ্যানিমেশন নিয়ন্ত্রণ করতে ব্যবহার করা যেতে পারে অ্যানিমেশন প্রভাবকে সংজ্ঞায়িত করার প্রয়োজন ছাড়াই, যেমন স্কেল, আকার বা অবস্থান। - Tweens একটি প্রারম্ভিক এবং শেষ মানের মধ্যে মানগুলিকে ইন্টারপোলেট করতে ব্যবহৃত হয় এবং যেকোন প্রকারের প্রতিনিধিত্ব করতে পারে, যেমন একটি ডবল,
Offset
বাColor
। - সময়ের সাথে সাথে একটি প্যারামিটারের পরিবর্তনের হার সামঞ্জস্য করতে কার্ভ ব্যবহার করা হয়। যখন একটি অ্যানিমেশন চলে, তখন অ্যানিমেশনের শুরুতে বা শেষে পরিবর্তনের হার দ্রুত বা ধীর করার জন্য একটি সহজ বক্ররেখা প্রয়োগ করা সাধারণ। কার্ভগুলি 0.0 এবং 1.0 এর মধ্যে একটি ইনপুট মান নেয় এবং 0.0 এবং 1.0 এর মধ্যে একটি আউটপুট মান প্রদান করে।
আপনি কি নির্মাণ করবেন
এই কোডল্যাবে, আপনি একটি বহু-পছন্দের কুইজ গেম তৈরি করতে যাচ্ছেন যা বিভিন্ন অ্যানিমেশন প্রভাব এবং কৌশল বৈশিষ্ট্যযুক্ত।
আপনি দেখতে পাবেন কিভাবে...
- একটি উইজেট তৈরি করুন যা এর আকার এবং রঙকে অ্যানিমেট করে
- একটি 3D কার্ড ফ্লিপ প্রভাব তৈরি করুন
- অ্যানিমেশন প্যাকেজ থেকে অভিনব প্রাক-নির্মিত অ্যানিমেশন প্রভাব ব্যবহার করুন
- Android এর সর্বশেষ সংস্করণে উপলব্ধ ভবিষ্যদ্বাণীমূলক ব্যাক জেসচার সমর্থন যোগ করুন
আপনি কি শিখবেন
এই কোডল্যাবে আপনি শিখবেন:
- প্রচুর কোডের প্রয়োজন ছাড়াই দুর্দান্ত চেহারার অ্যানিমেশনগুলি অর্জন করতে কীভাবে অন্তর্নিহিতভাবে অ্যানিমেটেড প্রভাবগুলি ব্যবহার করবেন।
-
AnimatedSwitcher
বাAnimationController
মতো প্রাক-নির্মিত অ্যানিমেটেড উইজেটগুলি ব্যবহার করে আপনার নিজের প্রভাবগুলি কনফিগার করতে কীভাবে স্পষ্টভাবে অ্যানিমেটেড প্রভাবগুলি ব্যবহার করবেন। - আপনার নিজস্ব উইজেট সংজ্ঞায়িত করতে
AnimationController
কীভাবে ব্যবহার করবেন যা একটি 3D প্রভাব প্রদর্শন করে। - ন্যূনতম সেটআপ সহ অভিনব অ্যানিমেশন প্রভাবগুলি প্রদর্শন করতে
animations
প্যাকেজটি কীভাবে ব্যবহার করবেন।
আপনি কি প্রয়োজন হবে
- ফ্লাটার SDK
- একটি IDE, যেমন VSCode বা Android Studio/IntelliJ
2. আপনার ফ্লটার ডেভেলপমেন্ট এনভায়রনমেন্ট সেট আপ করুন
এই ল্যাবটি সম্পূর্ণ করতে আপনার দুটি টুকরো সফ্টওয়্যার প্রয়োজন — ফ্লাটার SDK এবং একটি সম্পাদক ৷
আপনি এই ডিভাইসগুলির যেকোনো একটি ব্যবহার করে কোডল্যাব চালাতে পারেন:
- একটি ফিজিক্যাল অ্যান্ড্রয়েড ( 7 ধাপে ভবিষ্যদ্বাণী বাস্তবায়নের জন্য প্রস্তাবিত ) বা iOS ডিভাইস আপনার কম্পিউটারের সাথে সংযুক্ত এবং ডেভেলপার মোডে সেট করা আছে।
- আইওএস সিমুলেটর (এক্সকোড সরঞ্জাম ইনস্টল করা প্রয়োজন)।
- অ্যান্ড্রয়েড এমুলেটর (অ্যান্ড্রয়েড স্টুডিওতে সেটআপ প্রয়োজন)।
- একটি ব্রাউজার (ডিবাগিংয়ের জন্য Chrome প্রয়োজন)।
- একটি উইন্ডোজ , লিনাক্স , বা ম্যাকোস ডেস্কটপ কম্পিউটার। আপনি যে প্ল্যাটফর্মে স্থাপন করার পরিকল্পনা করছেন সেখানে আপনাকে অবশ্যই বিকাশ করতে হবে। সুতরাং, আপনি যদি একটি উইন্ডোজ ডেস্কটপ অ্যাপ বিকাশ করতে চান, তাহলে যথাযথ বিল্ড চেইন অ্যাক্সেস করতে আপনাকে অবশ্যই উইন্ডোজে বিকাশ করতে হবে। অপারেটিং সিস্টেম-নির্দিষ্ট প্রয়োজনীয়তা রয়েছে যা docs.flutter.dev/desktop- এ বিস্তারিতভাবে কভার করা হয়েছে।
আপনার ইনস্টলেশন যাচাই করুন
আপনার ফ্লাটার SDK সঠিকভাবে কনফিগার করা হয়েছে কিনা যাচাই করতে এবং উপরের লক্ষ্য প্ল্যাটফর্মগুলির মধ্যে অন্তত একটি ইনস্টল করা আছে, Flutter Doctor টুলটি ব্যবহার করুন:
$ flutter doctor Doctor summary (to see all details, run flutter doctor -v): [✓] Flutter (Channel stable, 3.24.2, on macOS 14.6.1 23G93 darwin-arm64, locale en) [✓] Android toolchain - develop for Android devices [✓] Xcode - develop for iOS and macOS [✓] Chrome - develop for the web [✓] Android Studio [✓] IntelliJ IDEA Ultimate Edition [✓] VS Code [✓] Connected device (4 available) [✓] Network resources • No issues found!
3. স্টার্টার অ্যাপ চালান
স্টার্টার অ্যাপটি ডাউনলোড করুন
GitHub-এ ফ্লাটার/স্যাম্পল রিপোজিটরি থেকে স্টার্ট অ্যাপ ক্লোন করতে git
ব্যবহার করুন।
$ git clone https://github.com/flutter/codelabs.git $ cd codelabs/animations/step_01/
বিকল্পভাবে, আপনি একটি .zip ফাইল হিসাবে সোর্স কোড ডাউনলোড করতে পারেন।
অ্যাপটি চালান
অ্যাপটি চালানোর জন্য, flutter run
কমান্ডটি ব্যবহার করুন এবং একটি টার্গেট ডিভাইস নির্দিষ্ট করুন, যেমন android
, ios
বা chrome
। সমর্থিত প্ল্যাটফর্মের সম্পূর্ণ তালিকার জন্য, সমর্থিত প্ল্যাটফর্ম পৃষ্ঠাটি দেখুন।
$ flutter run -d android
এছাড়াও আপনি আপনার পছন্দের IDE ব্যবহার করে অ্যাপটি চালাতে এবং ডিবাগ করতে পারেন। আরও তথ্যের জন্য অফিসিয়াল ফ্লটার ডকুমেন্টেশন দেখুন।
কোড ঘুরে দেখুন
স্টার্টার অ্যাপ হল একটি মাল্টিপল-চয়েস কুইজ গেম যা মডেল-ভিউ-ভিউ-মডেল বা MVVM ডিজাইন প্যাটার্ন অনুসরণ করে দুটি স্ক্রীন নিয়ে গঠিত। QuestionBank
(মডেল) ক্লাস থেকে ব্যবহারকারীকে একাধিক পছন্দের প্রশ্ন জিজ্ঞাসা করতে QuestionScreen
(View) QuizViewModel
(View-Model) ক্লাস ব্যবহার করে।
- home_screen.dart - একটি নতুন গেম বোতাম সহ একটি স্ক্রীন প্রদর্শন করে
- main.dart - উপাদান 3 ব্যবহার করতে এবং হোম স্ক্রীন দেখানোর জন্য
MaterialApp
কনফিগার করে - model.dart - অ্যাপ জুড়ে ব্যবহৃত মূল ক্লাসগুলিকে সংজ্ঞায়িত করে৷
- question_screen.dart - কুইজ গেমের জন্য UI প্রদর্শন করে
- view_model.dart -
QuestionScreen
দ্বারা প্রদর্শিত কুইজ গেমের জন্য রাজ্য এবং যুক্তি সংরক্ষণ করে
অ্যাপটি এখনও কোনো অ্যানিমেটেড প্রভাব সমর্থন করে না, ব্যবহারকারী যখন নতুন গেম বোতাম টিপে তখন Flutter's Navigator
ক্লাস দ্বারা প্রদর্শিত ডিফল্ট ভিউ ট্রানজিশন ব্যতীত।
4. অন্তর্নিহিত অ্যানিমেশন প্রভাব ব্যবহার করুন
অন্তর্নিহিত অ্যানিমেশনগুলি অনেক পরিস্থিতিতে একটি দুর্দান্ত পছন্দ, কারণ তাদের কোনও বিশেষ কনফিগারেশনের প্রয়োজন হয় না। এই বিভাগে, আপনি StatusBar
উইজেট আপডেট করবেন যাতে এটি একটি অ্যানিমেটেড স্কোরবোর্ড প্রদর্শন করে। সাধারণ অন্তর্নিহিত অ্যানিমেশন প্রভাবগুলি খুঁজে পেতে, ImplicitlyAnimatedWidget API ডকুমেন্টেশন ব্রাউজ করুন।
আননিমেটেড স্কোরবোর্ড উইজেট তৈরি করুন
নিম্নলিখিত কোড সহ lib/scoreboard.dart
একটি নতুন ফাইল তৈরি করুন:
lib/scoreboard.dart
import 'package:flutter/material.dart';
class Scoreboard extends StatelessWidget {
final int score;
final int totalQuestions;
const Scoreboard({
super.key,
required this.score,
required this.totalQuestions,
});
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
for (var i = 0; i < totalQuestions; i++)
Icon(
Icons.star,
size: 50,
color:
score < i + 1 ? Colors.grey.shade400 : Colors.yellow.shade700,
)
],
),
);
}
}
তারপরে StatusBar
উইজেটের বাচ্চাদের মধ্যে Scoreboard
উইজেট যোগ করুন, Text
উইজেটগুলি প্রতিস্থাপন করুন যা পূর্বে স্কোর এবং মোট প্রশ্ন সংখ্যা দেখিয়েছিল। আপনার সম্পাদককে স্বয়ংক্রিয়ভাবে ফাইলের শীর্ষে প্রয়োজনীয় import "scoreboard.dart"
যোগ করা উচিত।
lib/question_screen.dart
class StatusBar extends StatelessWidget {
final QuizViewModel viewModel;
const StatusBar({required this.viewModel, super.key});
@override
Widget build(BuildContext context) {
return Card(
elevation: 4,
child: Padding(
padding: EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Scoreboard( // NEW
score: viewModel.score, // NEW
totalQuestions: viewModel.totalQuestions, // NEW
),
],
),
),
);
}
}
এই উইজেট প্রতিটি প্রশ্নের জন্য একটি তারকা আইকন প্রদর্শন করে। যখন একটি প্রশ্নের সঠিক উত্তর দেওয়া হয়, তখন অন্য একটি তারকা তাৎক্ষণিকভাবে কোনো অ্যানিমেশন ছাড়াই জ্বলে ওঠে। নিম্নলিখিত ধাপে, আপনি ব্যবহারকারীকে জানাতে সাহায্য করবেন যে তাদের স্কোর এর আকার এবং রঙ অ্যানিমেট করে পরিবর্তিত হয়েছে।
একটি অন্তর্নিহিত অ্যানিমেশন প্রভাব ব্যবহার করুন
AnimatedStar
নামে একটি নতুন উইজেট তৈরি করুন যা স্টার সক্রিয় হয়ে গেলে scale
পরিমাণ 0.5
থেকে 1.0
পরিবর্তন করতে একটি AnimatedScale
উইজেট ব্যবহার করে:
lib/scoreboard.dart
import 'package:flutter/material.dart';
class Scoreboard extends StatelessWidget {
final int score;
final int totalQuestions;
const Scoreboard({
super.key,
required this.score,
required this.totalQuestions,
});
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
for (var i = 0; i < totalQuestions; i++)
AnimatedStar( // NEW
isActive: score > i, // NEW
) // NEW
],
),
);
}
}
class AnimatedStar extends StatelessWidget { // Add from here...
final bool isActive;
final Duration _duration = const Duration(milliseconds: 1000);
final Color _deactivatedColor = Colors.grey.shade400;
final Color _activatedColor = Colors.yellow.shade700;
AnimatedStar({super.key, required this.isActive});
@override
Widget build(BuildContext context) {
return AnimatedScale(
scale: isActive ? 1.0 : 0.5,
duration: _duration,
child: Icon(
Icons.star,
size: 50,
color: isActive ? _activatedColor : _deactivatedColor,
),
);
}
} // To here.
এখন, যখন ব্যবহারকারী একটি প্রশ্নের সঠিক উত্তর দেয়, তখন AnimatedStar
উইজেট একটি অন্তর্নিহিত অ্যানিমেশন ব্যবহার করে তার আকার আপডেট করে। Icon
color
এখানে অ্যানিমেটেড নয়, শুধুমাত্র scale
, যা AnimatedScale
উইজেট দ্বারা করা হয়।
দুটি মানের মধ্যে ইন্টারপোলেট করতে একটি টুইন ব্যবহার করুন
লক্ষ্য করুন যে AnimatedStar
উইজেটের রঙটি isActive
ক্ষেত্রটি সত্যে পরিবর্তিত হওয়ার সাথে সাথে পরিবর্তিত হয়।
একটি অ্যানিমেটেড রঙের প্রভাব অর্জনের জন্য, আপনি একটি AnimatedContainer
উইজেট ব্যবহার করার চেষ্টা করতে পারেন (যেটি ImplicitlyAnimatedWidget
এর আরেকটি সাবক্লাস), কারণ এটি স্বয়ংক্রিয়ভাবে রঙ সহ এর সমস্ত বৈশিষ্ট্য অ্যানিমেট করতে পারে। দুর্ভাগ্যবশত, আমাদের উইজেটকে একটি আইকন প্রদর্শন করতে হবে, একটি ধারক নয়।
আপনি AnimatedIcon
চেষ্টা করতে পারেন, যা আইকনগুলির আকারগুলির মধ্যে রূপান্তর প্রভাব প্রয়োগ করে৷ কিন্তু AnimatedIcons
ক্লাসে একটি তারকা আইকনের ডিফল্ট বাস্তবায়ন নেই।
পরিবর্তে, আমরা TweenAnimationBuilder
নামক ImplicitlyAnimatedWidget
এর আরেকটি সাবক্লাস ব্যবহার করব, যা প্যারামিটার হিসাবে একটি Tween
নেয়। একটি tween হল এমন একটি শ্রেণী যা দুটি মান ( begin
এবং end
) নেয় এবং মধ্যবর্তী মানগুলি গণনা করে, যাতে একটি অ্যানিমেশন তাদের প্রদর্শন করতে পারে। এই উদাহরণে, আমরা একটি ColorTween
ব্যবহার করব, যা আমাদের অ্যানিমেশন প্রভাব তৈরি করতে প্রয়োজনীয় Tween<Color>
ইন্টারফেসকে সন্তুষ্ট করে।
Icon
উইজেটটি নির্বাচন করুন এবং আপনার IDE-তে "র্যাপ উইথ বিল্ডার" দ্রুত অ্যাকশন ব্যবহার করুন, নামটি TweenAnimationBuilder
এ পরিবর্তন করুন। তারপর সময়কাল এবং ColorTween
প্রদান করুন।
lib/scoreboard.dart
class AnimatedStar extends StatelessWidget {
final bool isActive;
final Duration _duration = const Duration(milliseconds: 1000);
final Color _deactivatedColor = Colors.grey.shade400;
final Color _activatedColor = Colors.yellow.shade700;
AnimatedStar({super.key, required this.isActive});
@override
Widget build(BuildContext context) {
return AnimatedScale(
scale: isActive ? 1.0 : 0.5,
duration: _duration,
child: TweenAnimationBuilder( // Add from here...
duration: _duration,
tween: ColorTween(
begin: _deactivatedColor,
end: isActive ? _activatedColor : _deactivatedColor,
),
builder: (context, value, child) { // To here.
return Icon(
Icons.star,
size: 50,
color: value, // Modify from here...
);
}, // To here.
),
);
}
}
এখন, নতুন অ্যানিমেশন দেখতে অ্যাপটি হট-রিলোড করুন।
লক্ষ্য করুন যে আমাদের ColorTween
এর end
মান isActive
প্যারামিটারের মানের উপর ভিত্তি করে পরিবর্তিত হয়। এর কারণ হল TweenAnimationBuilder
যখনই Tween.end
মান পরিবর্তন হয় তখনই তার অ্যানিমেশন পুনরায় চালায়। যখন এটি ঘটে, তখন নতুন অ্যানিমেশন বর্তমান অ্যানিমেশন মান থেকে নতুন শেষ মান পর্যন্ত চলে, যা আপনাকে যে কোনো সময় রঙ পরিবর্তন করতে দেয় (এমনকি অ্যানিমেশন চলমান থাকাকালীন) এবং সঠিক মধ্যবর্তী মানগুলির সাথে একটি মসৃণ অ্যানিমেশন প্রভাব প্রদর্শন করতে দেয়। .
একটি বক্ররেখা প্রয়োগ করুন
এই উভয় অ্যানিমেশন প্রভাব একটি ধ্রুবক হারে চলে, কিন্তু অ্যানিমেশনগুলি প্রায়শই দৃশ্যত আকর্ষণীয় এবং তথ্যপূর্ণ হয় যখন তারা গতি বাড়ায় বা ধীর করে।
একটি Curve
একটি সহজ ফাংশন প্রয়োগ করে, যা সময়ের সাথে একটি প্যারামিটারের পরিবর্তনের হারকে সংজ্ঞায়িত করে। Curves
ক্লাসে পূর্ব-নির্মিত ইজিং কার্ভের সংগ্রহ সহ ফ্লাটার জাহাজ, যেমন easeIn
বা easeOut
।
এই চিত্রগুলি ( Curves
API ডকুমেন্টেশন পৃষ্ঠায় উপলব্ধ) বক্ররেখাগুলি কীভাবে কাজ করে তার একটি সূত্র দেয়। বক্ররেখা 0.0 এবং 1.0 এর মধ্যে একটি ইনপুট মান রূপান্তর করে (x অক্ষে প্রদর্শিত) 0.0 এবং 1.0 এর মধ্যে একটি আউটপুট মান (y অক্ষে প্রদর্শিত)। এই ডায়াগ্রামগুলি একটি ইজিং কার্ভ ব্যবহার করার সময় বিভিন্ন অ্যানিমেশন প্রভাবগুলি কেমন দেখায় তার একটি পূর্বরূপও দেখায়।
AnimatedStar-এ _curve
নামে একটি নতুন ক্ষেত্র তৈরি করুন এবং এটিকে AnimatedScale
এবং TweenAnimationBuilder
উইজেটগুলিতে প্যারামিটার হিসাবে পাস করুন।
lib/scoreboard.dart
class AnimatedStar extends StatelessWidget {
final bool isActive;
final Duration _duration = const Duration(milliseconds: 1000);
final Color _deactivatedColor = Colors.grey.shade400;
final Color _activatedColor = Colors.yellow.shade700;
final Curve _curve = Curves.elasticOut; // NEW
AnimatedStar({super.key, required this.isActive});
@override
Widget build(BuildContext context) {
return AnimatedScale(
scale: isActive ? 1.0 : 0.5,
curve: _curve, // NEW
duration: _duration,
child: TweenAnimationBuilder(
curve: _curve, // NEW
duration: _duration,
tween: ColorTween(
begin: _deactivatedColor,
end: isActive ? _activatedColor : _deactivatedColor,
),
builder: (context, value, child) {
return Icon(
Icons.star,
size: 50,
color: value,
);
},
),
);
}
}
এই উদাহরণে, elasticOut
বক্ররেখা একটি অতিরঞ্জিত স্প্রিং ইফেক্ট প্রদান করে যা স্প্রিং মোশন দিয়ে শুরু হয় এবং শেষের দিকে ভারসাম্য বজায় রাখে।
AnimatedSize
এবং TweenAnimationBuilder
এ প্রয়োগ করা এই বক্ররেখা দেখতে অ্যাপটিকে হট রিলোড করুন।
ধীরগতির অ্যানিমেশন সক্ষম করতে DevTools ব্যবহার করুন
যেকোনো অ্যানিমেশন ইফেক্ট ডিবাগ করতে, Flutter DevTools আপনার অ্যাপের সমস্ত অ্যানিমেশনকে ধীর করার একটি উপায় প্রদান করে, যাতে আপনি আরও স্পষ্টভাবে অ্যানিমেশন দেখতে পারেন।
DevTools খুলতে, অ্যাপটি ডিবাগ মোডে চলছে তা নিশ্চিত করুন এবং VSCode-এর ডিবাগ টুলবারে বা IntelliJ/Android স্টুডিওতে ডিবাগ টুল উইন্ডোতে Open Flutter DevTools বোতামটি নির্বাচন করে উইজেট ইন্সপেক্টর খুলুন।
একবার উইজেট ইন্সপেক্টর খোলা হলে, টুলবারে স্লো অ্যানিমেশন বোতামে ক্লিক করুন।
5. স্পষ্ট অ্যানিমেশন প্রভাব ব্যবহার করুন
অন্তর্নিহিত অ্যানিমেশনের মতো, স্পষ্ট অ্যানিমেশনগুলি পূর্ব-নির্মিত অ্যানিমেশন প্রভাব, তবে একটি লক্ষ্য মান নেওয়ার পরিবর্তে, তারা একটি প্যারামিটার হিসাবে একটি Animation
অবজেক্ট নেয়। এটি তাদের এমন পরিস্থিতিতে উপযোগী করে তোলে যেখানে অ্যানিমেশনটি ইতিমধ্যেই একটি নেভিগেশন ট্রানজিশন, AnimatedSwitcher
বা AnimationController
দ্বারা সংজ্ঞায়িত করা হয়েছে, উদাহরণস্বরূপ।
একটি স্পষ্ট অ্যানিমেশন প্রভাব ব্যবহার করুন
একটি স্পষ্ট অ্যানিমেশন প্রভাবের সাথে শুরু করতে, একটি AnimatedSwitcher
দিয়ে Card
উইজেটটি মুড়ে দিন।
lib/question_screen.dart
class QuestionCard extends StatelessWidget {
final String? question;
const QuestionCard({
required this.question,
super.key,
});
@override
Widget build(BuildContext context) {
return AnimatedSwitcher( // NEW
duration: const Duration(milliseconds: 300), // NEW
child: Card(
key: ValueKey(question),
elevation: 4,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Text(
question ?? '',
style: Theme.of(context).textTheme.displaySmall,
),
),
), // NEW
);
}
}
AnimatedSwitcher
ডিফল্টরূপে একটি ক্রস-ফেইড প্রভাব ব্যবহার করে, কিন্তু আপনি transitionBuilder
প্যারামিটার ব্যবহার করে এটিকে ওভাররাইড করতে পারেন। রূপান্তর নির্মাতা চাইল্ড উইজেট প্রদান করে যা AnimatedSwitcher
এবং একটি Animation
অবজেক্টে পাস করা হয়েছিল। এটি একটি স্পষ্ট অ্যানিমেশন ব্যবহার করার একটি দুর্দান্ত সুযোগ।
এই কোডল্যাবের জন্য, প্রথম স্পষ্ট অ্যানিমেশনটি আমরা ব্যবহার করব SlideTransition
, যা একটি Animation<Offset>
যা শুরু এবং শেষ অফসেটকে সংজ্ঞায়িত করে যে ইনকামিং এবং আউটগোয়িং উইজেটগুলির মধ্যে চলে যাবে।
Tweens এর একটি হেল্পার ফাংশন আছে, animate()
, যা যেকোনো Animation
টুইন প্রয়োগের সাথে অন্য Animation
রূপান্তর করে। এর মানে হল যে একটি Tween<Offset>
AnimatedSwitcher
দ্বারা প্রদত্ত Animation<double>
কে একটি Animation<Offset>
এ রূপান্তর করতে ব্যবহার করা যেতে পারে, যা SlideTransition
উইজেটে প্রদান করা হবে।
lib/question_screen.dart
class QuestionCard extends StatelessWidget {
final String? question;
const QuestionCard({
required this.question,
super.key,
});
@override
Widget build(BuildContext context) {
return AnimatedSwitcher(
transitionBuilder: (child, animation) { // Add from here...
final curveAnimation =
CurveTween(curve: Curves.easeInCubic).animate(animation);
final offsetAnimation =
Tween<Offset>(begin: Offset(-0.1, 0.0), end: Offset.zero)
.animate(curveAnimation);
return SlideTransition(position: offsetAnimation, child: child);
}, // To here.
duration: const Duration(milliseconds: 300),
child: Card(
key: ValueKey(question),
elevation: 4,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Text(
question ?? '',
style: Theme.of(context).textTheme.displaySmall,
),
),
),
);
}
}
মনে রাখবেন যে এটি Animation
একটি Curve
প্রয়োগ করতে Tween.animate
ব্যবহার করে, এবং তারপর এটিকে একটি Tween<double>
থেকে রূপান্তর করতে যা 0.0 থেকে 1.0 পর্যন্ত, একটি T ween<Offset>
যা x-এ -0.1 থেকে 0.0 পর্যন্ত রূপান্তরিত হয়। -অক্ষ
বিকল্পভাবে, অ্যানিমেশন ক্লাসে একটি drive()
ফাংশন রয়েছে যা যেকোনো Tween
(বা Animatable
) নেয় এবং এটিকে একটি নতুন Animation
রূপান্তর করে। এটি টুইনগুলিকে "শৃঙ্খলিত" করার অনুমতি দেয়, ফলে কোডটিকে আরও সংক্ষিপ্ত করে তোলে:
lib/question_screen.dart
transitionBuilder: (child, animation) {
var offsetAnimation = animation
.drive(CurveTween(curve: Curves.easeInCubic))
.drive(Tween<Offset>(begin: Offset(-0.1, 0.0), end: Offset.zero));
return SlideTransition(position: offsetAnimation, child: child);
},
সুস্পষ্ট অ্যানিমেশন ব্যবহার করার আরেকটি সুবিধা হল যে তারা সহজেই একসাথে রচনা করা যায়। আরেকটি স্পষ্ট অ্যানিমেশন যোগ করুন, FadeTransition যেটি SlideTransition উইজেট মোড়ানোর মাধ্যমে একই বাঁকা অ্যানিমেশন ব্যবহার করে।
lib/question_screen.dart
return AnimatedSwitcher(
transitionBuilder: (child, animation) {
final curveAnimation =
CurveTween(curve: Curves.easeInCubic).animate(animation);
final offsetAnimation =
Tween<Offset>(begin: Offset(-0.1, 0.0), end: Offset.zero)
.animate(curveAnimation);
final fadeInAnimation = curveAnimation; // NEW
return FadeTransition( // NEW
opacity: fadeInAnimation, // NEW
child: SlideTransition(position: offsetAnimation, child: child), // NEW
); // NEW
},
লেআউট বিল্ডার কাস্টমাইজ করুন
আপনি অ্যানিমেশন সুইচারের সাথে একটি ছোট সমস্যা লক্ষ্য করতে পারেন। যখন একটি প্রশ্নকার্ড একটি নতুন প্রশ্নে স্যুইচ করে, তখন এটি অ্যানিমেশন চলাকালীন উপলব্ধ স্থানের মাঝখানে রেখে দেয়, কিন্তু অ্যানিমেশন বন্ধ হয়ে গেলে, উইজেটটি স্ক্রিনের শীর্ষে চলে যায়। এটি একটি জ্যাঙ্কি অ্যানিমেশন সৃষ্টি করে কারণ অ্যানিমেশন চলাকালীন প্রশ্ন কার্ডের চূড়ান্ত অবস্থানের সাথে মেলে না।
এটি ঠিক করতে, অ্যানিমেটেড সুইচারের একটি লেআউটবিল্ডার প্যারামিটারও রয়েছে, যা লেআউটটি সংজ্ঞায়িত করতে ব্যবহার করা যেতে পারে। কার্ডটিকে পর্দার শীর্ষে সারিবদ্ধ করতে লেআউট নির্মাতা কনফিগার করতে এই ফাংশনটি ব্যবহার করুন:
lib/question_screen.dart
@override
Widget build(BuildContext context) {
return AnimatedSwitcher(
layoutBuilder: (currentChild, previousChildren) {
return Stack(
alignment: Alignment.topCenter,
children: <Widget>[
...previousChildren,
if (currentChild != null) currentChild,
],
);
},
এই কোডটি AnimatedSwitcher ক্লাস থেকে ডিফল্টLayoutBuilder- এর একটি পরিবর্তিত সংস্করণ, কিন্তু Alignment.center
এর পরিবর্তে Alignment.topCenter
ব্যবহার করে।
সারাংশ
- স্পষ্ট অ্যানিমেশনগুলি হল অ্যানিমেশন প্রভাব যা একটি অ্যানিমেশন অবজেক্ট নেয় (ইমপ্লিসিটলি অ্যানিমেটেড উইজেটগুলির বিপরীতে, যা একটি লক্ষ্য মান এবং সময়কাল নেয়)
- অ্যানিমেশন ক্লাস একটি চলমান অ্যানিমেশন প্রতিনিধিত্ব করে, কিন্তু একটি নির্দিষ্ট প্রভাব সংজ্ঞায়িত করে না।
- একটি অ্যানিমেশনে Tweens এবং Curves (CurveTween ব্যবহার করে) প্রয়োগ করতে Tween().animate বা Animation.drive() ব্যবহার করুন।
- অ্যানিমেটেড সুইচারের লেআউটবিল্ডার প্যারামিটার ব্যবহার করুন যাতে এটি তার বাচ্চাদের কীভাবে সাজায়।
6. একটি অ্যানিমেশনের অবস্থা নিয়ন্ত্রণ করুন
এখন পর্যন্ত, প্রতিটি অ্যানিমেশন ফ্রেমওয়ার্ক দ্বারা স্বয়ংক্রিয়ভাবে চালানো হয়েছে। অন্তর্নিহিত অ্যানিমেশনগুলি স্বয়ংক্রিয়ভাবে চলে, এবং স্পষ্ট অ্যানিমেশন প্রভাবগুলির সঠিকভাবে কাজ করার জন্য একটি অ্যানিমেশন প্রয়োজন৷ এই বিভাগে, আপনি শিখবেন কিভাবে একটি অ্যানিমেশন কন্ট্রোলার ব্যবহার করে আপনার নিজস্ব অ্যানিমেশন অবজেক্ট তৈরি করতে হয় এবং টুইন্সকে একসাথে একত্রিত করতে একটি TweenSequence ব্যবহার করতে হয়।
একটি অ্যানিমেশন কন্ট্রোলার ব্যবহার করে একটি অ্যানিমেশন চালান
একটি অ্যানিমেশন কন্ট্রোলার ব্যবহার করে একটি অ্যানিমেশন তৈরি করতে, আপনাকে এই পদক্ষেপগুলি অনুসরণ করতে হবে:
- একটি স্টেটফুল উইজেট তৈরি করুন
- আপনার অ্যানিমেশন কন্ট্রোলারে টিকার প্রদান করতে আপনার স্টেট ক্লাসে SingleTickerProviderStateMixin mixin ব্যবহার করুন
-
vsync
(TickerProvider) প্যারামিটারে বর্তমান স্টেট অবজেক্ট প্রদান করে initState জীবনচক্র পদ্ধতিতে অ্যানিমেশন কন্ট্রোলার শুরু করুন। - অ্যানিমেটেডবিল্ডার ব্যবহার করে অথবা ম্যানুয়ালি listen() এবং setState কল করে যখনই অ্যানিমেশন কন্ট্রোলার তার শ্রোতাদেরকে অবহিত করে তখনই আপনার উইজেট পুনরায় তৈরি হয় তা নিশ্চিত করুন৷
একটি নতুন ফাইল তৈরি করুন, flip_effect.dart এবং নিম্নলিখিত কোড কপি-পেস্ট করুন:
lib/flip_effect.dart
import 'dart:math' as math;
import 'package:flutter/widgets.dart';
class CardFlipEffect extends StatefulWidget {
final Widget child;
final Duration duration;
const CardFlipEffect({
super.key,
required this.child,
required this.duration,
});
@override
State<CardFlipEffect> createState() => _CardFlipEffectState();
}
class _CardFlipEffectState extends State<CardFlipEffect>
with SingleTickerProviderStateMixin {
late final AnimationController _animationController;
Widget? _previousChild;
@override
void initState() {
super.initState();
_animationController =
AnimationController(vsync: this, duration: widget.duration);
_animationController.addListener(() {
if (_animationController.value == 1) {
_animationController.reset();
}
});
}
@override
void didUpdateWidget(covariant CardFlipEffect oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.child.key != oldWidget.child.key) {
_handleChildChanged(widget.child, oldWidget.child);
}
}
void _handleChildChanged(Widget newChild, Widget previousChild) {
_previousChild = previousChild;
_animationController.forward();
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _animationController,
builder: (context, child) {
return Transform(
alignment: Alignment.center,
transform: Matrix4.identity()
..rotateX(_animationController.value * math.pi),
child: _animationController.isAnimating
? _animationController.value < 0.5
? _previousChild
: Transform.flip(flipY: true, child: child)
: child,
);
},
child: widget.child,
);
}
}
এই শ্রেণীটি একটি অ্যানিমেশন কন্ট্রোলার সেট আপ করে এবং যখনই ফ্রেমওয়ার্ক didUpdateWidget-কে কল করে যে উইজেট কনফিগারেশন পরিবর্তিত হয়েছে, এবং একটি নতুন চাইল্ড উইজেট থাকতে পারে তখন অ্যানিমেশনটি পুনরায় চালায়।
অ্যানিমেটেডবিল্ডার নিশ্চিত করে যে যখনই অ্যানিমেশন কন্ট্রোলার তার শ্রোতাদের অবহিত করে তখনই উইজেট ট্রিটি পুনরায় তৈরি করা হয় এবং ট্রান্সফর্ম উইজেটটি একটি 3D ঘূর্ণন প্রভাব প্রয়োগ করতে ব্যবহৃত হয় যাতে একটি কার্ড ফ্লিপ করা হয়।
এই উইজেটটি ব্যবহার করতে, প্রতিটি উত্তর কার্ড একটি CardFlipEffect উইজেট দিয়ে মুড়ে দিন। কার্ড উইজেটে একটি key
প্রদান নিশ্চিত করুন:
lib/question_screen.dart
@override
Widget build(BuildContext context) {
return GridView.count(
shrinkWrap: true,
crossAxisCount: 2,
childAspectRatio: 5 / 2,
children: List.generate(answers.length, (index) {
var color = Theme.of(context).colorScheme.primaryContainer;
if (correctAnswer == index) {
color = Theme.of(context).colorScheme.tertiaryContainer;
}
return CardFlipEffect( // NEW
duration: const Duration(milliseconds: 300), // NEW
child: Card.filled( // NEW
key: ValueKey(answers[index]), // NEW
color: color,
elevation: 2,
margin: EdgeInsets.all(8),
clipBehavior: Clip.hardEdge,
child: InkWell(
onTap: () => onTapped(index),
child: Padding(
padding: EdgeInsets.all(16.0),
child: Center(
child: Text(
answers.length > index ? answers[index] : '',
style: Theme.of(context).textTheme.titleMedium,
overflow: TextOverflow.clip,
),
),
),
),
), // NEW
);
}),
);
}
CardFlipEffect উইজেট ব্যবহার করে উত্তর কার্ডগুলি ফ্লিপ ওভার দেখতে এখন অ্যাপটি হট-রিলোড করুন৷
আপনি লক্ষ্য করতে পারেন যে এই ক্লাসটি দেখতে অনেকটা স্পষ্ট অ্যানিমেশন প্রভাবের মতো। আসলে, আপনার নিজস্ব সংস্করণ বাস্তবায়নের জন্য সরাসরি অ্যানিমেটেড উইজেট ক্লাস প্রসারিত করা প্রায়শই একটি ভাল ধারণা। দুর্ভাগ্যবশত, যেহেতু এই ক্লাসটিকে তার রাজ্যে আগের উইজেট সংরক্ষণ করতে হবে, তাই এটি একটি StatefulWidget ব্যবহার করতে হবে। আপনার নিজের স্পষ্ট অ্যানিমেশন প্রভাব তৈরি করার বিষয়ে আরও জানতে, অ্যানিমেটেড উইজেটের জন্য API ডকুমেন্টেশন দেখুন।
TweenSequence ব্যবহার করে একটি বিলম্ব যোগ করুন
এই বিভাগে, আপনি CardFlipEffect উইজেটে একটি বিলম্ব যোগ করবেন যাতে প্রতিটি কার্ড একবারে একটির উপরে উল্টে যায়। শুরু করতে, delayAmount
নামে একটি নতুন ক্ষেত্র যোগ করুন।
lib/flip_effect.dart
class CardFlipEffect extends StatefulWidget {
final Widget child;
final Duration duration;
final double delayAmount; // NEW
const CardFlipEffect({
super.key,
required this.child,
required this.duration,
required this.delayAmount, // NEW
});
@override
State<CardFlipEffect> createState() => _CardFlipEffectState();
}
তারপর AnswerCards
বিল্ড পদ্ধতিতে delayAmount
যোগ করুন।
lib/question_screen.dart
@override
Widget build(BuildContext context) {
return GridView.count(
shrinkWrap: true,
crossAxisCount: 2,
childAspectRatio: 5 / 2,
children: List.generate(answers.length, (index) {
var color = Theme.of(context).colorScheme.primaryContainer;
if (correctAnswer == index) {
color = Theme.of(context).colorScheme.tertiaryContainer;
}
return CardFlipEffect(
delayAmount: index.toDouble() / 2, // NEW
duration: const Duration(milliseconds: 300),
child: Card.filled(
key: ValueKey(answers[index]),
তারপর _CardFlipEffectState
এ, একটি নতুন অ্যানিমেশন তৈরি করুন যা একটি TweenSequence
ব্যবহার করে বিলম্ব প্রযোজ্য। লক্ষ্য করুন যে এটি dart:async
লাইব্রেরি থেকে কোনো ইউটিলিটি ব্যবহার করে না , যেমন Future.delayed
। এর কারণ হল বিলম্ব অ্যানিমেশনের অংশ এবং উইজেট যখন অ্যানিমেশন কন্ট্রোলার ব্যবহার করে তখন তা স্পষ্টভাবে নিয়ন্ত্রণ করে এমন কিছু নয়৷ এটি DevTools-এ ধীরগতির অ্যানিমেশন সক্রিয় করার সময় অ্যানিমেশন প্রভাবকে ডিবাগ করা সহজ করে, কারণ এটি একই টিকারপ্রোভাইডার ব্যবহার করে।
একটি TweenSequence
ব্যবহার করতে, দুটি TweenSequenceItem
s তৈরি করুন, একটিতে একটি ConstantTween
রয়েছে যা একটি আপেক্ষিক সময়ের জন্য অ্যানিমেশনকে 0 এ রাখে এবং একটি নিয়মিত Tween
যা 0.0
থেকে 1.0
পর্যন্ত যায়।
lib/flip_effect.dart
class _CardFlipEffectState extends State<CardFlipEffect>
with SingleTickerProviderStateMixin {
late final AnimationController _animationController;
Widget? _previousChild;
late final Animation<double> _animationWithDelay; // NEW
@override
void initState() {
super.initState();
_animationController = AnimationController(
vsync: this, duration: widget.duration * (widget.delayAmount + 1));
_animationController.addListener(() {
if (_animationController.value == 1) {
_animationController.reset();
}
});
_animationWithDelay = TweenSequence<double>([ // NEW
if (widget.delayAmount > 0) // NEW
TweenSequenceItem( // NEW
tween: ConstantTween<double>(0.0), // NEW
weight: widget.delayAmount, // NEW
), // NEW
TweenSequenceItem( // NEW
tween: Tween(begin: 0.0, end: 1.0), // NEW
weight: 1.0, // NEW
), // NEW
]).animate(_animationController); // NEW
}
অবশেষে, বিল্ড পদ্ধতিতে অ্যানিমেশন কন্ট্রোলারের অ্যানিমেশনটিকে নতুন বিলম্বিত অ্যানিমেশন দিয়ে প্রতিস্থাপন করুন।
lib/flip_effect.dart
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _animationWithDelay, // Modify this line
builder: (context, child) {
return Transform(
alignment: Alignment.center,
transform: Matrix4.identity()
..rotateX(_animationWithDelay.value * math.pi), // And this line
child: _animationController.isAnimating
? _animationWithDelay.value < 0.5 // And this one.
? _previousChild
: Transform.flip(flipY: true, child: child)
: child,
);
},
child: widget.child,
);
}
এখন অ্যাপটি হট রিলোড করুন এবং কার্ডগুলি একে একে ফ্লিপ করতে দেখুন। একটি চ্যালেঞ্জের জন্য Transform
উইজেট দ্বারা প্রদত্ত 3D প্রভাবের দৃষ্টিকোণ পরিবর্তন করে পরীক্ষা করার চেষ্টা করুন..
7. কাস্টম নেভিগেশন ট্রানজিশন ব্যবহার করুন
এখন পর্যন্ত, আমরা দেখেছি কিভাবে একটি একক স্ক্রিনে প্রভাব কাস্টমাইজ করা যায়, কিন্তু অ্যানিমেশন ব্যবহার করার আরেকটি উপায় হল স্ক্রীনের মধ্যে স্থানান্তর করতে ব্যবহার করা। এই বিভাগে, আপনি pub.dev-এ অফিসিয়াল অ্যানিমেশন প্যাকেজ দ্বারা প্রদত্ত বিল্ট-ইন অ্যানিমেশন প্রভাব এবং অভিনব প্রাক-নির্মিত অ্যানিমেশন প্রভাবগুলি ব্যবহার করে স্ক্রীন ট্রানজিশনে অ্যানিমেশন প্রভাবগুলি কীভাবে প্রয়োগ করবেন তা শিখবেন।
একটি নেভিগেশন ট্রানজিশন অ্যানিমেট করুন
PageRouteBuilder
ক্লাস হল একটি Route
যা আপনাকে ট্রানজিশন অ্যানিমেশন কাস্টমাইজ করতে দেয়। এটি আপনাকে এর transitionBuilder
কলব্যাককে ওভাররাইড করতে দেয়, যা দুটি অ্যানিমেশন অবজেক্ট প্রদান করে, যা নেভিগেটর দ্বারা চালিত ইনকামিং এবং আউটগোয়িং অ্যানিমেশনের প্রতিনিধিত্ব করে।
ট্রানজিশন অ্যানিমেশন কাস্টমাইজ করতে, MaterialPageRoute
কে একটি PageRouteBuilder
দিয়ে প্রতিস্থাপন করুন এবং যখন ব্যবহারকারী HomeScreen
থেকে QuestionScreen
এ নেভিগেট করেন তখন ট্রানজিশন অ্যানিমেশন কাস্টমাইজ করতে। একটি ফেড ট্রানজিশন (একটি স্পষ্টভাবে অ্যানিমেটেড উইজেট) ব্যবহার করুন যাতে নতুন স্ক্রীনটি আগের স্ক্রিনের উপরে ফেইড হয়ে যায়।
lib/home_screen.dart
ElevatedButton(
onPressed: () {
// Show the question screen to start the game
Navigator.push(
context,
PageRouteBuilder( // NEW
pageBuilder: (context, animation, secondaryAnimation) { // NEW
return QuestionScreen(); // NEW
}, // NEW
transitionsBuilder: // NEW
(context, animation, secondaryAnimation, child) { // NEW
return FadeTransition( // NEW
opacity: animation, // NEW
child: child, // NEW
); // NEW
}, // NEW
), // NEW
);
},
child: Text('New Game'),
),
অ্যানিমেশন প্যাকেজ ফ্যাডথ্রু ট্রানজিশনের মতো অভিনব প্রাক-নির্মিত অ্যানিমেশন প্রভাব প্রদান করে। অ্যানিমেশন প্যাকেজ আমদানি করুন এবং FadeThroughTransition উইজেট দিয়ে FadeTransition প্রতিস্থাপন করুন:
lib/home_screen.dart
import 'package;animations/animations.dart';
ElevatedButton(
onPressed: () {
// Show the question screen to start the game
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context, animation, secondaryAnimation) {
return const QuestionScreen();
},
transitionsBuilder:
(context, animation, secondaryAnimation, child) {
return FadeThroughTransition( // NEW
animation: animation, // NEW
secondaryAnimation: secondaryAnimation, // NEW
child: child, // NEW
); // NEW
},
),
);
},
child: Text('New Game'),
),
ভবিষ্যদ্বাণীমূলক ব্যাক অ্যানিমেশন কাস্টমাইজ করুন
প্রেডিকটিভ ব্যাক হল একটি নতুন অ্যান্ড্রয়েড বৈশিষ্ট্য যা ব্যবহারকারীকে নেভিগেট করার আগে বর্তমান রুট বা অ্যাপের পিছনে কী আছে তা দেখতে দেয়। পিক অ্যানিমেশন ব্যবহারকারীর আঙুলের অবস্থান দ্বারা চালিত হয় যখন তারা স্ক্রীন জুড়ে ফিরে আসে।
ফ্লটার সিস্টেম লেভেলে ফিচারটি সক্ষম করে সিস্টেম প্রেডিকটিভ ব্যাককে সমর্থন করে যখন ফ্লটার এর নেভিগেশন স্ট্যাকে পপ করার কোন রুট থাকে না বা অন্য কথায়, যখন ব্যাক অ্যাপ থেকে বেরিয়ে যাবে। এই অ্যানিমেশনটি সিস্টেম দ্বারা পরিচালিত হয় এবং ফ্লাটার নিজেই নয়।
Flutter একটি Flutter অ্যাপের মধ্যে রুটের মধ্যে নেভিগেট করার সময় ভবিষ্যদ্বাণীমূলক ব্যাক সমর্থন করে। PredictiveBackPageTransitionsBuilder
নামক একটি বিশেষ PageTransitionsBuilder সিস্টেম ভবিষ্যদ্বাণীমূলক ব্যাক অঙ্গভঙ্গি শোনে এবং অঙ্গভঙ্গির অগ্রগতির সাথে তার পৃষ্ঠার রূপান্তর চালায়।
ভবিষ্যদ্বাণীমূলক ব্যাক শুধুমাত্র অ্যান্ড্রয়েড ইউ এবং তার উপরে সমর্থিত, তবে ফ্লাটার আকর্ষণীয়ভাবে মূল ব্যাক জেসচার আচরণ এবং ZoomPageTransitionBuilder- এ ফিরে আসবে। আপনার নিজের অ্যাপে এটি কীভাবে সেট আপ করবেন সে সম্পর্কে একটি বিভাগ সহ আরও কিছুর জন্য আমাদের ব্লগ পোস্ট দেখুন৷
আপনার অ্যাপের জন্য ThemeData কনফিগারেশনে, Android-এ PredictiveBack ব্যবহার করতে PageTransitionsTheme কনফিগার করুন এবং অন্যান্য প্ল্যাটফর্মে অ্যানিমেশন প্যাকেজ থেকে ফেড-থ্রু ট্রানজিশন প্রভাব:
lib/main.dart
import 'package:animations/animations.dart'; // NEW
import 'package:flutter/material.dart';
import 'home_screen.dart';
void main() {
runApp(MainApp());
}
class MainApp extends StatelessWidget {
const MainApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
useMaterial3: true,
pageTransitionsTheme: PageTransitionsTheme(
builders: {
TargetPlatform.android: PredictiveBackPageTransitionsBuilder(), // NEW
TargetPlatform.iOS: FadeThroughPageTransitionsBuilder(), // NEW
TargetPlatform.macOS: FadeThroughPageTransitionsBuilder(), // NEW
TargetPlatform.windows: FadeThroughPageTransitionsBuilder(), // NEW
TargetPlatform.linux: FadeThroughPageTransitionsBuilder(), // NEW
},
),
),
home: HomeScreen(),
);
}
}
এখন আপনি Navigator.push() কলটিকে MaterialPageRoute-এ পরিবর্তন করতে পারেন।
lib/home_screen.dart
ElevatedButton(
onPressed: () {
// Show the question screen to start the game
Navigator.push(
context,
MaterialPageRoute(builder: (context) { // NEW
return const QuestionScreen(); // NEW
}), // NEW
);
},
child: Text('New Game'),
),
বর্তমান প্রশ্ন পরিবর্তন করতে FadeThroughTransition ব্যবহার করুন
অ্যানিমেটেড সুইচার উইজেট তার নির্মাতা কলব্যাকে শুধুমাত্র একটি অ্যানিমেশন প্রদান করে। এটি মোকাবেলার জন্য, animations
প্যাকেজ একটি PageTransitionSwitcher প্রদান করে।
lib/question_screen.dart
class QuestionCard extends StatelessWidget {
final String? question;
const QuestionCard({
required this.question,
super.key,
});
@override
Widget build(BuildContext context) {
return PageTransitionSwitcher( // NEW
layoutBuilder: (entries) { // NEW
return Stack( // NEW
alignment: Alignment.topCenter, // NEW
children: entries, // NEW
); // NEW
}, // NEW
transitionBuilder: (child, animation, secondaryAnimation) { // NEW
return FadeThroughTransition( // NEW
animation: animation, // NEW
secondaryAnimation: secondaryAnimation, // NEW
child: child, // NEW
); // NEW
}, // NEW
duration: const Duration(milliseconds: 300),
child: Card(
key: ValueKey(question),
elevation: 4,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Text(
question ?? '',
style: Theme.of(context).textTheme.displaySmall,
),
),
),
);
}
}
OpenContainer ব্যবহার করুন
animations
প্যাকেজ থেকে OpenContainer উইজেট একটি কন্টেইনার ট্রান্সফর্ম অ্যানিমেশন প্রভাব প্রদান করে যা দুটি উইজেটের মধ্যে একটি ভিজ্যুয়াল সংযোগ তৈরি করতে প্রসারিত হয়।
closedBuilder
দ্বারা প্রত্যাবর্তিত উইজেটটি প্রাথমিকভাবে প্রদর্শিত হয় এবং যখন ধারকটি ট্যাপ করা হয় বা যখন openContainer
কলব্যাক কল করা হয় তখন openBuilder
দ্বারা প্রত্যাবর্তিত উইজেটে প্রসারিত হয়।
openContainer
কলব্যাকটিকে ভিউ-মডেলের সাথে সংযুক্ত করতে, QuestionCard উইজেটে একটি নতুন পাস the viewModel যোগ করুন এবং একটি কলব্যাক সঞ্চয় করুন যা "গেম ওভার" স্ক্রীন দেখানোর জন্য ব্যবহার করা হবে:
lib/question_screen.dart
class QuestionScreen extends StatefulWidget {
const QuestionScreen({super.key});
@override
State<QuestionScreen> createState() => _QuestionScreenState();
}
class _QuestionScreenState extends State<QuestionScreen> {
late final QuizViewModel viewModel =
QuizViewModel(onGameOver: _handleGameOver);
VoidCallback? _showGameOverScreen; // NEW
@override
Widget build(BuildContext context) {
return ListenableBuilder(
listenable: viewModel,
builder: (context, child) {
return Scaffold(
appBar: AppBar(
actions: [
TextButton(
onPressed:
viewModel.hasNextQuestion && viewModel.didAnswerQuestion
? () {
viewModel.getNextQuestion();
}
: null,
child: const Text('Next'),
)
],
),
body: Center(
child: Column(
children: [
QuestionCard( // NEW
onChangeOpenContainer: _handleChangeOpenContainer, // NEW
question: viewModel.currentQuestion?.question, // NEW
viewModel: viewModel, // NEW
), // NEW
Spacer(),
AnswerCards(
onTapped: (index) {
viewModel.checkAnswer(index);
},
answers: viewModel.currentQuestion?.possibleAnswers ?? [],
correctAnswer: viewModel.didAnswerQuestion
? viewModel.currentQuestion?.correctAnswer
: null,
),
StatusBar(viewModel: viewModel),
],
),
),
);
},
);
}
void _handleChangeOpenContainer(VoidCallback openContainer) { // NEW
_showGameOverScreen = openContainer; // NEW
} // NEW
void _handleGameOver() { // NEW
if (_showGameOverScreen != null) { // NEW
_showGameOverScreen!(); // NEW
} // NEW
} // NEW
}
একটি নতুন উইজেট যোগ করুন, GameOverScreen:
lib/question_screen.dart
class GameOverScreen extends StatelessWidget {
final QuizViewModel viewModel;
const GameOverScreen({required this.viewModel, super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Scoreboard(
score: viewModel.score,
totalQuestions: viewModel.totalQuestions,
),
Text(
'You Win!',
style: Theme.of(context).textTheme.displayLarge,
),
Text(
'Score: ${viewModel.score} / ${viewModel.totalQuestions}',
style: Theme.of(context).textTheme.displaySmall,
),
ElevatedButton(
child: Text('OK'),
onPressed: () {
Navigator.popUntil(context, (route) => route.isFirst);
},
),
],
),
),
);
}
}
প্রশ্নকার্ড উইজেটে, ভিউমডেল এবং খোলা কন্টেইনার কলব্যাকের জন্য দুটি নতুন ক্ষেত্র যোগ করে অ্যানিমেশন প্যাকেজ থেকে একটি OpenContainer উইজেট দিয়ে কার্ডটি প্রতিস্থাপন করুন:
lib/question_screen.dart
class QuestionCard extends StatelessWidget {
final String? question;
const QuestionCard({
required this.onChangeOpenContainer,
required this.question,
required this.viewModel,
super.key,
});
final ValueChanged<VoidCallback> onChangeOpenContainer;
final QuizViewModel viewModel;
static const _backgroundColor = Color(0xfff2f3fa);
@override
Widget build(BuildContext context) {
return PageTransitionSwitcher(
duration: const Duration(milliseconds: 200),
transitionBuilder: (child, animation, secondaryAnimation) {
return FadeThroughTransition(
animation: animation,
secondaryAnimation: secondaryAnimation,
child: child,
);
},
child: OpenContainer( // NEW
key: ValueKey(question), // NEW
tappable: false, // NEW
closedColor: _backgroundColor, // NEW
closedShape: const RoundedRectangleBorder( // NEW
borderRadius: BorderRadius.all(Radius.circular(12.0)), // NEW
), // NEW
closedElevation: 4, // NEW
closedBuilder: (context, openContainer) { // NEW
onChangeOpenContainer(openContainer); // NEW
return ColoredBox( // NEW
color: _backgroundColor, // NEW
child: Padding( // NEW
padding: const EdgeInsets.all(16.0), // NEW
child: Text(
question ?? '',
style: Theme.of(context).textTheme.displaySmall,
),
),
);
},
openBuilder: (context, closeContainer) { // NEW
return GameOverScreen(viewModel: viewModel); // NEW
}, // NEW
),
);
}
}
8. অভিনন্দন
অভিনন্দন, আপনি সফলভাবে একটি Flutter অ্যাপে অ্যানিমেশন প্রভাব যুক্ত করেছেন এবং Flutter-এর অ্যানিমেশন সিস্টেমের মূল উপাদানগুলি সম্পর্কে শিখেছেন৷ বিশেষ করে, আপনি শিখেছেন:
- কিভাবে একটি ইমপ্লিসিটলি অ্যানিমেটেড উইজেট ব্যবহার করবেন
- কিভাবে একটি স্পষ্টভাবে অ্যানিমেটেড উইজেট ব্যবহার করবেন
- একটি অ্যানিমেশনে কার্ভ এবং টুইন্স কীভাবে প্রয়োগ করবেন
- অ্যানিমেটেড সুইচার বা PageRouteBuilder এর মতো প্রাক-নির্মিত ট্রানজিশন উইজেটগুলি কীভাবে ব্যবহার করবেন
-
animations
প্যাকেজ থেকে অভিনব প্রাক-নির্মিত অ্যানিমেশন প্রভাবগুলি কীভাবে ব্যবহার করবেন, যেমন FadeThroughTransition এবং OpenContainer - অ্যান্ড্রয়েডে ভবিষ্যদ্বাণীমূলক ব্যাক সমর্থন যোগ করা সহ ডিফল্ট ট্রানজিশন অ্যানিমেশন কীভাবে কাস্টমাইজ করবেন।
এরপর কি?
এই কোডল্যাবগুলির কয়েকটি দেখুন:
- উপাদান 3 সহ একটি অ্যানিমেটেড প্রতিক্রিয়াশীল অ্যাপ লেআউট তৈরি করা
- ফ্লটারের জন্য উপাদান গতির সাথে সুন্দর রূপান্তর তৈরি করা
- আপনার ফ্লটার অ্যাপটিকে বিরক্তিকর থেকে সুন্দরের দিকে নিয়ে যান
অথবা অ্যানিমেশন নমুনা অ্যাপ ডাউনলোড করুন, যা বিভিন্ন অ্যানিমেশন কৌশল প্রদর্শন করে
আরও পড়া
আপনি flutter.dev এ আরও অ্যানিমেশন সংস্থান খুঁজে পেতে পারেন:
- অ্যানিমেশন পরিচিতি
- অ্যানিমেশন টিউটোরিয়াল (টিউটোরিয়াল)
- অন্তর্নিহিত অ্যানিমেশন (টিউটোরিয়াল)
- একটি পাত্রের বৈশিষ্ট্য অ্যানিমেট করুন (রান্নার বই)
- একটি উইজেট ভিতরে এবং বাইরে ফেড করুন (রান্নার বই)
- হিরো অ্যানিমেশন
- একটি পৃষ্ঠা রুট ট্রানজিশন অ্যানিমেট করুন (কুকবুক)
- একটি পদার্থবিদ্যা সিমুলেশন ব্যবহার করে একটি উইজেট অ্যানিমেট করুন (কুকবুক)
- স্তব্ধ অ্যানিমেশন
- অ্যানিমেশন এবং মোশন উইজেট (উইজেট ক্যাটালগ)
অথবা মিডিয়ামে এই নিবন্ধগুলি দেখুন:
- অ্যানিমেশন গভীর ডুব
- ফ্লটারে কাস্টম অন্তর্নিহিত অ্যানিমেশন
- Flutter এবং Flux / Redux সহ অ্যানিমেশন ব্যবস্থাপনা
- কোন ফ্লটার অ্যানিমেশন উইজেটটি আপনার জন্য সঠিক তা কীভাবে চয়ন করবেন?
- অন্তর্নির্মিত স্পষ্ট অ্যানিমেশন সহ দিকনির্দেশক অ্যানিমেশন
- অন্তর্নিহিত অ্যানিমেশন সহ ফ্লটার অ্যানিমেশনের মূল বিষয়গুলি
- আমি কখন AnimatedBuilder বা AnimatedWidget ব্যবহার করব?