1. ভূমিকা
অ্যানিমেশনগুলি আপনার অ্যাপের ব্যবহারকারীর অভিজ্ঞতা উন্নত করার, ব্যবহারকারীর কাছে গুরুত্বপূর্ণ তথ্য যোগাযোগ করার এবং আপনার অ্যাপটিকে আরও সুন্দর এবং ব্যবহার করার জন্য উপভোগ্য করে তোলার একটি দুর্দান্ত উপায়৷
ফ্লটারের অ্যানিমেশন ফ্রেমওয়ার্কের ওভারভিউ
ফ্লটার প্রতিটি ফ্রেমে উইজেট গাছের একটি অংশ পুনঃনির্মাণ করে অ্যানিমেশন প্রভাব প্রদর্শন করে। এটি অ্যানিমেশন তৈরি এবং রচনা করা সহজ করতে পূর্বনির্মাণ অ্যানিমেশন প্রভাব এবং অন্যান্য API প্রদান করে।
- অন্তর্নিহিত অ্যানিমেশনগুলি হল প্রি-বিল্ট অ্যানিমেশন প্রভাব যা সম্পূর্ণ অ্যানিমেশন স্বয়ংক্রিয়ভাবে চালায়। যখন অ্যানিমেশনের লক্ষ্য মান পরিবর্তিত হয়, তখন এটি বর্তমান মান থেকে লক্ষ্য মান পর্যন্ত অ্যানিমেশন চালায় এবং এর মধ্যে প্রতিটি মান প্রদর্শন করে যাতে উইজেটটি মসৃণভাবে অ্যানিমেট হয়। অন্তর্নিহিত অ্যানিমেশনের উদাহরণগুলির মধ্যে রয়েছে
AnimatedSize,AnimatedScaleএবংAnimatedPositioned। - স্পষ্ট অ্যানিমেশনগুলিও প্রি-বিল্ট অ্যানিমেশন প্রভাব, কিন্তু কাজ করার জন্য একটি
Animationঅবজেক্টের প্রয়োজন। উদাহরণগুলির মধ্যে রয়েছেSizeTransition,ScaleTransitionবাPositionedTransitionTransition। - অ্যানিমেশন হল একটি শ্রেণী যা একটি চলমান বা থামানো অ্যানিমেশনকে উপস্থাপন করে, এবং অ্যানিমেশনটি যে লক্ষ্য মানটি চালাচ্ছে তা প্রতিনিধিত্ব করে এবং স্থিতি , যা অ্যানিমেশন যে কোনো নির্দিষ্ট সময়ে স্ক্রিনে প্রদর্শিত বর্তমান মানকে উপস্থাপন করে। এটি
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-এ flutter/samples রিপোজিটরি থেকে স্টার্ট অ্যাপ ক্লোন করতে 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(isActive: score > i), // Edit this line.
],
),
);
}
}
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 সন্তুষ্ট করে Tween আমাদের অ্যানিমেশন প্রভাব তৈরি করতে ইন্টারফেস প্রয়োজন।
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); // And modify this line.
},
),
);
}
}
এখন, নতুন অ্যানিমেশন দেখতে অ্যাপটি হট-রিলোড করুন।

লক্ষ্য করুন যে আমাদের 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 মানে Tween Animation রূপান্তর করতে ব্যবহার করা যেতে পারে Animation AnimatedSwitcher দ্বারা একটি Animation সরবরাহ করা হয়েছে Animation , 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 থেকে রূপান্তর করতে Tween যেটি 0.0 থেকে 1.0, একটি Tween পর্যন্ত Tween যেটি 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
},
লেআউট বিল্ডার কাস্টমাইজ করুন
আপনি AnimationSwitcher এর সাথে একটি ছোট সমস্যা লক্ষ্য করতে পারেন। যখন একটি QuestionCard একটি নতুন প্রশ্নে স্যুইচ করে, তখন এটি অ্যানিমেশন চলাকালীন উপলব্ধ স্থানের মাঝখানে রেখে দেয়, কিন্তু অ্যানিমেশন বন্ধ হয়ে গেলে, উইজেটটি স্ক্রিনের শীর্ষে চলে যায়। এটি একটি জ্যাঙ্কি অ্যানিমেশন সৃষ্টি করে কারণ অ্যানিমেশন চলাকালীন প্রশ্ন কার্ডের চূড়ান্ত অবস্থানের সাথে মেলে না।

