Post updated on 2nd August, 2017 at 06:55 am
অল্প কয়েক লাইনের কিছু কোড লিখেই আপনার অ্যান্ড্রয়েড অ্যাপে এরকম সুন্দর একটা এনিমেটেড ইফেক্ট নিয়ে আসতে পারবেন। আমরা সাধারণত Activity-তে ImageView, TextView ইত্যাদি রেখে সেগুলোকে Scroll করতে চাইলে ScrollVew ইউজ করি। নিচের GIF’র উদাহরণটা ScrollView থেকে একটু ভিন্ন। এখানে নিচের দিকের কনটেন্ট দেখার জন্য স্ক্রল করা হলে উপরের image-টা collapse হয়ে যাচ্ছে। আবার উপরের কনটেন্ট দেখার জন্য স্ক্রল করলে উপরে থাকা Toolbar-টা সেই আগের ইমেজে রূপান্তরিত হচ্ছে।
এই ফিচারটা ইমপ্লিমেন্ট করার জন্য XML এবং Java code উভয়ের combination লাগবে। নিচে পুরো প্রকৃয়াটি ধারাবাহিক ভাবে তুলে ধরা হলো।
Gradle file modification
প্রথমেই gradle এর dependency সেকশনটাতে support design এর লাইব্রেরিটা যুক্ত করে নিন। আপনি যখন এটা ইমপ্লিমেন্ট করবেন তখনকার latest version-টা ইউজ করুন। আমি যখন এই পোস্ট লিখছি এই সময়ের সর্বশেষ ভার্সন 26.0.0-alpha1. ডিপেন্ডেন্সির জন্য লিখতে হবে এই লাইনটাঃ
compile ‘com.android.support:design:26.0.0-alpha1’
XML file modification
আমরা LinearLayout, RelativeLayout সাধারণত ব্যবহার করে থাকি। CollapsingToolbarLayout এই widget-টা ব্যবহার করতে হয় AppBarLayout নামের widget এর ভিতরে। আর AppBarLayout ইউজ করার জন্য প্রয়েজন হয় CoordinatorLayout. তাই MainActivity’র xml এর root layout হিসাবে CoordinatorLayout ব্যবহার করতে হবে। GIF ইমেজ থেকে দেখতে পাচ্ছেন যে Activity এর back button press করলে একটা SnackBar দেখানো হচ্ছে। এটা দেখানোর জন্যেও CoordinatorLayout ব্যবহার করতে হয়।
Root layout এর ভিতরে পরপর দুইটা widget থাকবে। সেগুলো হচ্ছে AppBarLayout ও NestedScrollView. প্রথমটির মাধ্যমে toolbar দেখানো হবে, আর দ্বিতীয়টি দিয়ে দেখানো হবে বাকি সব কনটেন্ট। এই প্রোজেক্টের ক্ষেত্রে আমি এই স্ক্রলভিউয়ের মধ্যে শুধু একটা TextView দেখিয়েছি। আপনার প্রোজেক্ট অনুসারে এটা ভিন্ন হতে পারে।
AppBarLayout এর ভিতরে থাকবে CollapsingToolbarLayout. তার ভিতরে থাকবে একটা ImageView ও Toolbar. মূল গুরুত্বপূর্ণ অংশ আসলে এটিই। Activity যখন open হবে তখন AppBarLayout expanded অবস্থায় থাকবে। সে অবস্থাতেও উপরের বামপাশের কোণায় Back Button দেখানো হচ্ছে। এখানে back button টা দেখানো হচ্ছে Toolbar এ। কিন্তু চালাকি করে toolbar এর ব্যাকগ্রাউন্ড কালার transparent করে দেয়া হয়েছে। কিন্তু AppBarLayout যখন collapsed হবে তখন toolbar এ lemon-green টাইপের ব্যাকগ্রাউন্ড দেখা যাচ্ছে। এটা পরবর্তীতে Java code এর মাধ্যমে handle করা হয়েছে। নিচে পুরো xml-টা তুলে দেয়া হলোঃ
<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout android:id="@+id/coordinateLayout" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" android:layout_alignParentTop="true" android:layout_alignParentStart="true" android:layout_alignParentLeft="true"> <android.support.design.widget.AppBarLayout android:id="@+id/appBarLayout" android:layout_width="match_parent" android:layout_height="192dp" android:theme="@style/AppTheme.AppBarOverlay"> <android.support.design.widget.CollapsingToolbarLayout android:id="@+id/collapsingToolbar" android:layout_width="match_parent" android:layout_height="match_parent" app:contentScrim="?attr/colorPrimary" app:layout_scrollFlags="scroll|exitUntilCollapsed"> <ImageView android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="centerCrop" android:src="@drawable/image" app:layout_collapseMode="parallax" app:layout_collapseParallaxMultiplier="0.7" android:contentDescription="@string/image_description" /> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="@android:color/transparent" app:popupTheme="@style/AppTheme.PopupOverlay" app:layout_collapseMode="pin" /> </android.support.design.widget.CollapsingToolbarLayout> </android.support.design.widget.AppBarLayout> <android.support.v4.widget.NestedScrollView android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/article" android:padding="16dp"/> </LinearLayout> </android.support.v4.widget.NestedScrollView> </android.support.design.widget.CoordinatorLayout>
প্রতিটা widget এর property-গুলো নিয়ে ঘাটাঘাটি করতে পারেন। এতে হয়ত আরো ভালো ডিজাইন করা সম্ভব হবে।
Custom design এর toolbar এর জন্য নিচের custom_toolbar.xml ফাইলটা drawable এ রেখেছিঃ
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item> <shape> <gradient android:angle="90" android:endColor="#CDDC39" android:startColor="#4CAF50" android:type="linear"/> </shape> </item> </selector>
Java class modification
Toolbar show করা বা না করার জন্য আমরা লজিক চিন্তা করেছি। লজিক হচ্ছেঃ যখন AppBarLayout-টা expanded অবস্থায় থাকবে তখন toolbar এর background color হবে transparent (এটাকে বলছি toolbar show না করা)। আর যখন AppBarLayout collapsed অবস্থায় থাকবে তখন আমাদের কাস্টম ডিজাইনের টুলবারটা শো করবে। এই কাজটা করার জন্য আমাদের জানতে হবে কখন AppBarLayout expanded হচ্ছে আর কখনই বা collapsed হচ্ছে। এই event-গুলো listen করার জন্য AppBarStateChangeListener নামের একটা abstract class লিখে রেখেছি। এটা সরাসরি কপি-পেস্ট করলে যে কোনো প্রোজেক্টেই কাজ করবে।
public abstract class AppBarStateChangeListener implements AppBarLayout.OnOffsetChangedListener { public enum State { EXPANDED, COLLAPSED, IDLE } private State mCurrentState = State.IDLE; @Override public final void onOffsetChanged(AppBarLayout appBarLayout, int i) { if (i == 0) { if (mCurrentState != State.EXPANDED) { onStateChanged(appBarLayout, State.EXPANDED); } mCurrentState = State.EXPANDED; } else if (Math.abs(i) >= appBarLayout.getTotalScrollRange()) { if (mCurrentState != State.COLLAPSED) { onStateChanged(appBarLayout, State.COLLAPSED); } mCurrentState = State.COLLAPSED; } else { if (mCurrentState != State.IDLE) { onStateChanged(appBarLayout, State.IDLE); } mCurrentState = State.IDLE; } } public abstract void onStateChanged(AppBarLayout appBarLayout, State state); }
এখন MainActivity-তে event listen করে logic implement করবঃ
appBarLayout.addOnOffsetChangedListener(new AppBarStateChangeListener() { @Override public void onStateChanged(AppBarLayout appBarLayout, State state) { if(state.equals(State.COLLAPSED)) { toolbar.setBackgroundResource(R.drawable.custom_toolbar); Toast.makeText(getApplicationContext(), "COLLAPSED", Toast.LENGTH_SHORT).show(); } else if (state.equals(State.EXPANDED)) { toolbar.setBackgroundResource(R.color.transparent); Toast.makeText(getApplicationContext(), "EXPANDED", Toast.LENGTH_SHORT).show(); } else if ((state.equals(State.IDLE))){ Toast.makeText(getApplicationContext(), "IDLE", Toast.LENGTH_SHORT).show(); } } });
আসল কাজ শেষ। সর্বশেষ কাজ বাকি আছে। তা হলো back button এর click event listener. ব্যাক বাটনে ক্লিক করলে স্ক্রিনের নিচে একটা Snackbar দেখাচ্ছে। click event সহ Snackbar show করার করার কোডঃ
@Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == android.R.id.home) { Snackbar.make(coordinatorLayout, "Back button pressed", Snackbar.LENGTH_LONG).show(); return true; } return super.onOptionsItemSelected(item); }
পুরো সোর্স কোডটি পাওয়া যাবে আমার গিটহাব রিপোজিটরিতে।