Kriptofolio app series - Part 2
তাহলে আপনি আসলে কীভাবে একটি নতুন অ্যাপ বানানো শুরু করবেন? আপনার প্রথম মুভ কী হওয়া উচিত? আপনি যদি চিন্তা করেন আমাদের শুধু Android Studio লঞ্চ করে সরাসরি কোডে যেতে হবে, আবার চিন্তা করুন। সেটি ঠিক সেই কাজ যা আমি পরামর্শ দেব না করবেন কারণ এটি ভালোর চেয়ে বাড়তি ক্ষতি করতে পারে। কিন্তু এটি খুব প্রলোভনীয় যে যত দ্রুত সম্ভব আপনার কোডের প্রথম লাইন লিখতে শুরু করুন।
বদলে আমি পরামর্শ দেব UI mockups সহ একটি বুদ্ধিমান পরিকল্পনা তৈরি করার ওপর ফোকাস করার জন্য। মনে রাখবেন যে প্রতিটি ভালো নতুন অ্যাপ প্রজেক্ট সেটি দিয়ে শুরু হওয়া উচিত। এই অপ্রোচের সাথে আপনি অনেক সময় নষ্ট করবেন না এবং শুরু থেকেই হাই কোয়ালিটি প্রোডাক্ট বানাতে পারবেন।
তাই সিরিজের এই পার্টে, আমি "Kriptofolio" (পূর্বে "My Crypto Coins") অ্যাপের mockups উপস্থাপন করব এবং কীভাবে সেগুলো তৈরি করবেন তা আলোচনা করব। এছাড়া আমরা সকল UI লেআউট বিল্ড করব। এই লেআউটগুলো আমাদের স olid ফাউন্ডেশন হবে যা স্পষ্টভাবে ইঙ্গিত করবে কী কোড করতে হবে। শেষে আমরা আমাদের অ্যাপকে বিভিন্ন ভাষায় লোকালাইজ করব এবং রাইট-টু-লেফট (RTL) লিখিত ভাষাগুলো হ্যান্ডল করার পদ্ধতি শিখব।
Series content
- Introduction: A roadmap to build a modern Android app in 2018–2019
- Part 1: An introduction to the SOLID principles
- Part 2: How to start building your Android app: creating Mockups, UI, and XML layouts (you’re here)
- Part 3: All about that Architecture: exploring different architecture patterns and how to use them in your app
- Part 4: How to implement Dependency Injection in your app with Dagger 2
- Part 5: Handle RESTful Web Services using Retrofit, OkHttp, Gson, Glide and Coroutines
Mockups
আপনার প্রজেক্ট mockups তৈরি করার বিভিন্ন উপায় আছে। সবচেয়ে সিম্পলটি হলো একটি পেনসিল এবং একটি কাগজের কাগজ নিয়ে অঙ্কন শুরু করা। এই পদ্ধতির সেরা অংশ হচ্ছে এটি আপনাকে কিছু খরচ করবে না এবং আপনি তৎক্ষণাৎ শুরু করতে পারেন। ও হ্যা, আমি প্রায় ভুলে গেছিলাম, আপনার একটি ইরেজারও নিতে হবে কারণ এখানে কোনো undo ফাংশন থাকবে না। ?
আপনি যদি আমার মত অনুভব করেন যে আপনাকে আরও ফাংশন্যালিটি দরকার, তবে ডিটেইল্ড mockups তৈরির জন্য বিশেষ সফটওয়্যার ব্যবহার করার কথা ভাবুন। আমি পেনসিল ও কাগজের বদলে সফটওয়্যার ব্যবহার করা পছন্দ করি, যদিও এতে আপনার টাকা খরচ করে কিনতে হয় এবং শিখতে সময় লাগে।
বাজারে mockups তৈরির জন্য বিভিন্ন সফটওয়্যার অপশন আছে। আপনাকে নিজের থেকে 조사 করতে হবে কোনটি আপনার সব চাহিদা পুর্টি করে। আমার সকল প্রজেক্টের mockups এখন আমি Balsamiq Mockups for Desktop app ব্যবহার করি। Balsamiq দ্রুত, ইফেক্টিভ এবং খুব সহজে ব্যবহারযোগ্য wire framing সফটওয়্যার। যেহেতু আমি এট سے খুব খুশি, আমি Android অ্যাপের জন্য এটি রিকমেন্ড করি, তাই দয়া করে ট্রাই করুন।
আমি My Crypto Coins অ্যাপ প্রজেক্ট শুরু করলাম ভালোভাবে চিন্তা করা এবং খুব ডিটেইল্ড mockups তৈরি করে। আমি মনে করলাম যদি আমি সব কিছু খুব ডিটেইল্ডভাবে তৈরি করি, তবে আমি ভুল এড়াতে পারব। ডেভেলপমেন্ট প্রসেসের সময় হঠাৎ ফাংশন্যালিটি পরিবর্তনের জন্য সময় নষ্ট করব না। আপনি যদি ভালো mockups তৈরি করার জন্য প্রচুর পরিশ্রম করেন, তবে একটু কল্পনাশক্তির সাথে আপনি চূড়ান্ত প্রোডাক্টকে দেখে ও অনুভব করতে পারবেন।
আমার লক্ষ্য ছিল mockups-এ সব কিছু ডিফাইন করা যেন চূড়ান্ত প্রোডাক্টে কেমন দেখাবে। সেটির জন্য আমি হরিয়ে না যেন জরুরি পরিমাণ সময় খরচ করলাম। এখানে My Crypto Coins অ্যাপের আমার চূড়ান্ত mockups:
Stock design — Material
বিবেচনা করার আরেকটি গুরুত্বপূর্ণ বিষয় হলো অ্যাপের ভিজুয়াল ডিজাইন। এই লেখা লিখতে সময়, Material Design হলো Google দ্বারা সকল Android অ্যাপের জন্য রিকমেন্ডেড স্টক ভিজুয়াল ডিজাইন। এবং আশ्चর্য — স্টক ডিজাইন দিয়ে আপনি ভুল করতে পারবেন না।
My Crypto Coins অ্যাপে আমরা Material Design ব্যবহার করব। অ্যাপটি ডিটেইল্ড অনলাইন গাইডলাইনে ডিফাইন করা বেস্ট প্র্যাক্টিস ফলো করে।
Material.io/guidelines — অফিসিয়াল ম্যাটেরিয়াল ডিজাইন লিভিং স্পেক্স ডকুমেন্ট যা আমাদের এই প্রজেক্টের ডিজাইন গাইডলাইন হবে।
Layouts
এখন যখন আমাদের অ্যাপের wireframes রেডি, আসল UI বানানোর সময়। আবার আমরা কোড লিখতে যেতে পারি, কিন্তু কেন হরিয়ে যাব? বদলে আমি পরামর্শ দেব আপনার সকল XML লেআউট বিল্ড করার ওপর কনসেন্ট্রেট করার জন্য। আমার পরামর্শ এখানে হচ্ছে আপনি XML-এ যত বেশি রাখতে পারবেন उतনাই কম কোড লিখতে হবে।
Android টিম συνεχে আপনার UI বানানোর পদ্ধতি উন্নত করছে XML লেআউটে নতুন ফিচার যোগ করে। কখনো কখনো কিছু লাইন কোড লিখে desired look পাওয়া খুব প্রলোভনীয়। তবে টপিকটি আরও গভীরে Исслед করা ভালো যেন বুঝতে পারেন কোড ছাড়া কি করা সম্ভব। মনে রাখবেন: কম কোড আপনার প্রজেক্টকে ক্লিন করে তোলে। এছাড়া এটি অন্য ডেভেলপারদের জন্য আরও বোঝাপড়া সহজ এবং মেইনটেইন করা সহজ।
শেষে যখন আপনি সকল XML লেআউট তৈরি করবেন, আপনি অনুভব করবেন আপনার অ্যাপ বানানো হয়েছে। আপনি এটিকে লঞ্চ করতে পারবেন এবং দেখতে পারবেন এন্ড ইউজারের জন্য কেমন লাগে। এটা মানে না যে এটি ফেক ডেটা দেখাচ্ছে এবং কিছু করছে না। এখন আপনার লাস্ট চান্স আছে কিছু ড্রাস্টিক পরিবর্তন আনার।
আপনি যদি অন্য কারো জন্য অ্যাপ বানান, এটা উপস্থাপন করার খুব ভালো সময়। হয়তো আপনাকে কিছু চমকপ্রদ লাস্ট মিনিট পরিবর্তন করতে বলা হবে। তখন আপনি এমন ফাংশন্যালিটির জন্য কোড লিখতে বাঁচবেন যা কখনো ব্যবহার হবে না। অনেক মানুষের যথেষ্ট কল্পনাশক্তি নেই এবং তারা দেখে ও স্পর্শ করে প্রথমে ডিসাইড করে কি তারা চায়। তাই আপনার লেআউটগুলো আপনার ওয়ার্ক প্রসেসের লাস্ট স্টেপে না রেখে দিন।
এই অ্যাপের জন্য আমি বিভিন্ন কম্পোনেন্ট ব্যবহার করব যা সকল মডার্ন Android অ্যাপে কমন:
- CoordinatorLayout — একটি সুপার-পাওয়ারড FrameLayout, যার প্রধান আকর্ষণ হলো এর ভিতরের ভিউদের অ্যানিমেশন এবং ট্রানজিশন কোঅর্ডিনেট করার ক্ষমতা।
- AppBarLayout — একটি ভার্টিক্যাল LinearLayout যা ম্যাটেরিয়াল ডিজাইনের অ্যাপ বার কনসেপ্টের অনেক ফিচার ইমপ্লিমেন্ট করে, বিশেষ করে স্ক্রোলিং gesture।
- Toolbar — অ্যাপ্লিকেশন লেআউটে ব্যবহারের জন্য action bars-এর জেনারেলাইজেশন।
- CollapsingToolbarLayout — Toolbar-এর একটি র্যাপার যা একটি collapsing app bar ইমপ্লিমেন্ট করে। এটি AppBarLayout-এর ডায়রেক্ট চাইল্ড হিসেবে ব্যবহার করার জন্য ডিজাইন করা হয়েছে।
- ConstraintLayout — একটি ViewGroup যা আপনাকে বิดগেট পজিশন এবং সাইজ করার অনুমতি দেয় ফ্লেক্সিবলভাবে। RelativeLayout-কে steroid দিয়ে শক্তিশালী করা कल্পনা করুন।
- SwipeRefreshLayout — विजেট যা swipe-to-refresh ইউজার ইন্টারফেস প্যাটার্ন পুরোপুরি ইমপ্লিমেন্ট করতে দেয়। এটি ভার্টিক্যাল স্বাইপ ডিটেক্ট করে, একটি ডিস্টিংक्ट প্রগ্রেস বার ডিসপ্লে করে, এবং আপনার অ্যাপে কলব্যাক মেথড ট্রিগার করে।
- FloatingActionButton — একটি সার্কুলার বাটন যা আপনার অ্যাপের UI-তে প্রাইমারি অ্যাকশন ট্রিগার করে।
মেইন স্ক্রিনের জন্য আমরা এই সব কম্পোনেন্টের কম্বিনেশন ব্যবহার করব নাইস UI/UX তৈরি করতে। ইউজাররা লেআউটের টপ পার্ট এক্সপ্যান্ড ও কোল্যাপস করতে পারবেন তাদের সকল ক্রিপ্টোকারেন্সি পোর্টফোলিওর টোটাল ভ্যালু খুঁজে বের করতে। সে ২৪ ঘণ্টার মধ্যে যেকোনো ভ্যালু পরিবর্তন চেক করতে পারবেন এবং সিলেক্টেড ফিয়্যাট কারেন্সি পরিবর্তন করতে পারবেন।
অবশ্যই এই নয়টির বাইরে আরো কম্পোনেন্ট আছে। পুরো কম্পোনেন্ট প্যালেট মাস্টার করা খুব গুরুত্বপূর্ণ যাতে কোনো নির্দিষ্ট কেসে কোনটি ব্যবহার করবেন সেটি জানতে পারেন। মোবাইল ট্রেন্ড সময়ের সাথে সাথে পরিবর্তন হলে প্যালেটও এক্সপ্যান্ড হবে।
আমি প্রতিটি কম্পোনেন্ট সম্পর্কে কথা বলব না, কিন্তু আমার পরামর্শ সেটি নিজে investigate করার। আমার জন্য সেগুলো বুঝতে সেরা উপায় হলো Android Studio-তে অটোমেটিক drag & drop টুল ব্যবহার না করে ম্যানুয়ালি XML লেআউট বানানোর চেষ্টা করা।
Styles, Colors, Dimensions, Strings, Icons
প্রথম নজরে, এই সেকশন টাইটেলে উল্লেখিত বিষয়গুলো গুরুত্বপূর্ণ নয় ऐसा লাগতে পারে। যাইহোক, আমি অনুরোধ করছি যে যেকোনো অ্যাপে এগুলো তৈরি করার সময় প্রচুর প্রচেষ্টা করুন আপনি যদি সেটিকে মডার্ন এবং এক্সক্লूसিভ বানাতে চান। মনে রাখবেন এই ব্লগ পোস্ট সিরিজ হলো কীভাবে একটি মডার্ন Android অ্যাপ বানাব! কতটুকু ভুল হোক, মানুষ সাধারণত আপনার অ্যাপকে প্রথমে এর লুকস দিয়ে জাজ করে, ফাংশন্যালিটি দিয়ে নয়।
তাই এখানে একটি পারফেক্ট সুযোগ আছে শুরু থেকেই নতুন ইউজারদের ভালোবাসা অর্জন করার। এখানে আমার টিপস:
- আপনার XML লেআউট ফাইল বানানোর সময়, আপনাকে চিহ্নিত করতে হবে কোথায় আপনি ভিউদের কিছু কমন অ্যাট্রিবিউট রিপিট করছেন। সেগুলো আলাদা XML styles হিসেবে ডিফাইন করতে হবে। তখন আপনার XML লেআউট ফাইলগুলো ছোট হবে। আপনি অ্যাপ স্টাইলিং-এর সকল দিক একটি আলাদা জায়গা থেকে কন্ট্রোল করতে পারবেন। কতটুকু বেনিফিট হবে সেটি কল্পনা করুন। উদাহরণস্বরূপ, আপনি ইউজারকে অ্যাপ স্কিন বেছে নেওয়া দিতে পারেন (bright, dark, ইত্যাদি)।
- আপনার সকল অ্যাপ কালার আলাদা ফাইলে ডিফাইন করুন, এবং লুক রিফ্রেশ করে নতুন কালার দিয়ে এক্সপেরিমেন্ট করার ক্ষমতা উপভোগ করুন। কখনো কখনো একই প্রোডাক্টকে নতুন জীবন দেওয়া যায় এবং ইউজাররা আবার এনগেজ হয় শুধু কালার রিফ্রেশ করলে। কয়েকটি ওয়েবসাইট আছে যা আপনাকে সুন্দর কালার বেছে নেওয়ায় সাহায্য করে, কিন্তু আমার ফেভারিট MaterialPalette.com, তাই একবার দেখুন।
- আপনার অ্যাপ ডাইমেনশন আলাদা ফাইলে ডিফাইন করুন। এটি আপনাকে আপনার অ্যাপকে বিভিন্ন সাইজের স্ক্রিনে ভালো দেখানোর জন্য অ্যাডজাস্ট করতে দেবে।
- আপনার সকল স্ট্রিং হার্ডকোডেড হওয়া উচিত নয়, এবং Android Studio আপনাকে ইনফর্ম করবে যদি আপনি ভুলে যান। সেটি অহকারী করবেন না। আপনার স্ট্রিং পৃথক থাকার সেরা অংশ হচ্ছে আপনি আপনার অ্যাপকে বিভিন্ন ভাষায় ট্রান্সলেট করতে পারেন।
- অ্যাপের জন্য আইকন ব্যবহার করার সময়, সবসময় XML vector drawable ফরম্যাট পছন্দ করুন। এটি নতুন রিকমেন্ডেড স্ট্যান্ডার্ড এবং পিক্সেলেশন এড়াতে একটি চতুর পথ। কমিউনিটি থেকে প্রফেশনালি বানানো অনেক ম্যাটেরিয়াল ডিজাইন স্টাইল আইকন পাওয়ার জন্য MaterialDesignIcons.com চেক আউট করুন। আমি এই ওয়েবসাইট থেকে My Crypto Coins অ্যাপের জন্য আইকন ব্যবহার করেছি।
RecyclerView
My Crypto Coins অ্যাপের মেইন স্ক্রিন হবে ক্রিপ্টোকারেন্সির একটি লিস্ট যা ব্যবহারকারী ধারণ করে। এই উদ্দেশ্যে RecyclerView widget সেরা ফিট। এটি একটি উইজেট যা বড় ডেটা সেট (বা ডেটা যা ঘন ঘন পরিবর্তন হয়) ভিত্তিক একটি স্ক্রলিং লিস্ট এলিমেন্ট ডিসপ্লে করে।
এর সুবিধা কারণে, RecyclerView যেকোনো লিস্ট স্ক্রিন তৈরি করার জন্য রিকমেন্ডেড কম্পোনেন্ট। এটি সহজ ListView কম্পোনেন্টের চেয়ে আরও এডভান্সড এবং ফ্লেক্সিবল ভার্সন। আমরা পরে এই সম্পর্কে ও কথা বলব। এই পার্টে আমরা শুধু লেআউট তৈরি করছি। কোডিং-এ কনসেন্ট্রেট করছি না।
আমাদের অ্যাপ ভিজুয়ালি দেখতে, আমাদের RecyclerView ইমপ্লিমেন্ট করতে হবে কিছু কোড লিখে। RecyclerView ইমপ্লিমেন্ট করার ধাপগুলো:
1. একটি RecyclerView কম্পোনেন্ট যোগ করুন।
আমাদের MainActivity লেআউট হচ্ছে activity_main.xml। এই লেআউট content_main.xml লেআউট ইনক্লুড করে যা একটি ফ্র্যাগমেন্ট। এই MainActivityListFragment লেআউট fragment_main_list.xml ইনফ্লেট করে। তাই আপনাকে RecyclerView কম্পোনেন্ট এখানে যোগ করতে হবে।
... <android.support.v7.widget.RecyclerView android:id="@+id/recyclerview_fragment_main_list" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/colorForMainListBackground" android:clipToPadding="false" android:paddingBottom="72dp" android:paddingTop="5dp" android:scrollbarStyle="outsideOverlay" android:scrollbars="vertical" /> ...
যে দেখতে পাচ্ছেন আমরা আমাদের RecyclerView কনফিগার করেছি কিছু প্যাডিং স্পেস বটকে ছাড়াতে। এটি FloatingActionButton দিয়ে লাস্ট লিস্ট আইটেম কভার হওয়া থেকে বাঁচাতে। এছাড়া আমরা ভার্টিক্যাল স্ক্রোলবার অন করেছি যেন তা উপলব্ধ থাকে।
2. RecyclerView row layout তৈরি করুন।
আমাদের প্রাথমিক উদ্দেশ্যে আমরা শুধু প্রতিটি রো-এর জন্য আইটেম নাম সেট করব। আমাদের সরলীকৃত লেআউট এইরকম দেখাবে।
<android.support.v7.widget.CardView xmlns:android="https://schemas.android.com/apk/res/android" xmlns:app="https://schemas.android.com/apk/res-auto" xmlns:tools="https://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="@dimen/main_cardview_list_item_outer_top_bottom_margin" android:layout_marginEnd="@dimen/main_cardview_list_item_outer_start_end_margin" android:layout_marginStart="@dimen/main_cardview_list_item_outer_start_end_margin" android:layout_marginTop="@dimen/main_cardview_list_item_outer_top_bottom_margin" android:foreground="?android:attr/selectableItemBackground" android:clickable="true" android:focusable="true" app:cardBackgroundColor="@color/colorForMainListItemBackground"> <android.support.constraint.ConstraintLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="@dimen/main_cardview_list_item_inner_margin"> ... <android.support.v7.widget.AppCompatTextView android:id="@+id/item_name" style="@style/MainListItemPrimeText" android:layout_marginEnd="@dimen/main_cardview_list_item_text_between_margin" android:layout_marginStart="@dimen/main_cardview_list_item_inner_margin" app:layout_constraintBottom_toTopOf="@+id/item_amount_symbol" app:layout_constraintEnd_toStartOf="@+id/guideline1_percent" app:layout_constraintStart_toEndOf="@+id/item_image_icon" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_chainStyle="spread" tools:text="@string/sample_text_item_name" /> ... </android.support.constraint.ConstraintLayout> </android.support.v7.widget.CardView>
3. ডেটা অ্যাডাপ্টার ক্লাস তৈরি করুন।
আমাদের অ্যাডাপ্টার এখন স্ট্রিং ডেটা এক্সেপ্ট করবে। পরে আমাদের আলাদা একটি ক্লাস ডেটা মডেল তৈরি করতে হবে। আমাদের এক سترিং এর চেয়ে বেশি ইনফরমেশন পাস করতে হবে।
class MainRecyclerViewAdapter(val dataList: ArrayList<String>) : RecyclerView.Adapter<MainRecyclerViewAdapter.CustomViewHolder>() { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CustomViewHolder { val v = LayoutInflater.from(parent.context).inflate(R.layout.fragment_main_list_item, parent, false) return CustomViewHolder(v) } override fun onBindViewHolder(holder: CustomViewHolder, position: Int) { holder.txtName?.text = dataList[position] } override fun getItemCount(): Int { return dataList.size } inner class CustomViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { val txtName = itemView.findViewById<TextView>(R.id.item_name) } }
4. RecyclerView কে কাস্টম অ্যাডাপ্টার সাথে কানেক্ট করুন।
class MainActivityListFragment : Fragment() { private lateinit var recyclerView: RecyclerView private lateinit var recyclerAdapter: MainRecyclerViewAdapter override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { val v: View = inflater.inflate(R.layout.fragment_main_list, container, false) recyclerView = v.findViewById(R.id.recyclerview_fragment_main_list) return v } override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) setupList() } private fun setupList() { val data = ArrayList<String>() data.add("Bitcoin") data.add("Etherium") data.add("Ripple") data.add("Bitcoin Cash") data.add("Litecoin") data.add("NEO") data.add("Stellar") data.add("EOS") data.add("Cardano") data.add("Stellar") data.add("IOTA") data.add("Dash") data.add("Monero") data.add("TRON") data.add("NEM") data.add("ICON") data.add("Bitcoin Gold") data.add("Zcash") data.add("Verge") recyclerView.layoutManager = LinearLayoutManager(activity) recyclerAdapter = MainRecyclerViewAdapter(data) recyclerView.adapter = recyclerAdapter } }
হয়েছে! এখন আমাদের মেইন স্ক্রিন এইরকম দেখাচ্ছে:
ListView
এই প্রজেক্টে, আমরা ListView ব্যবহার করব সেই স্ক্রিনে যেখানে আপনি ক্রিপ্টো কয়েন যোগ করতে পারবেন যা আপনি ইতিমধ্যে ধারণ করছেন। গত বছরের তার ত্রুটির কারণে এটিকে কঠিনভাবে ব্যবহার করা হয়না।
তাহলে আমি অনুমান করি আপনাদের অনেকেই এই মুহূর্তে চিন্তা করছেন কেন আমি My Crypto Coins অ্যাপে এটি ব্যবহার করার সিদ্ধান্ত নিলাম যখন আমরা সহজেই একই ফাংশন্যালিটি RecyclerView-র সাথে তৈরি করতে পারতাম।
মনে রাখবেন, যাইহোক, যে এই প্রজেক্টটি প্রথমে ট্রেনিং উদ্দেশ্যে তৈরি হয়েছিল। আমি মনে করলাম ListView এবং কীভাবে এটি কাজ করে তার ইনসাইট পাওয়া বেনিফিশিয়াল হবে। যেকোনো ডেভেলপার লিগেসি কোডে ListView-এ ব딪তে পারে, এবং সেটি কীভাবে কাজ করে সেটি জানা ভালো। বসাইডে, আমরা যে লিস্ট তৈরি করব সেটি খুব সিম্পল যাতে ListView-এর টেকনিক্যাল লিমিটেশন আমাদের কোনো সমস্যা করবেনা।
ListView ইমপ্লিমেন্ট করতে খুব সিমিলার ধাপগুলো ফলো করুন:
1. একটি ListView কম্পোনেন্ট যোগ করুন।
প্রথম কাজ হচ্ছে AddSearchActivity-এ একটি ListView যোগ করা। অ্যাক্টিভিটি লেআউট ফাইল activity_add_search.xml খুলুন এবং আপনি দেখবেন এটি content_add_search.xml ইনক্লুড করে। সেখানে আমরা ListView কম্পোনেন্ট যোগ করব।
... <ListView android:id="@+id/listview_activity_add_search" android:layout_width="match_parent" android:layout_height="wrap_content" android:scrollbars="vertical" /> ...
2. ListView row layout তৈরি করুন।
আগের মতো, শুধু প্রাথমিক উদ্দেশ্যে, আমরা শুধু প্রতিটি রো-এর জন্য আইটেম নাম সেট করব। এখানে সরলীকৃত লেআউট:
<android.support.constraint.ConstraintLayout xmlns:android="https://schemas.android.com/apk/res/android" xmlns:app="https://schemas.android.com/apk/res-auto" xmlns:tools="https://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="@dimen/add_search_list_item_inner_margin"> ... <android.support.v7.widget.AppCompatTextView android:id="@+id/item_name" style="@style/AddSearchListItemPrimeText" android:layout_marginEnd="@dimen/add_search_list_item_text_between_margin_2x" android:layout_marginStart="@dimen/add_search_list_item_text_between_margin" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toStartOf="@+id/item_symbol" app:layout_constraintStart_toEndOf="@+id/item_image_icon" app:layout_constraintTop_toTopOf="parent" tools:text="@string/sample_text_item_name" /> ... </android.support.constraint.ConstraintLayout>
3. ডেটা অ্যাডাপ্টার ক্লাস তৈরি করুন।
RecyclerView-এর মতো আমাদের ListView adapter এখন শুধু স্ট্রিং ডেটা এক্সেপ্ট করবে আইটেম নাম পাওয়ার এবং স্ক্রিনে দেখানোর জন্য। পরে আমরা আলাদা ক্লাস ডেটা মডেল ব্যবহার করব। এই পার্টের জন্য, আমরা একটি খুব সিম্পল লিস্ট বানাতে চাই যা শুধু ক্রিপ্টোকারেন্সির টাইটেল দেখাবে। আমাদের কাস্টম অ্যাডাপ্টার বানানোর বদলে আমরা ডিফল্ট ArrayAdapter ব্যবহার করতে পারি।
class AddSearchListAdapter(context: Context, private val dataSource: ArrayList<String>) : BaseAdapter() { private val inflater: LayoutInflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View { val view: View val holder: CustomViewHolder if (convertView == null) { view = inflater.inflate(R.layout.activity_add_search_list_item, parent, false) holder = CustomViewHolder() holder.nameTextView = view.findViewById(R.id.item_name) view.tag = holder } else { view = convertView holder = convertView.tag as CustomViewHolder } val nameTextView = holder.nameTextView nameTextView.text = getItem(position) as String return view } override fun getItem(position: Int): Any { return dataSource[position] } override fun getItemId(position: Int): Long { return position.toLong(); } override fun getCount(): Int { return dataSource.size } inner class CustomViewHolder { lateinit var nameTextView: AppCompatTextView } }
যে অ্যাডাপ্টার কোডে দেখতে পাচ্ছেন, CustomViewHolder অবজেক্ট তৈরি করে আমি ViewHolder pattern ব্যবহার করেছি। এটি লিস্ট রো ভিউ রেফারেন্স স্টোর করে। findViewById() মেথড কল শুধু কয়েকবার ঘটে। এটি আমাদের লিস্ট স্ক্রোলিং স্মুথ এবং ইফিশিয়েন্ট করতে সাহায্য করে।
ListView আমাদের ViewHolder pattern ব্যবহার করতে বাধ্য করে না। RecyclerView-এর অ্যাডাপ্টার আমাদের সেই প্রকার প্রোটেকশন ডিফল্টভাবে দেয়, কারণ এটি আমাদের বাধ্য করে এটি ব্যবহার করার জন্য।
4. ListView কে কাস্টম অ্যাডাপ্টার সাথে কানেক্ট করুন।
ডিফল্ট ArrayAdapter-এ এটি এইরকম দেখেতে পারত val adapter = ArrayAdapter(this, android.R.layout.simple_list_item_1, data)। এটিই ListView কম্পোনেন্টের সৌন্দর্য। আপনি চাইলে খুব দ্রুত একটি সিম্পল লিস্ট বানাতে পারেন নিজের অ্যাডাপ্টার বা রো লেআউট বানানো ছাড়া (স্টেপ ২ এবং ৩ স্কিপ করুন)।
class AddSearchActivity : AppCompatActivity() { private lateinit var listView: ListView override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_add_search) setSupportActionBar(toolbar2) supportActionBar?.setDisplayHomeAsUpEnabled(true) val data = ArrayList<String>() data.add("Bitcoin") data.add("Etherium") data.add("Ripple") data.add("Bitcoin Cash") data.add("Litecoin") data.add("NEO") data.add("Stellar") data.add("EOS") data.add("Cardano") data.add("Stellar") data.add("IOTA") data.add("Dash") data.add("Monero") data.add("TRON") data.add("NEM") data.add("ICON") data.add("Bitcoin Gold") data.add("Zcash") data.add("Verge") val adapter = AddSearchListAdapter(this, data) listView = findViewById(R.id.listview_activity_add_search) listView.adapter = adapter } ... }
ListView সেটআপ রেডি!
SearchView
সকল ক্রিপ্টোকারেন্সি লিস্ট করা একই স্ক্রিনে, আমাদের SearchView ও যোগ করতে হবে। সার্চ যেকোনো ইউজারের জন্য উপযোগী ফাংশন্যালিটি যারা নাম টাইপ করে নির্দিষ্ট ক্রিপ্টোকারেন্সি খুঁজতে চায়। এই পার্টের জন্য আমরা ফাংশন্যালিটি পুরোপুরি বানাব না কিন্তু শুধু এর ভিজুয়াল পার্ট ইমপ্লিমেন্ট করব। SearchView প্রজেক্টে যোগ করার জন্য এই ধাপগুলো ফলো করুন:
1. XML-এ searchable configuration ডিক্লেয়ার করুন।
Searchable configuration ফাইল আপনার res ডিরেক্টরিতে xml নামে থাকা উচিত। এখানে আপনি আপনার SearchView কম্পোনেন্টের জন্য অ্যাট্রিবিউট স্পেসিফাই করতে পারেন যা ডিফাইন করে কীভাবে এটি behave করবে।
<searchable xmlns:android="https://schemas.android.com/apk/res/android" android:label="@string/app_name" android:hint="@string/search_hint"> </searchable>
2. নতুন অ্যাক্টিভিটি তৈরি করুন যা আমাদের searchable activity হবে।
আমরা একটি নতুন ব্লাঙ্ক অ্যাক্টিভিটি তৈরি করব যা AppCompatActivity() এক্সটেন্ড করে। আমরা এটিকে AddSearchActivity নাম দিব।
3. নতুন তৈরি অ্যাক্টিভিটি Android manifest ফাইলে searchable হিসেবে স্পেসিফাই করুন।
<manifest xmlns:android="https://schemas.android.com/apk/res/android" package="com.baruckis.mycryptocoins"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> ... <activity android:name=".AddSearchList.AddSearchActivity" android:launchMode="singleTop" android:parentActivityName=".MainList.MainActivity" android:theme="@style/AppTheme.NoActionBar"> <intent-filter> <action android:name="android.intent.action.SEARCH" /> </intent-filter> <meta-data android:name="android.app.searchable" android:resource="@xml/searchable" /> </activity> ... </application> </manifest>
আমরা Android সিস্টেমকে সার্চ প্রসেস হ্যান্ডেল করতে দেব। তাই আমরা intent action search এবং meta-data অ্যাড করলাম AddSearchActivity-র activity element-এ। Meta-data-র name এবং resource আছে যা searchable configuration ফাইলের সাথে লিংক করা res/xml ফোল্ডারে অবস্থিত।
4. Search menu তৈরি করুন।
res/menu ফোল্ডারের ভিতরে আমরা একটি মেনু রিসোর্স ফাইল তৈরি করব।
<menu xmlns:android="https://schemas.android.com/apk/res/android" xmlns:app="https://schemas.android.com/apk/res-auto"> <item android:id="@+id/search" android:icon="@drawable/ic_search" android:title="@string/action_search" app:actionViewClass="android.support.v7.widget.SearchView" app:showAsAction="ifRoom|collapseActionView" /> </menu>
5. Search menu অ্যাক্টিভিটিতে যোগ করুন।
আমরা Android search widget-কে একটি মেনু action view হিসেবে যোগ করব।
class AddSearchActivity : AppCompatActivity() { ... override fun onCreateOptionsMenu(menu: Menu?): Boolean { menuInflater.inflate(R.menu.menu_search, menu) val searchManager = getSystemService(Context.SEARCH_SERVICE) as SearchManager val searchView = menu?.findItem(R.id.search)?.actionView as SearchView searchView.setSearchableInfo(searchManager.getSearchableInfo(componentName)) searchView.maxWidth = Integer.MAX_VALUE return true } }
এখন SearchView অ্যাক্টিভিটিতে যোগ হয়েছে। এখনও সার্চ ফাংশন্যালিটি কাজ করছে না। কিন্তু আমরা ইমপ্লিমেন্ট করেছি যেমন আমরা এই পার্টের জন্য চেয়েছিলাম।
Settings
আপনি যদি একটি মডার্ন Android অ্যাপ বানাতে চান, আমি পরামর্শ দিই আপনি একটি সেটিংস স্ক্রিন যোগ করুন এবং ইউজারকে অ্যাপ সেটিংস অ্যাক্সেস দিন। আপনার অ্যাপে সেটিংস থাকলে আপনার ইউজারদের আপনার অ্যাপের কিছু ফাংশন্যালিটি কন্ট্রোল করার ক্ষমতা দেয় যা সেদের খুশি করে। তারা এখন আপনার অ্যাপ কীভাবে behave করবে সেটি কন্ট্রোল করে। তাই আমরা My Crypto Coins অ্যাপের জন্যও একটি সেটিংস স্ক্রিন তৈরি করব।
আপনি Android Studio টেমপ্লেট দিয়ে একটি সেটিংস স্ক্রিন বানাতে পারেন এবং এটি আপনার প্রয়োজনীয় সকল কোড জেনারেট করবে। ডিফল্টভাবে এই লেখা লিখতে সময়, settings activity preference headers সহ জেনারেট হয়। আমাদের একটু ছোট অ্যাপে যেখানে আমরা শুধু কিছু সেটিংস রাখব প্রথমে, সেটি আমরা চাই না।
তাই আমরা সব কিছু ম্যানুয়ালি বানাব। Settings screen XML-র মতো লেআউট দিয়ে ডিজাইন করা হয়। ধাপে ধাপে আবার শুধু ভিজুয়াল পার্ট তৈরি করি এই ব্লগ পোস্টের জন্য:
1. Preferences screen XML ফাইল তৈরি করুন।
আমরা preferences screen XML ফাইল তৈরি করব যেটি res/xml ডিরেক্টরিতে রাখা হবে।
<PreferenceScreen xmlns:android="https://schemas.android.com/apk/res/android" xmlns:tools="https://schemas.android.com/tools"> <PreferenceCategory android:title="@string/pref_general_category_title"> <ListPreference android:defaultValue="@string/pref_default_language_value" android:entries="@array/pref_language_list_entries" android:entryValues="@array/pref_language_list_values" android:icon="@drawable/ic_translate" android:key="language_list" android:summary="@string/pref_default_language_entry" android:title="@string/pref_language_title" tools:summary="@string/pref_default_language_entry" /> <ListPreference android:defaultValue="@string/pref_default_fiat_currency_value" android:entries="@array/pref_fiat_currency_list_entries" android:entryValues="@array/pref_fiat_currency_list_values" android:icon="@drawable/ic_cash" android:key="fiat_currency_list" android:summary="@string/pref_default_fiat_currency_entry" android:title="@string/pref_fiat_currency_title" tools:summary="@string/pref_default_fiat_currency_entry" /> <ListPreference android:defaultValue="@string/pref_default_date_format_value" android:entries="@array/pref_date_format_list_entries" android:entryValues="@array/pref_date_format_list_values" android:icon="@drawable/ic_date_range" android:key="date_format_list" android:summary="@string/pref_default_date_format_entry" android:title="@string/pref_date_format_title" tools:summary="@string/pref_default_date_format_entry" /> <SwitchPreference android:defaultValue="true" android:icon="@drawable/ic_calendar_clock" android:key="24h_switch" android:summary="@string/pref_24h_switch_summary" android:title="@string/pref_24h_switch_title" /> </PreferenceCategory> <PreferenceCategory android:title="@string/pref_support_category_title"> <Preference android:icon="@drawable/ic_star" android:title="@string/pref_rate_app_title" /> <Preference android:icon="@drawable/ic_share" android:title="@string/pref_share_app_title" /> <Preference android:icon="@drawable/ic_attach_money" android:summary="@string/pref_donate_view_summary" android:title="@string/pref_donate_view_title" /> <Preference android:icon="@drawable/ic_currency_btc" android:summary="@string/pref_donate_crypto_summary" android:title="@string/pref_donate_crypto_title" /> </PreferenceCategory> <PreferenceCategory android:title="@string/pref_support_about_title"> <Preference android:icon="@drawable/ic_web" android:summary="@string/pref_website_summary" android:title="@string/pref_website_title" /> <Preference android:icon="@drawable/ic_human_greeting" android:summary="@string/pref_author_summary" android:title="@string/pref_author_title" /> <Preference android:icon="@drawable/ic_github_circle" android:summary="@string/pref_source_summary" android:title="@string/pref_source_title" /> <Preference android:icon="@drawable/ic_file_multiple" android:title="@string/pref_open_source_title" /> <Preference android:icon="@drawable/ic_copyright" android:summary="@string/pref_license_summary" android:title="@string/pref_license_title" /> <Preference android:icon="@drawable/ic_info_outline" android:summary="@string/pref_app_summary" android:title="@string/pref_app_title" /> </PreferenceCategory> </PreferenceScreen>
2. Preferences fragment তৈরি করুন।
তারপর আমাদের একটি সিম্পল ব্লাঙ্ক ফ্র্যাগমেন্ট — SettingsFragment তৈরি করতে হবে, যা PreferenceFragment() এক্সটেন্ড করবে। এই ফ্র্যাগমেন্ট আমরা তৈরি করা XML রিসোর্স থেকে preferences তৈরি করবে। ভবিষ্যতে এই ফ্র্যাগমেন্ট সকল প্রয়োজনীয় মেথড ধারণ করবে XML settings ইনফ্লেট করার জন্য। এছাড়া সেটিংস পরিবর্তন হলে কলব্যাক প্রদান করবে।
class SettingsFragment : PreferenceFragment() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) addPreferencesFromResource(R.xml.pref_main); } }
3. Preferences activity তৈরি করুন।
Settings fragment রেডি থাকলে আসুন নতুন অ্যাক্টিভিটি — AppCompatPreferenceActivity তৈরি করি, যা PreferenceActivity() এক্সটেন্ড করে। এই ক্লাস সকল ডিভাইস এবং ভার্সনে কম্প্যাটিবিলিটি প্রদান করে।
abstract class AppCompatPreferenceActivity : PreferenceActivity() { override fun onCreate(savedInstanceState: Bundle?) { delegate.installViewFactory() delegate.onCreate(savedInstanceState) super.onCreate(savedInstanceState) } override fun onPostCreate(savedInstanceState: Bundle?) { super.onPostCreate(savedInstanceState) delegate.onPostCreate(savedInstanceState) } val supportActionBar: ActionBar? get() = delegate.supportActionBar fun setSupportActionBar(toolbar: Toolbar?) { delegate.setSupportActionBar(toolbar) } override fun getMenuInflater(): MenuInflater { return delegate.menuInflater } override fun setContentView(@LayoutRes layoutResID: Int) { delegate.setContentView(layoutResID) } override fun setContentView(view: View) { delegate.setContentView(view) } override fun setContentView(view: View, params: ViewGroup.LayoutParams) { delegate.setContentView(view, params) } override fun addContentView(view: View, params: ViewGroup.LayoutParams) { delegate.addContentView(view, params) } override fun onPostResume() { super.onPostResume() delegate.onPostResume() } override fun onTitleChanged(title: CharSequence, color: Int) { super.onTitleChanged(title, color) delegate.setTitle(title) } override fun onConfigurationChanged(newConfig: Configuration) { super.onConfigurationChanged(newConfig) delegate.onConfigurationChanged(newConfig) } override fun onStop() { super.onStop() delegate.onStop() } override fun onDestroy() { super.onDestroy() delegate.onDestroy() } override fun invalidateOptionsMenu() { delegate.invalidateOptionsMenu() } private val delegate: AppCompatDelegate by lazy { AppCompatDelegate.create(this, null) } }
4. Settings activity তৈরি করুন।
class SettingsActivity : AppCompatPreferenceActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setupActionBar() fragmentManager.beginTransaction().replace(android.R.id.content, SettingsFragment()).commit() } private fun setupActionBar() { supportActionBar?.setDisplayHomeAsUpEnabled(true) } override fun onMenuItemSelected(featureId: Int, item: MenuItem): Boolean { val id = item.itemId if (id == android.R.id.home) { if (!super.onMenuItemSelected(featureId, item)) { NavUtils.navigateUpFromSameTask(this) } return true } return super.onMenuItemSelected(featureId, item) } }
5. Settings item মেইন মেনুতে যোগ করুন।
<menu xmlns:android="https://schemas.android.com/apk/res/android" xmlns:app="https://schemas.android.com/apk/res-auto" xmlns:tools="https://schemas.android.com/tools" tools:context="com.baruckis.mycryptocoins.MainList.MainActivity"> <item android:id="@+id/action_settings" android:orderInCategory="100" android:title="@string/action_settings" app:showAsAction="never" /> </menu>
6. নতুন তৈরি settings activity লঞ্চ করুন যখন overflow menu থেকে settings সিলেক্ট করা হয়।
class MainActivity : AppCompatActivity() { ... override fun onCreateOptionsMenu(menu: Menu): Boolean { // Inflate the menu; this adds items to the action bar if it is present. menuInflater.inflate(R.menu.menu_main, menu) return true } override fun onOptionsItemSelected(item: MenuItem): Boolean { return when (item.itemId) { R.id.action_settings -> { startActivity(Intent(this@MainActivity, SettingsActivity::class.java)); return true } else -> super.onOptionsItemSelected(item) } } }
7. নতুন তৈরি settings activity Android manifest ফাইলে স্পেসিফাই করুন।
<manifest xmlns:android="https://schemas.android.com/apk/res/android" package="com.baruckis.mycryptocoins"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> ... <activity android:name=".Settings.SettingsActivity" android:label="@string/title_activity_settings" android:parentActivityName=".MainList.MainActivity"> <meta-data android:name="android.support.PARENT_ACTIVITY" android:value="com.baruckis.mycryptocoins.MainList.MainActivity" /> </activity> </application> </manifest>
অভিনন্দন, আপনি অবশেষে টুলবারের মেনু আইটেম থেকে settings লঞ্চ করতে পারবেন।
3rd party libraries ব্যবহার — Gmail style flip circle button-view
OK, 3rd party libraries ব্যবহার সম্পর্কে বিভিন্ন মতামত আছে — ডেভেলপমেন্ট প্ল্যাটফর্মের আসল ভেন্ডরের বাইরের কোনো ডেভেলপার দ্বারা তৈরি কোড। কিছু মানুষ এগুলো এড়িয়ে চলে কারণ কখনো স্পষ্ট নয় কতক্ষণ এবং কত ভালো সাপোর্ট করা হবে। অন্যদিকে অন্যদের এটি ব্যবহার করে কারণ এগুলো ডেভেলপমেন্ট প্রসেস ত্বরান্বিত করতে পারে।
আপনার এগুলো ব্যবহার করার সিদ্ধান্ত আপনার নির্দিষ্ট কেসের ওপর নির্ভর করবে। আপনাকে লাইব্রেরি নিজে investigate করতে হবে এবং নির্ধারণ করতে হবে সেটি যথেষ্ট ফ্লেক্সিবল কিনা আপনার সকল রিকোয়ারমেন্ট ফিট করার জন্য।
My Crypto Coins অ্যাপের জন্য, একটি পরিস্থিতি আছে যেখানে আমি একটি সার্কেল ইমেজ ভিউ তৈরি করতে চাই। এই ইমেজ একটি নির্দিষ্ট ক্রিপ্টোকারেন্সি আইকন সার্কেল শেপে দেখাবে। কিন্তু যদি আইকন না থাকে, তবে আমি ক্রিপ্টোকারেন্সি কোডের প্রথম তিন অক্ষর দেখাতে চাই।
उसके ऊपर আমি ইমেজ সিলেক্ট করতে চাই ক্লিক করলে। সিলেকশন একটি শর্ট flip view অ্যানিমেশন হিসেবে প্রেজেন্ট হবে।
আমি যে সকল UX বর্ণনা করলাম সেগুলো মূলত আমার আবিষ্কার করা নয়। আপনি সিমিলার behaviour Gmail অ্যাপে পাবেন এবং দেখতে খুব ভালো লাগে।
তবে আমরা এটিকে কীভাবে তৈরি করব? আসলে, circle image view ডিফল্ট কম্পোনেন্টও নয় যা আপনি Android Studio কম্পোনেন্ট প্যালেটে পাবেন।
আপনি কঠিন পথে যেতে পারেন এবং সব কিছু নিজে বানানোর চেষ্টা করতে পারেন, কিন্তু এটি সময় এবং শক্তি নষ্ট করতে পারে। বদলে, আপনি সিদ্ধান্ত নিতে পারেন GitHub-এ সেই উদ্দেশ্যে তৈরি অনেক ওপেন সোর্স লাইব্রেরির একটি ইমপ্লিমেন্ট করার।
আমার UI/UX রিকোয়ারমেন্টের জন্য, আমি GitHub-এ davideas/FlipView লাইব্রেরি পেলাম। কিছু investigation এর পর আমি ডিসাইড করলাম এটি খুব প্রফেশনালি বানানো। ইমপ্লিমেন্ট করা সহজ এবং যথেষ্ট দিন সাপোর্টেড যাতে একবার ট্রাই করা যায়। তাই এটা ব্যবহার শুরু করতে, আমরা এই সহজ ধাপগুলো ফলো করব:
1. Dependency যোগ করুন।
লাইব্রেরিকে আপনার প্রজেক্টে ইম্পোর্ট করুন।
dependencies { implementation 'eu.davidea:flipview:1.1.3' }
2. এটি ব্যবহার করুন।
FlipView কনফিগার করুন Android-এর সাধারণ এবং কাস্টম অ্যাপ অ্যাট্রিবিউট দিয়ে। এটা সহজ নয়? ?
<android.support.v7.widget.CardView xmlns:android="https://schemas.android.com/apk/res/android" xmlns:app="https://schemas.android.com/apk/res-auto" ... <eu.davidea.flipview.FlipView android:id="@+id/item_image_icon" style="@style/FlipView" android:clickable="true" android:focusable="true" app:layout_constraintBottom_toTopOf="@+id/item_ranking" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> ... </android.support.v7.widget.CardView>
তাই চাকা নতুন করে আবিষ্কার করবেন না। সবসময় প্রথমে কোনো লাইব্রেরি ব্যবহার করার কথা ভাবুন দ্রুত ফলাফল দিতে। এবং আপনার প্রজেক্ট মেসি হয়ে যায়, সেটি পুরনো লাইব্রেরির দোষ নয় বরং আপনি কত ভালো আপনার কোড স্ট্রাকচার করেছেন সেটি। আপনার প্রজেক্ট যদি মডুলার পর্যাপ্ত হয়, তবে কোনো সমস্যা হবে না। কিন্তু এটি আলাদা একটি টপিক এবং আমি পরবর্তী ব্লগ পোস্টে প্রজেক্ট আর্কিটেকচার সম্পর্কে কথা বলব।
RTL সাপোর্টসহ লোকালাইজেশন
যখন আমি এই অ্যাপ বানানোর সিদ্ধান্ত নিলাম, আমি নিজের জন্য একটি লক্ষ্য নির্ধারণ করলাম শুধু ডিফল্ট ইংরেজি UI-তে বানানো নয়, বরং আমার মাতৃভাষা লিথুয়েনিয়ানে শুরু থেকেই ট্রান্সলেট করার।
এই লক্ষ্য আমাকে Android-এ লোকালাইজেশন শিখতে বাধ্য করল। যা मैंने পাওয়া তা হলো একাধিক ভাষার সাপোর্ট যোগ করা খুব সহজ। যেমন আমি আগে বললাম, প্রথমে আপনাকে আপনার সকল স্ট্রিং strings.xml ফাইলে আলাদা করতে হবে। তারপর Android Studio-র ভিতরে Translations Editor টুল লঞ্চ করুন। এটি আপনাকে নতুন ভাষা সাপোর্ট যোগ করতে দেবে।
আপনি দেখবেন ইন্টারফেস খুব ইন্টুইটিভ। এখন আপনাকে আপনার strings.xml ফাইল থেকে প্রতিটি স্ট্রিং নতুন ভাষায় ট্রান্সলেট করতে হবে। IDE দ্বারা একটি নতুন ফাইল আলাদা ডিরেক্টরিতে জেনারেট হবে। উদাহরণস্বরূপ, লিথুয়েনিয়ান ভাষার জন্য, এটি values-lt/strings.xml। এটাই হলো! ?
আপনি যদি আপনার Android ডিভাইসের সিস্টেম ভাষা সেটিয়ে দেন যা আপনি এখন ট্রান্সলেট করলেন এবং তারপর আপনার অ্যাপ রান করেন, সব UI আপনার ট্রান্সলেশনে আটোমেটিক্যালি আপডেট হবে। বолее того, My Crypto Coins অ্যাপের জন্য, পরে আমি রান-টাইমে ভাষা পরিবর্তন করার ক্ষমতা যোগ করার প্ল্যান করছি। তাই আপনি সেটিংস স্ক্রিনে ল্যাঙ্গুয়েজ সুইচার লক্ষ্য করবেন।
আপনার অ্যাপকে বিভিন্ন ভাষায় ট্রান্সলেট করা নিঃসন্দেহে আপনার অডিয়েন্স বাড়াবে। কেন না আরও একটু এগিয়ে যাওয়ায় কিছু স্পেশাল ভাষা যেগুলো Right to Left (RTL) — যেমন Arabic, Hebrew বা Persian লিখে।
আসলে RTL সাপোর্ট যোগ করা কঠিন নয়। শুধু manifest ফাইলে support attribute যোগ করুন:
<manifest xmlns:android="https://schemas.android.com/apk/res/android" package="com.baruckis.mycryptocoins"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> ... </application> </manifest>
অভিনন্দন, আপনার অ্যাপ এখন RTL সাপোর্ট করে। যাইহোক আপনি ব্লাইন্ডলি ট্রাস্ট করতে পারবেন না যে সব কিছু সঠিকভাবে কাজ করবে সরাসরি। আপনাকে নিজে চেক করতে হবে কত ভালো সাপোর্ট করা হয়েছে। সেটি করতে RTL ভাষাগুলোর একটি আপনার প্রাইমারি ডিভাইস ল্যাঙ্গুয়েজ হিসেবে সিলেক্ট করুন।
RTL-এর জন্য কিছু টিপস:
- আপনার সকল লেআউটে আপনাকে সব
LeftএবংRightলেআউট প্রপার্টিStartএবংEndসমতুল্য দিয়ে রিপ্লেস করতে হবে। উদাহরণস্বরূপandroid:paddingLeftকেandroid:paddingStartদিয়ে রিপ্লেস করতে হবে। - আপনার কাছে যদি RTL-এর জন্য স্পেশাল drawable নাও থাকে, হয়তো আপনি আপনার কারেন্টগুলোকে
autoMirroredঅ্যাট্রিবিউট দিয়ে মিরর করতে চান।
<vector xmlns:android="https://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:autoMirrored="true" android:tint="@color/colorForPreferenceIcon" android:viewportHeight="24.0" android:viewportWidth="24.0"> <path android:fillColor="#FF000000" android:pathData="M1.5,4V5.5C1.5,9.65 3.71,13.28 7,15.3V20H22V18C22,15.34 16.67,14 14,14C14,14 13.83,14 13.75,14C9,14 5,10 5,5.5V4M14,4A4,4 0 0,0 10,8A4,4 0 0,0 14,12A4,4 0 0,0 18,8A4,4 0 0,0 14,4Z" /> </vector>
- কিছু নির্দিষ্ট জায়গায় যদি আপনাকে RTL এর বদলে LTR দরকার হয়, সেটিও করা যায়। উদাহরণস্বরূপ যেকোনো লেআউটকে LTR ফোর্স করতে শুধু
android:layoutDirection="ltr"সেটি ভিউতে যোগ করুন। যদি টেক্সট ভিউতে টেক্সট ডিরেকশন ফোর্স করতে হয় তবেandroid:textDirection="ltr"ব্যবহার করুন।
ব্যাবা, Translations Editor ব্যবহার করার সময়, একটি খুব উপকারী ফিচার আছে প্রফেশনাল ট্রান্সলেশন সার্ভিস অর্ডার করার। যদি আমি ব্যক্তিগতভাবে হিব্রু ভাষা সম্পর্কে কিছুই না জানি, তবুও আমি নিজের জন্য লক্ষ্য নির্ধারণ করলাম My Crypto Coins প্রজেক্টের জন্য একটি উদাহরণ RTL ভাষা হিসেবে সাপোর্ট যোগ করার। তাই এই ফিচার আমার কাছে খুব ভালো আইডিয়া লাগলো ট্রাই করার। আমি IDE-র ভিতর থেকে সরাসরি ইংরেজি থেকে হিব্রুতে ট্রান্সলেশন সফলভাবে অর্ডার করলাম শুধু কয়েক ক্লিক দিয়ে।
Final thoughts
সিরিজের এই দ্বিতীয় পার্টে, আমরা ডিটেইল্ড mockups-র ভিত্তিতে সকল UI লেআউট কিছু প্রাথমিক কোড সহ তৈরি করলাম। আমি প্রতিটি টপিকে খুব গভীরে যেতে চাইনি যেন আপনাকে কনফিউজ না করি। আমার লক্ষ্য ছিল আপনাকে কীভাবে বড় চিত্র দেখবেন, কীভাবে ছোট ডিটেইলসে ফোকাস করবেন, এবং পরবর্তীতে ব্যয়বহুল ভুল এড়াবেন সেটি দেখানো।
আপনি যদি কিছু কিছু ভালোভাবে কভার না করা পান, তবে সেটি আপনার নিজস্ব রিসার্চ করার একটি জাম্পিং অফ পয়েন্ট হিসেবে ব্যবহার করুন। ওয়েবের চারদিকে শিখতে অনেক ভালো রিসোর্স সবসময় আছে। ?
Repository
এই পার্টের জন্য তৈরি সকল XML লেআউট এবং কোড আপনি এখানে পাবেন:
View Source On GitHub
Ačiū! Thanks for reading! I originally published this post for my personal blog www.baruckis.com on May 14, 2018.