এটি ঠিক করতে, AnimatedSwitcher একটি layoutBuilder প্যারামিটারও রয়েছে, যা লেআউটটি সংজ্ঞায়িত করতে ব্যবহার করা যেতে পারে। কার্ডটিকে পর্দার শীর্ষে সারিবদ্ধ করতে লেআউট নির্মাতা কনফিগার করতে এই ফাংশনটি ব্যবহার করুন:
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 ব্যবহার করে।
সারাংশ
- স্পষ্ট অ্যানিমেশন হল অ্যানিমেশন প্রভাব যা একটি
Animationঅবজেক্ট নেয় (ImplicitlyAnimatedWidgetsবিপরীতে, যা একটি লক্ষ্যvalueএবংdurationনেয়) -
Animationক্লাস একটি চলমান অ্যানিমেশন প্রতিনিধিত্ব করে, কিন্তু একটি নির্দিষ্ট প্রভাব সংজ্ঞায়িত করে না। - একটি অ্যানিমেশনে
TweensএবংCurves(CurveTweenব্যবহার করে) প্রয়োগ করতেTween().animateবাAnimation.drive()ব্যবহার করুন। -
AnimatedSwitcherlayoutBuilderপ্যারামিটার ব্যবহার করুন যাতে এটি তার বাচ্চাদের কীভাবে সাজায়।
6. একটি অ্যানিমেশনের অবস্থা নিয়ন্ত্রণ করুন
এখন পর্যন্ত, প্রতিটি অ্যানিমেশন ফ্রেমওয়ার্ক দ্বারা স্বয়ংক্রিয়ভাবে চালানো হয়েছে। অন্তর্নিহিত অ্যানিমেশনগুলি স্বয়ংক্রিয়ভাবে চলে, এবং স্পষ্ট অ্যানিমেশন প্রভাবগুলির সঠিকভাবে কাজ করার জন্য একটি Animation প্রয়োজন৷ এই বিভাগে, আপনি শিখবেন কিভাবে একটি AnimationController ব্যবহার করে আপনার নিজস্ব Animation অবজেক্ট তৈরি করতে হয়, এবং Tween কে একসাথে একত্রিত করতে একটি TweenSequence ব্যবহার করতে হয়।
একটি অ্যানিমেশন কন্ট্রোলার ব্যবহার করে একটি অ্যানিমেশন চালান
একটি অ্যানিমেশন কন্ট্রোলার ব্যবহার করে একটি অ্যানিমেশন তৈরি করতে, আপনাকে এই পদক্ষেপগুলি অনুসরণ করতে হবে:
- একটি
StatefulWidgetতৈরি করুন - আপনার
AnimationControllerকন্ট্রোলারেTickerপ্রদান করতে আপনারStateক্লাসেSingleTickerProviderStateMixinmixin ব্যবহার করুন -
initStateলাইফসাইকেল পদ্ধতিতেAnimationControllerচালু করুন, বর্তমানStateঅবজেক্টটিvsync(TickerProvider) প্যারামিটারে প্রদান করুন। -
AnimatedBuilderব্যবহার করে অথবা ম্যানুয়ালিlisten()এবংsetStateকল করে যখনইAnimationControllerতার শ্রোতাদেরকে অবহিত করে তখনই আপনার উইজেট পুনরায় তৈরি হয় তা নিশ্চিত করুন৷
একটি নতুন ফাইল তৈরি করুন, 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,
);
}
}
এই শ্রেণীটি একটি AnimationController সেট আপ করে এবং যখনই ফ্রেমওয়ার্ক didUpdateWidget কল করে যে উইজেট কনফিগারেশন পরিবর্তিত হয়েছে, এবং একটি নতুন চাইল্ড উইজেট থাকতে পারে তখন অ্যানিমেশনটি পুনরায় চালায়।
AnimatedBuilder নিশ্চিত করে যে যখনই AnimationController তার শ্রোতাদের অবহিত করে তখনই উইজেট ট্রিটি পুনরায় তৈরি করা হয় এবং Transform উইজেটটি একটি 3D ঘূর্ণন প্রভাব প্রয়োগ করতে ব্যবহৃত হয় যাতে একটি কার্ড ফ্লিপ করা হয়।
এই উইজেটটি ব্যবহার করতে, প্রতিটি উত্তর কার্ড একটি CardFlipEffect উইজেট দিয়ে মুড়ে দিন। Card উইজেটে একটি 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 উইজেট ব্যবহার করে উত্তর কার্ডগুলি ফ্লিপ ওভার দেখতে এখন অ্যাপটি হট-রিলোড করুন৷

