1. ভূমিকা
মেটেরিয়াল ডিজাইন হল সাহসী এবং সুন্দর ডিজিটাল পণ্য তৈরির একটি সিস্টেম। নীতি এবং উপাদানগুলির একটি ধারাবাহিক সেটের অধীনে শৈলী, ব্র্যান্ডিং, মিথস্ক্রিয়া এবং গতি একত্রিত করার মাধ্যমে, পণ্য দলগুলি তাদের সর্বশ্রেষ্ঠ নকশা সম্ভাবনা উপলব্ধি করতে পারে।
মেটেরিয়াল কম্পোনেন্টস (MDC) ডেভেলপারদের ম্যাটেরিয়াল ডিজাইন বাস্তবায়নে সহায়তা করে। Google-এ প্রকৌশলী এবং UX ডিজাইনারদের একটি দল দ্বারা তৈরি, MDC কয়েক ডজন সুন্দর এবং কার্যকরী UI উপাদান বৈশিষ্ট্যযুক্ত এবং এটি Android, iOS, ওয়েব এবং Flutter.material.io/develop-এর জন্য উপলব্ধ |
ফ্লটারের জন্য উপাদানের গতি ব্যবস্থা কী?
ফ্লটারের জন্য ম্যাটেরিয়াল মোশন সিস্টেম হল অ্যানিমেশন প্যাকেজের মধ্যে পরিবর্তনের প্যাটার্নের একটি সেট যা ব্যবহারকারীদের একটি অ্যাপ বুঝতে এবং নেভিগেট করতে সাহায্য করতে পারে, যেমনটি মেটেরিয়াল ডিজাইন নির্দেশিকাতে বর্ণিত হয়েছে।
চারটি প্রধান উপাদান রূপান্তর নিদর্শন নিম্নরূপ:
- ধারক রূপান্তর: UI উপাদানগুলির মধ্যে রূপান্তর যা একটি ধারক অন্তর্ভুক্ত করে; নির্বিঘ্নে একটি উপাদানকে অন্যটিতে রূপান্তর করে দুটি স্বতন্ত্র UI উপাদানের মধ্যে একটি দৃশ্যমান সংযোগ তৈরি করে।
- ভাগ করা অক্ষ: UI উপাদানগুলির মধ্যে স্থানান্তর যা একটি স্থানিক বা নেভিগেশনাল সম্পর্ক রয়েছে; উপাদানগুলির মধ্যে সম্পর্ককে শক্তিশালী করতে x, y, বা z অক্ষে একটি ভাগ করা রূপান্তর ব্যবহার করে।
- ফেইড থ্রু: UI উপাদানগুলির মধ্যে রূপান্তর যা একে অপরের সাথে শক্তিশালী সম্পর্ক নেই; ইনকামিং এলিমেন্টের স্কেল সহ একটি অনুক্রমিক ফেইড আউট এবং ফেড ইন ব্যবহার করে।
- ফেইড: UI উপাদানগুলির জন্য ব্যবহৃত হয় যা স্ক্রিনের সীমানার মধ্যে প্রবেশ করে বা প্রস্থান করে।
ফ্লাটার অ্যানিমেশন লাইব্রেরি ( flutter/animation.dart
) এবং Flutter উপাদান লাইব্রেরি ( flutter/material.dart
) উভয়ের উপরে নির্মিত এই প্যাটার্নগুলির জন্য অ্যানিমেশন প্যাকেজ ট্রানজিশন উইজেটগুলি অফার করে :
এই কোডল্যাবে আপনি ফ্লাটার ফ্রেমওয়ার্ক এবং মেটেরিয়াল লাইব্রেরির উপরে নির্মিত ম্যাটেরিয়াল ট্রানজিশন ব্যবহার করবেন, যার অর্থ আপনি উইজেট নিয়ে কাজ করবেন। :)
আপনি কি নির্মাণ করবেন
এই কোডল্যাবটি আপনার অ্যাপের চেহারা এবং অনুভূতি কাস্টমাইজ করতে অ্যানিমেশন প্যাকেজ থেকে ট্রানজিশনগুলি কীভাবে ব্যবহার করতে পারেন তা প্রদর্শন করতে ডার্ট ব্যবহার করে উত্তর নামক একটি উদাহরণ ফ্লাটার ইমেল অ্যাপে কিছু রূপান্তর তৈরি করার মাধ্যমে আপনাকে গাইড করবে।
রিপ্লাই অ্যাপের জন্য স্টার্টার কোড প্রদান করা হবে, এবং আপনি অ্যাপটিতে নিম্নলিখিত উপাদানের রূপান্তরগুলিকে অন্তর্ভুক্ত করবেন, যা নীচে সম্পূর্ণ কোডল্যাবের জিআইএফ-এ দেখা যাবে:
- ইমেল তালিকা থেকে ইমেল বিস্তারিত পৃষ্ঠায় কনটেইনার রূপান্তর
- ইমেল পৃষ্ঠা রচনা করার জন্য FAB থেকে কনটেইনার রূপান্তর পরিবর্তন
- সার্চ আইকন থেকে সার্চ ভিউ পৃষ্ঠায় শেয়ার করা জেড-অক্ষ পরিবর্তন
- মেইলবক্স পৃষ্ঠাগুলির মধ্যে স্থানান্তরের মাধ্যমে বিবর্ণ
- কম্পোজ এবং উত্তর FAB এর মধ্যে পরিবর্তনের মাধ্যমে ফেইড
- অদৃশ্য হয়ে যাওয়া মেলবক্স শিরোনামের মধ্যে রূপান্তরের মাধ্যমে বিবর্ণ
- নিচের অ্যাপ বার অ্যাকশনের মধ্যে পরিবর্তনের মাধ্যমে ফেইড করুন
আপনি কি প্রয়োজন হবে
- ফ্লটার ডেভেলপমেন্ট এবং ডার্ট সম্পর্কে প্রাথমিক জ্ঞান
- একটি কোড সম্পাদক
- একটি Android/iOS এমুলেটর বা ডিভাইস
- নমুনা কোড (পরবর্তী ধাপ দেখুন)
ফ্লাটার অ্যাপ তৈরি করার অভিজ্ঞতার স্তরকে আপনি কীভাবে রেট করবেন?
আপনি এই কোডল্যাব থেকে কি শিখতে চান?
2. আপনার ফ্লটার ডেভেলপমেন্ট এনভায়রনমেন্ট সেট আপ করুন
এই ল্যাবটি সম্পূর্ণ করার জন্য আপনার দুটি টুকরো সফ্টওয়্যার প্রয়োজন - ফ্লাটার SDK এবং একটি সম্পাদক ৷
আপনি এই ডিভাইসগুলির যেকোনো একটি ব্যবহার করে কোডল্যাব চালাতে পারেন:
- আপনার কম্পিউটারের সাথে সংযুক্ত এবং বিকাশকারী মোডে সেট করা একটি শারীরিক Android বা iOS ডিভাইস৷
- আইওএস সিমুলেটর (এক্সকোড সরঞ্জাম ইনস্টল করা প্রয়োজন)।
- অ্যান্ড্রয়েড এমুলেটর (অ্যান্ড্রয়েড স্টুডিওতে সেটআপ প্রয়োজন)।
- একটি ব্রাউজার (ডিবাগিংয়ের জন্য Chrome প্রয়োজন)।
- একটি Windows , Linux , বা macOS ডেস্কটপ অ্যাপ্লিকেশন হিসাবে। আপনি যে প্ল্যাটফর্মে স্থাপন করার পরিকল্পনা করছেন সেখানে আপনাকে অবশ্যই বিকাশ করতে হবে। সুতরাং, আপনি যদি একটি উইন্ডোজ ডেস্কটপ অ্যাপ বিকাশ করতে চান, তাহলে যথাযথ বিল্ড চেইন অ্যাক্সেস করতে আপনাকে অবশ্যই উইন্ডোজে বিকাশ করতে হবে। অপারেটিং সিস্টেম-নির্দিষ্ট প্রয়োজনীয়তা রয়েছে যা docs.flutter.dev/desktop- এ বিস্তারিতভাবে কভার করা হয়েছে।
3. কোডল্যাব স্টার্টার অ্যাপটি ডাউনলোড করুন
বিকল্প 1: GitHub থেকে স্টার্টার কোডল্যাব অ্যাপটি ক্লোন করুন
GitHub থেকে এই কোডল্যাব ক্লোন করতে, নিম্নলিখিত কমান্ডগুলি চালান:
git clone https://github.com/material-components/material-components-flutter-motion-codelab.git cd material-components-flutter-motion-codelab
বিকল্প 2: স্টার্টার কোডল্যাব অ্যাপ জিপ ফাইলটি ডাউনলোড করুন
স্টার্টার অ্যাপটি material-components-flutter-motion-codelab-starter
ডিরেক্টরিতে রয়েছে।
প্রকল্প নির্ভরতা যাচাই করুন
প্রকল্পটি অ্যানিমেশন প্যাকেজের উপর নির্ভর করে। pubspec.yaml
এ, লক্ষ্য করুন dependencies
বিভাগে নিম্নলিখিতগুলি অন্তর্ভুক্ত রয়েছে:
animations: ^2.0.0
প্রকল্পটি খুলুন এবং অ্যাপটি চালান
- আপনার পছন্দের সম্পাদকে প্রকল্পটি খুলুন।
- Get Started: আপনার নির্বাচিত সম্পাদকের জন্য টেস্ট ড্রাইভ -এ "অ্যাপ চালাতে" নির্দেশাবলী অনুসরণ করুন।
সফলতার ! উত্তরের হোমপেজের জন্য স্টার্টার কোড আপনার ডিভাইস/এমুলেটরে চালানো উচিত। আপনার ইমেলের একটি তালিকা সম্বলিত ইনবক্স দেখতে হবে।
ঐচ্ছিক: ডিভাইস অ্যানিমেশন ধীর করুন
যেহেতু এই কোডল্যাবে দ্রুত, কিন্তু পালিশ করা ট্রানজিশন জড়িত, তাই আপনি যখন বাস্তবায়ন করছেন তখন ট্রানজিশনের কিছু সূক্ষ্ম বিবরণ পর্যবেক্ষণ করতে ডিভাইসের অ্যানিমেশনগুলিকে ধীর করে দিতে এটি কার্যকর হতে পারে। এটি একটি ইন-অ্যাপ সেটিংসের মাধ্যমে সম্পন্ন করা যেতে পারে, যখন নীচের ড্রয়ারটি খোলা থাকে তখন সেটিংস আইকনে একটি ট্যাপের মাধ্যমে অ্যাক্সেসযোগ্য৷ চিন্তা করবেন না, ডিভাইস অ্যানিমেশন ধীর করার এই পদ্ধতি রিপ্লাই অ্যাপের বাইরের ডিভাইসে অ্যানিমেশনকে প্রভাবিত করবে না।
ঐচ্ছিক: ডার্ক মোড
যদি উত্তরের উজ্জ্বল থিম আপনার চোখকে আঘাত করে, তাহলে আর তাকাবেন না। একটি অন্তর্ভূক্ত অ্যাপ সেটিংস রয়েছে যা আপনাকে অ্যাপের থিমটিকে ডার্ক মোডে পরিবর্তন করতে দেয়, যাতে আপনার চোখের জন্য আরও ভাল হয়। নিচের ড্রয়ার খোলা থাকলে সেটিংস আইকনে ট্যাপ করে এই সেটিংটি অ্যাক্সেসযোগ্য।
4. নমুনা অ্যাপ কোডের সাথে পরিচিত হন
চলুন কোড তাকান. আমরা একটি অ্যাপ প্রদান করেছি যেটি অ্যানিমেশন প্যাকেজ ব্যবহার করে অ্যাপ্লিকেশানের বিভিন্ন স্ক্রিনের মধ্যে স্থানান্তর করতে পারে৷
- হোমপেজ: নির্বাচিত মেইলবক্স প্রদর্শন করে
- ইনবক্সপেজ : ইমেলের একটি তালিকা প্রদর্শন করে
- MailPreviewCard : একটি ইমেলের পূর্বরূপ প্রদর্শন করে
- MailViewPage: একটি একক, সম্পূর্ণ ইমেল প্রদর্শন করে
- কম্পোজপেজ: একটি নতুন ইমেল রচনার অনুমতি দেয়
- অনুসন্ধান পৃষ্ঠা: একটি অনুসন্ধান দৃশ্য প্রদর্শন করে
রাউটার.ডার্ট
প্রথমত, অ্যাপের রুট নেভিগেশন কীভাবে সেটআপ করা হয় তা বুঝতে, lib
ডিরেক্টরিতে router.dart
খুলুন:
class ReplyRouterDelegate extends RouterDelegate<ReplyRoutePath>
with ChangeNotifier, PopNavigatorRouterDelegateMixin<ReplyRoutePath> {
ReplyRouterDelegate({required this.replyState})
: navigatorKey = GlobalObjectKey<NavigatorState>(replyState) {
replyState.addListener(() {
notifyListeners();
});
}
@override
final GlobalKey<NavigatorState> navigatorKey;
RouterProvider replyState;
@override
void dispose() {
replyState.removeListener(notifyListeners);
super.dispose();
}
@override
ReplyRoutePath get currentConfiguration => replyState.routePath!;
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider<RouterProvider>.value(value: replyState),
],
child: Selector<RouterProvider, ReplyRoutePath?>(
selector: (context, routerProvider) => routerProvider.routePath,
builder: (context, routePath, child) {
return Navigator(
key: navigatorKey,
onPopPage: _handlePopPage,
pages: [
// TODO: Add Shared Z-Axis transition from search icon to search view page (Motion)
const CustomTransitionPage(
transitionKey: ValueKey('Home'),
screen: HomePage(),
),
if (routePath is ReplySearchPath)
const CustomTransitionPage(
transitionKey: ValueKey('Search'),
screen: SearchPage(),
),
],
);
},
),
);
}
bool _handlePopPage(Route<dynamic> route, dynamic result) {
// _handlePopPage should not be called on the home page because the
// PopNavigatorRouterDelegateMixin will bubble up the pop to the
// SystemNavigator if there is only one route in the navigator.
assert(route.willHandlePopInternally ||
replyState.routePath is ReplySearchPath);
final bool didPop = route.didPop(result);
if (didPop) replyState.routePath = const ReplyHomePath();
return didPop;
}
@override
Future<void> setNewRoutePath(ReplyRoutePath configuration) {
replyState.routePath = configuration;
return SynchronousFuture<void>(null);
}
}
এটি আমাদের রুট নেভিগেটর, এবং এটি আমাদের অ্যাপের স্ক্রিনগুলি পরিচালনা করে যা সম্পূর্ণ ক্যানভাস যেমন HomePage
এবং SearchPage
ব্যবহার করে৷ আমরা ReplySearchPath
এ রুট সেট করেছি কিনা তা পরীক্ষা করার জন্য এটি আমাদের অ্যাপের অবস্থা শোনে। যদি আমাদের থাকে, তাহলে এটি স্ট্যাকের শীর্ষে SearchPage
সাথে আমাদের ন্যাভিগেটরকে পুনর্নির্মাণ করে। লক্ষ্য করুন যে আমাদের স্ক্রিনগুলি একটি CustomTransitionPage
মোড়ানো হয়েছে যেখানে কোনও রূপান্তর সংজ্ঞায়িত করা হয়নি৷ এটি আপনাকে কোনো কাস্টম ট্রানজিশন ছাড়াই পর্দার মধ্যে নেভিগেট করার একটি উপায় দেখায়।
home.dart
আমরা home.dart
এ _BottomAppBarActionItems
এর ভিতরে নিম্নলিখিত কাজ করে আমাদের অ্যাপের অবস্থায় ReplySearchPath
এ আমাদের রুট সেট করি:
Align(
alignment: AlignmentDirectional.bottomEnd,
child: IconButton(
icon: const Icon(Icons.search),
color: ReplyColors.white50,
onPressed: () {
Provider.of<RouterProvider>(
context,
listen: false,
).routePath = const ReplySearchPath();
},
),
);
আমাদের onPressed
প্যারামিটারে, আমরা আমাদের RouterProvider
অ্যাক্সেস করি এবং এর routePath
ReplySearchPath
এ সেট করি। আমাদের RouterProvider
আমাদের রুট নেভিগেটরদের অবস্থার উপর নজর রাখে।
mail_view_router.dart
এখন, আমাদের অ্যাপের অভ্যন্তরীণ নেভিগেশন কীভাবে সেট আপ করা হয় তা দেখুন, lib
ডিরেক্টরিতে mail_view_router.dart
খুলুন। আপনি উপরেরটির মতো একটি নেভিগেটর দেখতে পাবেন:
class MailViewRouterDelegate extends RouterDelegate<void>
with ChangeNotifier, PopNavigatorRouterDelegateMixin {
MailViewRouterDelegate({required this.drawerController});
final AnimationController drawerController;
@override
Widget build(BuildContext context) {
bool _handlePopPage(Route<dynamic> route, dynamic result) {
return false;
}
return Selector<EmailStore, String>(
selector: (context, emailStore) => emailStore.currentlySelectedInbox,
builder: (context, currentlySelectedInbox, child) {
return Navigator(
key: navigatorKey,
onPopPage: _handlePopPage,
pages: [
// TODO: Add Fade through transition between mailbox pages (Motion)
CustomTransitionPage(
transitionKey: ValueKey(currentlySelectedInbox),
screen: InboxPage(
destination: currentlySelectedInbox,
),
)
],
);
},
);
}
...
}
এটি আমাদের অভ্যন্তরীণ নেভিগেটর। এটি আমাদের অ্যাপের অভ্যন্তরীণ স্ক্রিনগুলি পরিচালনা করে যা শুধুমাত্র ক্যানভাসের মূল অংশ যেমন InboxPage
ব্যবহার করে। আমাদের অ্যাপের বর্তমান মেলবক্স কী অবস্থায় আছে তার উপর নির্ভর করে InboxPage
ইমেলের একটি তালিকা প্রদর্শন করে। ন্যাভিগেটরটিকে স্ট্যাকের উপরে সঠিক InboxPage
দিয়ে পুনর্নির্মাণ করা হয়, যখনই আমাদের অ্যাপের অবস্থার currentlySelectedInbox
সিলেক্টেড ইনবক্স প্রপার্টিতে কোনো পরিবর্তন হয়।
home.dart
আমরা home.dart
এ _HomePageState
এর ভিতরে নিম্নলিখিত কাজ করে আমাদের অ্যাপের অবস্থায় আমাদের বর্তমান মেলবক্স সেট করি:
void _onDestinationSelected(String destination) {
var emailStore = Provider.of<EmailStore>(
context,
listen: false,
);
if (emailStore.onMailView) {
emailStore.currentlySelectedEmailId = -1;
}
if (emailStore.currentlySelectedInbox != destination) {
emailStore.currentlySelectedInbox = destination;
}
setState(() {});
}
আমাদের _onDestinationSelected
ফাংশনে, আমরা আমাদের EmailStore
অ্যাক্সেস করি এবং নির্বাচিত গন্তব্যে এটির currentlySelectedInbox
সেট করি। আমাদের EmailStore
আমাদের অভ্যন্তরীণ নেভিগেটর অবস্থার উপর নজর রাখে।
home.dart
সবশেষে, একটি ন্যাভিগেশন রাউটিং ব্যবহার করা হচ্ছে তার উদাহরণ দেখতে, lib
ডিরেক্টরিতে home.dart
খুলুন। InkWell
উইজেটের onTap
সম্পত্তির ভিতরে _ReplyFabState
ক্লাসটি সনাক্ত করুন, যা দেখতে এইরকম হওয়া উচিত:
onTap: () {
Provider.of<EmailStore>(
context,
listen: false,
).onCompose = true;
Navigator.of(context).push(
PageRouteBuilder(
pageBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
) {
return const ComposePage();
},
),
);
},
এটি দেখায় কিভাবে আপনি কোনো কাস্টম ট্রানজিশন ছাড়াই ইমেল রচনা পৃষ্ঠায় নেভিগেট করতে পারেন। এই কোডল্যাব চলাকালীন, আপনি ম্যাটেরিয়াল ট্রানজিশন সেট আপ করতে রিপ্লাই এর কোডে ডুব দেবেন যা অ্যাপ জুড়ে বিভিন্ন নেভিগেশন অ্যাকশনের সাথে মিলেমিশে কাজ করে।
এখন যেহেতু আপনি স্টার্টার কোডের সাথে পরিচিত, আসুন আমাদের প্রথম রূপান্তরটি বাস্তবায়ন করি।
5. ইমেল তালিকা থেকে ইমেল বিস্তারিত পৃষ্ঠায় কনটেইনার ট্রান্সফর্ম ট্রানজিশন যোগ করুন
শুরু করার জন্য, একটি ইমেলে ক্লিক করার সময় আপনি একটি পরিবর্তন যোগ করবেন। এই নেভিগেশন পরিবর্তনের জন্য, কন্টেইনার ট্রান্সফর্ম প্যাটার্নটি উপযুক্ত, কারণ এটি একটি ধারক অন্তর্ভুক্ত UI উপাদানগুলির মধ্যে পরিবর্তনের জন্য ডিজাইন করা হয়েছে। এই প্যাটার্ন দুটি UI উপাদানের মধ্যে একটি দৃশ্যমান সংযোগ তৈরি করে।
কোনো কোড যোগ করার আগে, রিপ্লাই অ্যাপটি চালানোর চেষ্টা করুন এবং একটি ইমেলে ক্লিক করুন। এটি একটি সাধারণ জাম্প-কাট করা উচিত, যার অর্থ স্ক্রীনটি কোনও রূপান্তর ছাড়াই প্রতিস্থাপিত হয়েছে:
আগে
নিম্নলিখিত স্নিপেটে দেখানো হিসাবে mail_card_preview.dart
এর শীর্ষে অ্যানিমেশন প্যাকেজের জন্য একটি আমদানি যোগ করে শুরু করুন:
mail_card_preview.dart
import 'package:animations/animations.dart';
এখন আপনার কাছে অ্যানিমেশন প্যাকেজের জন্য একটি আমদানি আছে, আমরা আপনার অ্যাপে সুন্দর রূপান্তর যোগ করা শুরু করতে পারি। আসুন একটি StatelessWidget
ক্লাস তৈরি করে শুরু করি যা আমাদের OpenContainer
উইজেটকে রাখবে।
mail_card_preview.dart
এ, MailPreviewCard
এর ক্লাস সংজ্ঞার পরে নিম্নলিখিত কোড স্নিপেট যোগ করুন:
mail_card_preview.dart
// TODO: Add Container Transform transition from email list to email detail page (Motion)
class _OpenContainerWrapper extends StatelessWidget {
const _OpenContainerWrapper({
required this.id,
required this.email,
required this.closedChild,
});
final int id;
final Email email;
final Widget closedChild;
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return OpenContainer(
openBuilder: (context, closedContainer) {
return MailViewPage(id: id, email: email);
},
openColor: theme.cardColor,
closedShape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(0)),
),
closedElevation: 0,
closedColor: theme.cardColor,
closedBuilder: (context, openContainer) {
return InkWell(
onTap: () {
Provider.of<EmailStore>(
context,
listen: false,
).currentlySelectedEmailId = id;
openContainer();
},
child: closedChild,
);
},
);
}
}
এখন আমাদের নতুন মোড়ক ব্যবহার করা যাক. MailPreviewCard
শ্রেণির সংজ্ঞার ভিতরে আমরা আমাদের build()
ফাংশন থেকে আমাদের নতুন _OpenContainerWrapper
এর সাথে Material
উইজেটটি মোড়ানো করব:
mail_card_preview.dart
// TODO: Add Container Transform transition from email list to email detail page (Motion)
return _OpenContainerWrapper(
id: id,
email: email,
closedChild: Material(
...
আমাদের _OpenContainerWrapper
একটি InkWell
উইজেট রয়েছে এবং OpenContainer
এর রঙের বৈশিষ্ট্যগুলি এটিকে ঘেরা কন্টেইনারটির রঙ নির্ধারণ করে। অতএব, আমরা উপাদান এবং ইনকওয়েল উইজেটগুলি সরাতে পারি। ফলাফল কোড নিম্নলিখিত হিসাবে দেখায়:
mail_card_preview.dart
// TODO: Add Container Transform transition from email list to email detail page (Motion)
return _OpenContainerWrapper(
id: id,
email: email,
closedChild: Dismissible(
key: ObjectKey(email),
dismissThresholds: const {
DismissDirection.startToEnd: 0.8,
DismissDirection.endToStart: 0.4,
},
onDismissed: (direction) {
switch (direction) {
case DismissDirection.endToStart:
if (onStarredInbox) {
onStar();
}
break;
case DismissDirection.startToEnd:
onDelete();
break;
default:
}
},
background: _DismissibleContainer(
icon: 'twotone_delete',
backgroundColor: colorScheme.primary,
iconColor: ReplyColors.blue50,
alignment: Alignment.centerLeft,
padding: const EdgeInsetsDirectional.only(start: 20),
),
confirmDismiss: (direction) async {
if (direction == DismissDirection.endToStart) {
if (onStarredInbox) {
return true;
}
onStar();
return false;
} else {
return true;
}
},
secondaryBackground: _DismissibleContainer(
icon: 'twotone_star',
backgroundColor: currentEmailStarred
? colorScheme.secondary
: theme.scaffoldBackgroundColor,
iconColor: currentEmailStarred
? colorScheme.onSecondary
: colorScheme.onBackground,
alignment: Alignment.centerRight,
padding: const EdgeInsetsDirectional.only(end: 20),
),
child: mailPreview,
),
);
এই পর্যায়ে, আপনার একটি সম্পূর্ণরূপে কাজ করা পাত্রে রূপান্তর হওয়া উচিত। একটি ইমেলের উপর ক্লিক করা ইমেলের তালিকা প্রত্যাহার করার সময় তালিকা আইটেমটিকে একটি বিশদ স্ক্রিনে প্রসারিত করে। ইমেলের তালিকায় স্কেল করার সময় পিছনে টিপলে ইমেলের বিবরণের স্ক্রীনটি একটি তালিকা আইটেমে ফিরে আসে।
পরে
6. ইমেল পৃষ্ঠা রচনা করতে FAB থেকে কনটেইনার ট্রান্সফর্ম ট্রানজিশন যোগ করুন
চলুন কন্টেইনার ট্রান্সফর্ম চালিয়ে যাওয়া যাক এবং ফ্লোটিং অ্যাকশন বোতাম থেকে ComposePage
একটি রূপান্তর যোগ করুন যা ব্যবহারকারীর দ্বারা লেখা একটি নতুন ইমেলে FAB-কে প্রসারিত করে। প্রথমে, অ্যাপটি পুনরায় চালান এবং ইমেল রচনা স্ক্রীনটি চালু করার সময় কোন রূপান্তর নেই তা দেখতে FAB-এ ক্লিক করুন।
আগে
আমরা যেভাবে এই ট্রানজিশনটি কনফিগার করি সেটি শেষ ধাপে আমরা যেভাবে করেছিলাম তার অনুরূপ হবে, যেহেতু আমরা একই উইজেট ক্লাস, OpenContainer
ব্যবহার করছি।
home.dart
এ, ফাইলের শীর্ষে package:animations/animations.dart
আমদানি করি এবং _ReplyFabState
build()
পদ্ধতি পরিবর্তন করি। ফিরে আসা Material
উইজেটটিকে একটি OpenContainer
উইজেট দিয়ে মোড়ানো যাক:
home.dart
// TODO: Add Container Transform from FAB to compose email page (Motion)
return OpenContainer(
openBuilder: (context, closedContainer) {
return const ComposePage();
},
openColor: theme.cardColor,
onClosed: (success) {
Provider.of<EmailStore>(
context,
listen: false,
).onCompose = false;
},
closedShape: circleFabBorder,
closedColor: theme.colorScheme.secondary,
closedElevation: 6,
closedBuilder: (context, openContainer) {
return Material(
color: theme.colorScheme.secondary,
...
আমাদের পূর্ববর্তী OpenContainer
উইজেট কনফিগার করতে ব্যবহৃত পরামিতিগুলি ছাড়াও, onClosed
এখন সেট করা হচ্ছে। onClosed
হল একটি ClosedCallback
যেটিকে বলা হয় যখন OpenContainer
রুট পপ করা হয় বা বন্ধ অবস্থায় ফিরে আসে। সেই লেনদেনের রিটার্ন মান একটি আর্গুমেন্ট হিসাবে এই ফাংশনে পাস করা হয়। আমরা আমাদের অ্যাপের প্রদানকারীকে সূচিত করতে এই Callback
ব্যবহার করি যে আমরা ComposePage
রুটটি ছেড়েছি, যাতে এটি সমস্ত শ্রোতাদেরকে অবহিত করতে পারে।
আমাদের শেষ ধাপের জন্য আমরা যা করেছি তার অনুরূপ, আমরা আমাদের উইজেট থেকে Material
উইজেটটি সরিয়ে ফেলব যেহেতু OpenContainer
উইজেট ক্লোজড closedBuilder
দ্বারা closedColor
দ্বারা ফিরে আসা উইজেটের রঙ পরিচালনা করে। আমরা আমাদের InkWell উইজেটের onTap
এর ভিতরের আমাদের Navigator.push()
কলটিও সরিয়ে দেব এবং openContainer() Callback
OpenContainer
উইজেটের closedBuilder
দ্বারা প্রদত্ত কলব্যাকের সাথে প্রতিস্থাপন করব, যেহেতু এখন OpenContainer
উইজেট তার নিজস্ব রাউটিং পরিচালনা করছে।
ফলাফল কোড নিম্নরূপ:
home.dart
// TODO: Add Container Transform from FAB to compose email page (Motion)
return OpenContainer(
openBuilder: (context, closedContainer) {
return const ComposePage();
},
openColor: theme.cardColor,
onClosed: (success) {
Provider.of<EmailStore>(
context,
listen: false,
).onCompose = false;
},
closedShape: circleFabBorder,
closedColor: theme.colorScheme.secondary,
closedElevation: 6,
closedBuilder: (context, openContainer) {
return Tooltip(
message: tooltip,
child: InkWell(
customBorder: circleFabBorder,
onTap: () {
Provider.of<EmailStore>(
context,
listen: false,
).onCompose = true;
openContainer();
},
child: SizedBox(
height: _mobileFabDimension,
width: _mobileFabDimension,
child: Center(
child: fabSwitcher,
),
),
),
);
},
);
এখন কিছু পুরানো কোড পরিষ্কার করতে. যেহেতু আমাদের OpenContainer
উইজেট এখন আমাদের অ্যাপের প্রদানকারীকে সূচিত করে যে আমরা onClosed ClosedCallback
এর মাধ্যমে ComposePage
নেই, তাই আমরা mail_view_router.dart
এ আমাদের পূর্ববর্তী বাস্তবায়ন মুছে ফেলতে পারি।
mail_view_router.dart
// TODO: Add Container Transform from FAB to compose email page (Motion)
emailStore.onCompose = false; /// delete this line
return SynchronousFuture<bool>(true);
এই পদক্ষেপের জন্য এটি! নিচের মত দেখতে স্ক্রীন রচনা করতে আপনার FAB থেকে একটি রূপান্তর হওয়া উচিত:
পরে
7. সার্চ ভিউ পেজে সার্চ আইকন থেকে শেয়ার্ড জেড-অ্যাক্সিস ট্রানজিশন যোগ করুন
এই ধাপে, আমরা সার্চ আইকন থেকে পূর্ণ স্ক্রীন সার্চ ভিউতে একটি রূপান্তর যোগ করব। যেহেতু এই ন্যাভিগেশন পরিবর্তনের সাথে জড়িত কোন স্থায়ী ধারক নেই, তাই আমরা দুটি স্ক্রিনের মধ্যে স্থানিক সম্পর্ককে শক্তিশালী করতে একটি শেয়ার্ড জেড-অ্যাক্সিস ট্রানজিশন ব্যবহার করতে পারি এবং অ্যাপের শ্রেণিবিন্যাসের মধ্যে একটি স্তর উপরের দিকে নিয়ে যাওয়ার ইঙ্গিত দিতে পারি।
অতিরিক্ত কোড যোগ করার আগে, অ্যাপটি চালানোর চেষ্টা করুন এবং স্ক্রিনের নীচের ডানদিকে কোণায় অনুসন্ধান আইকনে আলতো চাপুন। এটি কোনো ট্রানজিশন ছাড়াই সার্চ ভিউ স্ক্রীন আনতে হবে।
আগে
শুরু করতে, আসুন আমাদের router.dart
ফাইলে যাই। আমাদের ReplySearchPath
ক্লাস সংজ্ঞার পরে নিম্নলিখিত স্নিপেট যোগ করুন:
রাউটার.ডার্ট
// TODO: Add Shared Z-Axis transition from search icon to search view page (Motion)
class SharedAxisTransitionPageWrapper extends Page {
const SharedAxisTransitionPageWrapper(
{required this.screen, required this.transitionKey})
: super(key: transitionKey);
final Widget screen;
final ValueKey transitionKey;
@override
Route createRoute(BuildContext context) {
return PageRouteBuilder(
settings: this,
transitionsBuilder: (context, animation, secondaryAnimation, child) {
return SharedAxisTransition(
fillColor: Theme.of(context).cardColor,
animation: animation,
secondaryAnimation: secondaryAnimation,
transitionType: SharedAxisTransitionType.scaled,
child: child,
);
},
pageBuilder: (context, animation, secondaryAnimation) {
return screen;
});
}
}
এখন, আমাদের কাঙ্খিত রূপান্তরটি অর্জন করতে আমাদের নতুন SharedAxisTransitionPageWrapper
ব্যবহার করা যাক। আমাদের ReplyRouterDelegate
শ্রেণীর সংজ্ঞার ভিতরে, pages
সম্পত্তির অধীনে, আসুন একটি CustomTransitionPage
এর পরিবর্তে একটি SharedAxisTransitionPageWrapper
দিয়ে আমাদের অনুসন্ধান স্ক্রীনটি মুড়ে দেই:
রাউটার.ডার্ট
return Navigator(
key: navigatorKey,
onPopPage: _handlePopPage,
pages: [
// TODO: Add Shared Z-Axis transition from search icon to search view page (Motion)
const CustomTransitionPage(
transitionKey: ValueKey('Home'),
screen: HomePage(),
),
if (routePath is ReplySearchPath)
const SharedAxisTransitionPageWrapper(
transitionKey: ValueKey('Search'),
screen: SearchPage(),
),
],
);
এখন অ্যাপটি পুনরায় চালানোর চেষ্টা করুন।
জিনিসগুলি দুর্দান্ত দেখতে শুরু করছে! আপনি যখন নীচের অ্যাপ বারে অনুসন্ধান আইকনে ক্লিক করেন, তখন একটি ভাগ করা অক্ষ স্থানান্তর অনুসন্ধান পৃষ্ঠাটিকে দৃশ্যে স্কেল করে। যাইহোক, লক্ষ্য করুন কিভাবে হোম পেজটি স্কেল করা হয় না এবং সার্চ পেজ এর উপর স্কেল করার সাথে সাথে স্থির থাকে। উপরন্তু, পিছনের বোতাম টিপলে, হোম পৃষ্ঠাটি দৃশ্যের মধ্যে স্কেল করে না, পরিবর্তে এটি স্থির থাকে কারণ অনুসন্ধান পৃষ্ঠাটি দৃশ্যের বাইরে চলে যায়। তাই আমরা এখনও সম্পন্ন করছি না.
আসুন একটি CustomTransitionPage
এর পরিবর্তে আমাদের SharedAxisTransitionWrapper
দিয়ে HomePage
মোড়ানোর মাধ্যমে উভয় সমস্যাই ঠিক করি:
রাউটার.ডার্ট
return Navigator(
key: navigatorKey,
onPopPage: _handlePopPage,
pages: [
// TODO: Add Shared Z-Axis transition from search icon to search view page (Motion)
const SharedAxisTransitionPageWrapper(
transitionKey: ValueKey('home'),
screen: HomePage(),
),
if (routePath is ReplySearchPath)
const SharedAxisTransitionPageWrapper(
transitionKey: ValueKey('search'),
screen: SearchPage(),
),
],
);
তাই তো! এখন অ্যাপটি পুনরায় চালানোর চেষ্টা করুন এবং অনুসন্ধান আইকনে আলতো চাপুন। হোম এবং সার্চ ভিউ স্ক্রীনগুলি একই সাথে Z-অক্ষ বরাবর বিবর্ণ এবং স্কেল করা উচিত, যা দুটি পর্দার মধ্যে একটি বিরামহীন প্রভাব তৈরি করে।
পরে
8. মেলবক্স পৃষ্ঠাগুলির মধ্যে স্থানান্তরের মাধ্যমে ফেড যোগ করুন৷
এই ধাপে, আমরা বিভিন্ন মেলবক্সের মধ্যে একটি পরিবর্তন যোগ করব। যেহেতু আমরা স্থানিক বা শ্রেণিবদ্ধ সম্পর্কের উপর জোর দিতে চাই না, তাই ইমেলের তালিকার মধ্যে একটি সাধারণ "অদলবদল" করতে আমরা একটি ফেড থ্রু ব্যবহার করব।
কোনও অতিরিক্ত কোড যোগ করার আগে, অ্যাপটি চালানোর চেষ্টা করুন, নীচের অ্যাপ বারে উত্তর লোগোতে আলতো চাপুন এবং মেলবক্সগুলি স্যুইচ করুন৷ ইমেলের তালিকা কোন পরিবর্তন ছাড়াই পরিবর্তন করা উচিত।
আগে
শুরু করতে, আসুন আমাদের mail_view_router.dart
ফাইলে যাই। আমাদের MailViewRouterDelegate
ক্লাস সংজ্ঞার পরে নিম্নলিখিত স্নিপেট যোগ করুন:
mail_view_router.dart
// TODO: Add Fade through transition between mailbox pages (Motion)
class FadeThroughTransitionPageWrapper extends Page {
const FadeThroughTransitionPageWrapper({
required this.mailbox,
required this.transitionKey,
}) : super(key: transitionKey);
final Widget mailbox;
final ValueKey transitionKey;
@override
Route createRoute(BuildContext context) {
return PageRouteBuilder(
settings: this,
transitionsBuilder: (context, animation, secondaryAnimation, child) {
return FadeThroughTransition(
fillColor: Theme.of(context).scaffoldBackgroundColor,
animation: animation,
secondaryAnimation: secondaryAnimation,
child: child,
);
},
pageBuilder: (context, animation, secondaryAnimation) {
return mailbox;
});
}
}
আমাদের শেষ ধাপের মতো, আমরা যে রূপান্তর চাই তা অর্জন করতে আমাদের নতুন FadeThroughTransitionPageWrapper
ব্যবহার করি। আমাদের MailViewRouterDelegate
শ্রেণীর সংজ্ঞার ভিতরে, pages
সম্পত্তির অধীনে, একটি CustomTransitionPage
দিয়ে আমাদের মেলবক্স স্ক্রীন মোড়ানোর পরিবর্তে, পরিবর্তে FadeThroughTransitionPageWrapper
ব্যবহার করুন:
mail_view_router.dart
return Navigator(
key: navigatorKey,
onPopPage: _handlePopPage,
pages: [
// TODO: Add Fade through transition between mailbox pages (Motion)
FadeThroughTransitionPageWrapper(
mailbox: InboxPage(destination: currentlySelectedInbox),
transitionKey: ValueKey(currentlySelectedInbox),
),
],
);
অ্যাপটি আবার চালান। আপনি যখন নীচের নেভিগেশন ড্রয়ারটি খুলবেন এবং মেলবক্সগুলি পরিবর্তন করবেন, তখন ইমেলের বর্তমান তালিকাটি বিবর্ণ হওয়া উচিত এবং স্কেল করা উচিত যখন নতুন তালিকাটি বিবর্ণ এবং স্কেল করা হবে। চমৎকার!
পরে
9. রচনা এবং উত্তর FAB এর মধ্যে পরিবর্তনের মাধ্যমে ফেড যোগ করুন
এই ধাপে, আমরা বিভিন্ন FAB আইকনের মধ্যে একটি পরিবর্তন যোগ করব। যেহেতু আমরা স্থানিক বা শ্রেণিবদ্ধ সম্পর্কের উপর জোর দিতে চাই না, তাই আমরা FAB-এর আইকনগুলির মধ্যে একটি সাধারণ "অদলবদল" করতে একটি ফেড থ্রু ব্যবহার করব৷
কোনও অতিরিক্ত কোড যোগ করার আগে, অ্যাপটি চালানোর চেষ্টা করুন, একটি ইমেলে আলতো চাপুন এবং ইমেল ভিউ খুলুন। FAB আইকন পরিবর্তন ছাড়াই পরিবর্তন করা উচিত।
আগে
কোডল্যাবের বাকি অংশের জন্য আমরা home.dart
এ কাজ করব, তাই অ্যানিমেশন প্যাকেজের জন্য আমদানি যোগ করার বিষয়ে চিন্তা করবেন না যেহেতু আমরা ইতিমধ্যেই home.dart
এর জন্য 2 ধাপে ফিরে এসেছি।
আমরা যেভাবে পরবর্তী কয়েকটি ট্রানজিশন কনফিগার করব তা খুব একই রকম হবে, যেহেতু তারা সবাই একটি পুনঃব্যবহারযোগ্য ক্লাস ব্যবহার করবে, _FadeThroughTransitionSwitcher
।
home.dart
এ আসুন _ReplyFabState
অধীনে নিম্নলিখিত স্নিপেট যোগ করি:
home.dart
// TODO: Add Fade through transition between compose and reply FAB (Motion)
class _FadeThroughTransitionSwitcher extends StatelessWidget {
const _FadeThroughTransitionSwitcher({
required this.fillColor,
required this.child,
});
final Widget child;
final Color fillColor;
@override
Widget build(BuildContext context) {
return PageTransitionSwitcher(
transitionBuilder: (child, animation, secondaryAnimation) {
return FadeThroughTransition(
fillColor: fillColor,
child: child,
animation: animation,
secondaryAnimation: secondaryAnimation,
);
},
child: child,
);
}
}
এখন, আমাদের _ReplyFabState
এ, fabSwitcher
উইজেটটি সন্ধান করুন। fabSwitcher
এটি ইমেল ভিউতে আছে কি না তার উপর ভিত্তি করে একটি ভিন্ন আইকন প্রদান করে। আসুন এটিকে আমাদের _FadeThroughTransitionSwitcher
দিয়ে মোড়ানো যাক:
home.dart
// TODO: Add Fade through transition between compose and reply FAB (Motion)
static final fabKey = UniqueKey();
static const double _mobileFabDimension = 56;
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final circleFabBorder = const CircleBorder();
return Selector<EmailStore, bool>(
selector: (context, emailStore) => emailStore.onMailView,
builder: (context, onMailView, child) {
// TODO: Add Fade through transition between compose and reply FAB (Motion)
final fabSwitcher = _FadeThroughTransitionSwitcher(
fillColor: Colors.transparent,
child: onMailView
? Icon(
Icons.reply_all,
key: fabKey,
color: Colors.black,
)
: const Icon(
Icons.create,
color: Colors.black,
),
);
...
আমরা আমাদের _FadeThroughTransitionSwitcher
একটি স্বচ্ছ fillColor
দিই, তাই ট্রানজিশন করার সময় উপাদানগুলির মধ্যে কোন পটভূমি নেই। এছাড়াও আমরা একটি UniqueKey
তৈরি করি এবং এটিকে আইকনের একটিতে বরাদ্দ করি।
এখন, এই ধাপে, আপনার একটি সম্পূর্ণ অ্যানিমেটেড প্রাসঙ্গিক FAB থাকা উচিত। একটি ইমেল ভিউতে যাওয়ার ফলে পুরানো FAB আইকনটি বিবর্ণ হয়ে যায় এবং স্কেল আউট হয়ে যায় যখন নতুনটি বিবর্ণ হয়ে যায় এবং স্কেল হয়ে যায়।
পরে
10. অদৃশ্য হয়ে যাওয়া মেলবক্স শিরোনামের মধ্যে পরিবর্তনের মাধ্যমে ফেড যোগ করুন
এই ধাপে, আমরা একটি ইমেল ভিউতে থাকাকালীন একটি দৃশ্যমান এবং অদৃশ্য অবস্থার মধ্যে মেলবক্স শিরোনামের মাধ্যমে বিবর্ণ করার জন্য রূপান্তরের মাধ্যমে একটি ফেড যোগ করব৷ যেহেতু আমরা একটি স্থানিক বা শ্রেণিবদ্ধ সম্পর্কের উপর জোর দিতে চাই না, তাই আমরা মেইলবক্স শিরোনাম এবং একটি খালি SizedBox
জুড়ে থাকা Text
উইজেটের মধ্যে একটি সাধারণ "অদলবদল" সম্পাদন করতে একটি ফেড থ্রু ব্যবহার করব।
কোনও অতিরিক্ত কোড যোগ করার আগে, অ্যাপটি চালানোর চেষ্টা করুন, একটি ইমেলে আলতো চাপুন এবং ইমেল ভিউ খুলুন। মেইলবক্স শিরোনাম একটি রূপান্তর ছাড়াই অদৃশ্য হওয়া উচিত।
আগে
এই কোডল্যাবের বাকিটা দ্রুত হবে কারণ আমরা ইতিমধ্যেই আমাদের শেষ ধাপে আমাদের _FadeThroughTransitionSwitcher
এ বেশিরভাগ কাজ করে ফেলেছি।
এখন, আমাদের স্থানান্তর যোগ করতে home.dart
এ আমাদের _AnimatedBottomAppBar
ক্লাসে যাওয়া যাক। আমরা আমাদের শেষ ধাপ থেকে _FadeThroughTransitionSwitcher
পুনরায় ব্যবহার করব, এবং আমাদের onMailView
শর্তসাপেক্ষে মোড়ানো হবে, যা হয় একটি খালি SizedBox
ফেরত দেয়, অথবা একটি মেলবক্স শিরোনাম যা নীচের ড্রয়ারের সাথে সিঙ্কে বিবর্ণ হয়:
home.dart
...
const _ReplyLogo(),
const SizedBox(width: 10),
// TODO: Add Fade through transition between disappearing mailbox title (Motion)
_FadeThroughTransitionSwitcher(
fillColor: Colors.transparent,
child: onMailView
? const SizedBox(width: 48)
: FadeTransition(
opacity: fadeOut,
child: Selector<EmailStore, String>(
selector: (context, emailStore) =>
emailStore.currentlySelectedInbox,
builder: (
context,
currentlySelectedInbox,
child,
) {
return Text(
currentlySelectedInbox,
style: Theme.of(context)
.textTheme
.bodyMedium!
.copyWith(
color: ReplyColors.white50,
),
);
},
),
),
),
এটাই, আমরা এই পদক্ষেপটি সম্পন্ন করেছি!
অ্যাপটি আবার চালান। আপনি যখন একটি ইমেল খুলবেন এবং ইমেল ভিউতে নিয়ে যাবেন, তখন নীচের অ্যাপ বারে মেলবক্সের শিরোনামটি বিবর্ণ হওয়া উচিত এবং স্কেল করা উচিত। অসাধারন!
পরে
11. নিচের অ্যাপ বার অ্যাকশনের মধ্যে পরিবর্তনের মাধ্যমে ফেইড যোগ করুন
এই ধাপে, আমরা অ্যাপ্লিকেশান প্রসঙ্গের উপর ভিত্তি করে নীচের অ্যাপ বার অ্যাকশনগুলির মাধ্যমে বিবর্ণ করার জন্য ট্রানজিশনের মাধ্যমে একটি ফেড যোগ করব। যেহেতু আমরা একটি স্থানিক বা শ্রেণিবদ্ধ সম্পর্কের উপর জোর দিতে চাই না, আমরা যখন অ্যাপটি হোমপেজে থাকে, যখন নীচের ড্রয়ারটি দৃশ্যমান হয় এবং নীচের অ্যাপ বার ক্রিয়াগুলির মধ্যে একটি সাধারণ "অদলবদল" করতে আমরা একটি ফেড থ্রু ব্যবহার করব যখন আমরা ইমেল ভিউতে থাকি।
কোনও অতিরিক্ত কোড যোগ করার আগে, অ্যাপটি চালানোর চেষ্টা করুন, একটি ইমেলে আলতো চাপুন এবং ইমেল ভিউ খুলুন। আপনি উত্তর লোগোতে ট্যাপ করার চেষ্টা করতে পারেন। নীচের অ্যাপ বার অ্যাকশনগুলি পরিবর্তন ছাড়াই পরিবর্তন করা উচিত।
আগে
শেষ ধাপের মতো, আমরা আবার আমাদের _FadeThroughTransitionSwitcher
ব্যবহার করব। কাঙ্খিত রূপান্তরটি অর্জন করতে আমাদের _BottomAppBarActionItems
শ্রেণীর সংজ্ঞাতে যান এবং একটি _FadeThroughTransitionSwitcher
দিয়ে আমাদের build()
ফাংশনের রিটার্ন উইজেটটি মোড়ানো করুন:
home.dart
// TODO: Add Fade through transition between bottom app bar actions (Motion)
return _FadeThroughTransitionSwitcher(
fillColor: Colors.transparent,
child: drawerVisible
? Align(
key: UniqueKey(),
alignment: AlignmentDirectional.bottomEnd,
child: IconButton(
icon: const Icon(Icons.settings),
color: ReplyColors.white50,
onPressed: () async {
drawerController.reverse();
showModalBottomSheet(
context: context,
shape: RoundedRectangleBorder(
borderRadius: modalBorder,
),
builder: (context) => const SettingsBottomSheet(),
);
},
),
)
: onMailView
...
এখন এর চেষ্টা করা যাক! আপনি যখন একটি ইমেল খুলবেন এবং ইমেল ভিউতে নিয়ে যাবেন, তখন পুরানো নীচের অ্যাপ বার অ্যাকশনগুলি বিবর্ণ হওয়া উচিত এবং স্কেল করা উচিত যখন নতুন অ্যাকশনগুলি বিবর্ণ হয়ে যায় এবং স্কেল করা হয়।
পরে
12. অভিনন্দন!
ডার্ট কোডের 100 টিরও কম লাইন ব্যবহার করে, অ্যানিমেশন প্যাকেজ আপনাকে একটি বিদ্যমান অ্যাপে সুন্দর রূপান্তর তৈরি করতে সাহায্য করেছে যা মেটেরিয়াল ডিজাইন নির্দেশিকাগুলির সাথে সামঞ্জস্যপূর্ণ এবং সমস্ত ডিভাইস জুড়ে ধারাবাহিকভাবে দেখায় এবং আচরণ করে।
পরবর্তী পদক্ষেপ
ম্যাটেরিয়াল মোশন সিস্টেম সম্পর্কে আরও তথ্যের জন্য, নির্দেশিকা এবং সম্পূর্ণ ডেভেলপার ডকুমেন্টেশন পরীক্ষা করে দেখতে ভুলবেন না এবং আপনার অ্যাপে কিছু ম্যাটেরিয়াল ট্রানজিশন যোগ করার চেষ্টা করুন!
উপাদান গতি চেষ্টা করার জন্য ধন্যবাদ. আমরা আশা করি আপনি এই কোডল্যাব উপভোগ করেছেন!
আমি যুক্তিসঙ্গত সময় এবং প্রচেষ্টার সাথে এই কোডল্যাবটি সম্পূর্ণ করতে সক্ষম হয়েছি
আমি ভবিষ্যতে মেটেরিয়াল মোশন সিস্টেম ব্যবহার চালিয়ে যেতে চাই
ফ্লটার গ্যালারি দেখুন
মেটেরিয়াল ফ্লাটার লাইব্রেরি দ্বারা প্রদত্ত উইজেটগুলি কীভাবে ব্যবহার করতে হয় সে সম্পর্কে আরও ডেমোর জন্য, পাশাপাশি ফ্লাটার ফ্রেমওয়ার্ক ফ্লাটার গ্যালারিতে যেতে ভুলবেন না। |