আপনি লক্ষ্য করতে পারেন যে এই ক্লাসটি দেখতে অনেকটা স্পষ্ট অ্যানিমেশন প্রভাবের মতো। আসলে, আপনার নিজস্ব সংস্করণ বাস্তবায়নের জন্য সরাসরি AnimatedWidget ক্লাস প্রসারিত করা প্রায়শই একটি ভাল ধারণা। দুর্ভাগ্যবশত, যেহেতু এই ক্লাসের পূর্ববর্তী উইজেটটি তার State সংরক্ষণ করতে হবে, তাই এটি একটি 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 এ, একটি নতুন Animation তৈরি করুন যা একটি TweenSequence ব্যবহার করে বিলম্ব প্রযোজ্য। লক্ষ্য করুন যে এটি dart:async লাইব্রেরি থেকে কোনো ইউটিলিটি ব্যবহার করে না , যেমন Future.delayed । এর কারণ হল বিলম্ব অ্যানিমেশনের অংশ এবং উইজেট যখন AnimationController ব্যবহার করে তখন তা স্পষ্টভাবে নিয়ন্ত্রণ করে এমন কিছু নয়। এটি DevTools-এ ধীরগতির অ্যানিমেশন সক্রিয় করার সময় অ্যানিমেশন প্রভাবকে ডিবাগ করা সহজ করে তোলে, যেহেতু এটি একই TickerProvider ব্যবহার করে।
একটি 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>([ // Add from here...
if (widget.delayAmount > 0)
TweenSequenceItem(
tween: ConstantTween<double>(0.0),
weight: widget.delayAmount,
),
TweenSequenceItem(tween: Tween(begin: 0.0, end: 1.0), weight: 1.0),
]).animate(_animationController); // To here.
}
অবশেষে, build পদ্ধতিতে AnimationController অ্যানিমেশনটিকে নতুন বিলম্বিত অ্যানিমেশন দিয়ে প্রতিস্থাপন করুন।
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 এ নেভিগেট করেন তখন ট্রানজিশন অ্যানিমেশন কাস্টমাইজ করতে। একটি FadeTransition (একটি স্পষ্টভাবে অ্যানিমেটেড উইজেট) ব্যবহার করুন যাতে নতুন স্ক্রীনটি আগের স্ক্রিনের উপরে ফেইড হয়ে যায়।
lib/home_screen.dart
ElevatedButton(
onPressed: () {
// Show the question screen to start the game
Navigator.push(
context,
PageRouteBuilder( // Add from here...
pageBuilder: (context, animation, secondaryAnimation) {
return const QuestionScreen();
},
transitionsBuilder:
(context, animation, secondaryAnimation, child) {
return FadeTransition(
opacity: animation,
child: child,
);
},
), // To here.
);
},
child: Text('New Game'),
),
অ্যানিমেশন প্যাকেজ অভিনব প্রি-বিল্ট অ্যানিমেশন প্রভাব প্রদান করে, যেমন FadeThroughTransition । অ্যানিমেশন প্যাকেজ আমদানি করুন এবং 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( // Add from here...
animation: animation,
secondaryAnimation: secondaryAnimation,
child: child,
); // To here.
},
),
);
},
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),
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( // Add from here...
builder: (context) {
return const QuestionScreen();
},
), // To here.
);
},
child: Text('New Game'),
),
বর্তমান প্রশ্ন পরিবর্তন করতে FadeThroughTransition ব্যবহার করুন
AnimatedSwitcher উইজেট তার নির্মাতা কলব্যাকে শুধুমাত্র একটি Animation প্রদান করে। এটি সমাধানের জন্য, 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( // Add from here...
layoutBuilder: (entries) {
return Stack(alignment: Alignment.topCenter, children: entries);
},
transitionBuilder: (child, animation, secondaryAnimation) {
return FadeThroughTransition(
animation: animation,
secondaryAnimation: secondaryAnimation,
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,
),
),
),
);
}
}
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);
},
),
],
),
),
);
}
}
QuestionCard উইজেটে, viewModel এবং খোলা কন্টেইনার কলব্যাকের জন্য দুটি নতুন ক্ষেত্র যোগ করে animations প্যাকেজ থেকে একটি OpenContainer উইজেট দিয়ে Card প্রতিস্থাপন করুন:
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-এর অ্যানিমেশন সিস্টেমের মূল উপাদানগুলি সম্পর্কে শিখেছেন৷ বিশেষ করে, আপনি শিখেছেন:
- কিভাবে একটি
ImplicitlyAnimatedWidgetব্যবহার করবেন - কিভাবে একটি
ExplicitlyAnimatedWidgetব্যবহার করবেন - একটি অ্যানিমেশনে
CurvesএবংTweensকীভাবে প্রয়োগ করবেন -
AnimatedSwitcherবাPageRouteBuilderমতো প্রি-বিল্ট ট্রানজিশন উইজেটগুলি কীভাবে ব্যবহার করবেন -
animationsপ্যাকেজ থেকে অভিনব প্রি-বিল্ট অ্যানিমেশন প্রভাবগুলি কীভাবে ব্যবহার করবেন, যেমনFadeThroughTransitionএবংOpenContainer - অ্যান্ড্রয়েডে ভবিষ্যদ্বাণীমূলক ব্যাক সমর্থন যোগ করা সহ ডিফল্ট ট্রানজিশন অ্যানিমেশন কীভাবে কাস্টমাইজ করবেন।

এরপর কি?
এই কোডল্যাবগুলির কয়েকটি দেখুন:
- উপাদান 3 সহ একটি অ্যানিমেটেড প্রতিক্রিয়াশীল অ্যাপ লেআউট তৈরি করা
- ফ্লটারের জন্য উপাদান গতির সাথে সুন্দর রূপান্তর তৈরি করা
- আপনার ফ্লটার অ্যাপটিকে বিরক্তিকর থেকে সুন্দরের দিকে নিয়ে যান
অথবা অ্যানিমেশন নমুনা অ্যাপ ডাউনলোড করুন, যা বিভিন্ন অ্যানিমেশন কৌশল প্রদর্শন করে।
আরও পড়া
আপনি flutter.dev এ আরও অ্যানিমেশন সংস্থান খুঁজে পেতে পারেন:
- অ্যানিমেশন পরিচিতি
- অ্যানিমেশন টিউটোরিয়াল (টিউটোরিয়াল)
- অন্তর্নিহিত অ্যানিমেশন (টিউটোরিয়াল)
- একটি পাত্রের বৈশিষ্ট্য অ্যানিমেট করুন (রান্নার বই)
- একটি উইজেট ভিতরে এবং বাইরে ফেড করুন (রান্নার বই)
- হিরো অ্যানিমেশন
- একটি পৃষ্ঠা রুট ট্রানজিশন অ্যানিমেট করুন (কুকবুক)
- একটি পদার্থবিদ্যা সিমুলেশন ব্যবহার করে একটি উইজেট অ্যানিমেট করুন (কুকবুক)
- স্তব্ধ অ্যানিমেশন
- অ্যানিমেশন এবং মোশন উইজেট (উইজেট ক্যাটালগ)
অথবা মিডিয়ামে এই নিবন্ধগুলি দেখুন:
- অ্যানিমেশন গভীর ডুব
- ফ্লটারে কাস্টম অন্তর্নিহিত অ্যানিমেশন
- Flutter এবং Flux / Redux সহ অ্যানিমেশন ব্যবস্থাপনা
- কোন ফ্লটার অ্যানিমেশন উইজেটটি আপনার জন্য সঠিক তা কীভাবে চয়ন করবেন?
- অন্তর্নির্মিত স্পষ্ট অ্যানিমেশন সহ দিকনির্দেশক অ্যানিমেশন
- অন্তর্নিহিত অ্যানিমেশন সহ ফ্লটার অ্যানিমেশনের মূল বিষয়গুলি
- আমি কখন AnimatedBuilder বা AnimatedWidget ব্যবহার করব?