در قسمت شانزدهم آموزش برنامه نویسی اندروید مبحث فرگمنت در اندروید را آموزش میدهیم (fragment در برنامه نویسی اندروید). به علاوه توضیحاتی درباره ماهیت فرگمنت ها و چرخه حیات آنها مثالی ساده برای این مبحث نیز ذکر کرده ایم که در ادامه بیشتر درباره این مبحث صحبت خواهیم کرد.
در آموزش های پیش آموختیم که یک اکتیویتی چیست و چگونه میتوان از آن استفاده کرد.در صفحه های کوچک (مثل گوشی های هوشمند) یک اکتیویتی تمام صفحه را اشغال میکند پس با استفاده از چند نما(View) به رابط کاربری برنامه خود شکل میدهیم.یک اکتیویتی اصولا ظرفی برای نماها است.اما اگر برنامه در یک صفحه نمایش بزرگتر مانند تبلت نمایش داده شود کاملا به هم ریخته خواهد شد چرا که نمایش شما برای صفحه کوچکتر طراحی شده و برای صفحه های بزرگتر نیز میبایستی دوباره چینش صوت بگیرد.این حالت باعث پیچیدگی در طراحی نما خوهد شد.
ایده بهتر برای رفع این مشکل ایجاد چند اکتیویتی کوچک است که هرکدام دارای نمای خود باشد.در زمان یک اکتیویتی میتواند شامل چندین اکتیویتی کوچک باشد که البته جهت آن بستگی جهت صفحه نمایش دارد(عمودی یا افقی) در اندروید ۳ به بالا این اکتیویتی های کوچک را فرگمنت ها گویند.
تصور کنید فرگمنت یک نوع دیگر از اکتیویتی است.فرگمنت ها برای نمایش نما بوجود می آیند کاملا مثل اکتیویتی ها. فرگمنت ها همیشه در دل اکتیویتی ها جای میگیرند برای مثال تصویر زیر را در نظر بگیرید
طبق تصویر فوق تصور کنید Fragment 1 یک لیست از عناوین کتاب است و Fragment 2 حاوی یک TextView و ImageView و… میباشد.
حال فرض کنید برنامه را درون یک دستگاه اندروید در حالت عمودی(مثل یک گوشی هوشمند) اجر کنیم اجرا کنیم در این صورت ممکن است فرگمنت ۱ در یک اکتیوتی و فرگمنت ۲ در اکتیویتی دیگر قرار گیرد هرگاه کابر آیتمی را از لیت فرگمنت ۱ انتخاب کند فرگمنت ۲ اجرا شود.
حال اگر برنامه را به صورت افقی درون دستگاهی مانند تبلت نمایش دهیم هر دو فرگمنت کنار یکدیگر اجرا میشوند
از این بحث میتوان چنین دریافت که فرگمنت ها راه حل جامعی را برای رفع مشکل نماها در رابط کاربری اندروید ارایه میدهند. فرگمنت ها از بخش های کلیدی برنامه اندروید شما هستند میتوانند به صورت پویا اضافه و حذف شوند تا بهترین رابط کاربری را برای دستگاه بوجود آورند.
همانند اکتیوتی ها فرگمنت ها نیز چرخه حیات دارند هنگام ایجاد یک فرگمنت حالات زیر رخ میدهد
وقتی بک فرگمنت نمایش داده میشود حالات زیر رخ میدهد
وقتی بک فرگمنت به حالت Background یا پس زمینه میرود و بدون آنکه نابود شود از حالت نمایش پنهان شود
وقتی که فرگمنت نابود میگردد (یعنی زمانی که یک اکتیوتی میزبان فرگمنت را نابود میکند)
همانند اکتیویتی ها میتوان یک وهله از فرگمنت را به وسیله شی Bundle در حالت زیر بازیابی کرد
بیشتر حالاتی که ممکن است برای فرگمنت اتفاق بیفتد شبیه حالاتی است که برای اکتیویتی آن اتفاق می افتد چند حالت که مختص فرگمنت ها هستند به شرح ذیل است :
نکته قابل توجه در رابطه با تفاوت اکتیویتی و فرگمنت این است که زمانی که اکتیوتی به پس زمینه میرود درواقع back stack قرار میگیرد.این نکته به اکتیویتی اجازه میدهد تا وقتی کابر دکمه back رافشرد اکتیویتی قابل برگشت باشد. اما در مورد فرگمنت ها این اتفاق به صورت خودکار صورت نمیپذیرد و در back stack قرار نمیگیرند مگر اینکه متد ()addToBackStack را در تراکنش های فرگمنت به صورت صریح فراخوانی کنید.
حال یک مثال ساده برای فرگمنت ها آموزش میدهیم که براساس افقی یا عمودی بودن صفحه دستگاه یکی از فرگمنت ها را نمایش میدهد
ابتدا پروژه جدیدی با نام FragmentsPrj ایجاد کرده و دو فایل xml با نام های fragment1 و fragment 2 در مسیر res/layout ایجاد کرده و محتویاتشان را چنان تغییر میدهیم
محتوی fragment1 که تنها یک textview ایجاد کرده و در صورت افقی بودن نشان داده میشود
<TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="this is Landscape Fragment" android:textColor="#000000" android:textSize="25px" />
محتوی fragment 2 که در صورت عمودی بودن دستگاه نشان داده میشود
<TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="this is Portrate Fragment" android:textColor="#000000" android:textSize="25px" />
حال درون فایل activity_main.xml چنین کدنویسی میکنیم
<fragment android:name="com.example.fragments" android:id="@+id/fragment1" android:layout_weight="1" android:layout_width="0dp" android:layout_height="match_parent" /> <fragment android:name="com.example.fragments" android:id="@+id/fragment2" android:layout_weight="2" android:layout_width="0dp" android:layout_height="match_parent" />
حال دو کلاس جاوا برای دو فرگمنت ایجاد شده با نام های Fragment1 و Fragment2 ایجاد کرده و درون فایل Fragment1.java چنین کدنویسی میکنیم
import android.app.Fragment; import android.os.Bundle; import android.view.*; public class Fragment1 extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { //--Inflate the layout for this fragment-- return inflater.inflate(R.layout.fragment1, container, false); } }
و درون فایل Fragment2.java نیز بدین صورت
import android.app.Fragment; import android.os.Bundle; import android.view.*; public class Fragment2 extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { //--Inflate the layout for this fragment-- return inflater.inflate(R.layout.fragment2, container, false); } }
حال در MainActivity.java برای مشخص کردن اکتیویتی مناسب و نمایش آن چنین کدنویسی میکنیم
import android.os.Bundle; import android.app.Activity; import android.app.FragmentManager; import android.app.FragmentTransaction; import android.content.res.Configuration; import android.view.WindowManager; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Configuration config = getResources().getConfiguration(); FragmentManager fragmentManager = getFragmentManager(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); // Check the device orientation and act accordingly if (config.orientation == Configuration.ORIENTATION_LANDSCAPE) { // Landscape mode of the device Fragment1 f1 = new Fragment1(); fragmentTransaction.replace(android.R.id.content, f1); }else{ // Portrait mode of the device Fragment2 f2 = new Fragment2(); fragmentTransaction.replace(android.R.id.content, f2); } fragmentTransaction.commit(); } }
حال میتوان برنامه را اجرا کرد و نتیجه ا بسته به دستگاه اجرا کننده مطابق شکل زیر ببینید
یک فرگمنت در اندروید بسیار به اکتیویتی شباهت دارد چرا که دارای کلاس جاوا است و همچنین رابط کاربری خود را از xml بارگذاری میکند.کلاس جاوایی که برای فرگمنت نوشته میشود باید کلاس پایه fragment را بسط دهد
public class Fragment2 extends Fragment {
برای ترسیم رابط کاربری یک فرگمنت در اندروید متد onCreateView() را override میکنیم این متد یک شی از نوع View را برمیگرداند
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { //--Inflate the layout for this fragment-- return inflater.inflate(R.layout.fragment2, container, false); }
در اینجا از شی LayoutInflater برای برجسته کردن رابط کاربری از فایل xml موردنظر (در این مورد R.layout.fragment2) استفاده شده.آرگومان container به ViewGroup والد اشاره داردکه همان اکتیویتی است که شما سعی دارید آن را در فرگمنت Enable کنید. آرگومان savedInstanceState به شما این قابیت را میدهد تا فرگمنت را به حالت ذخیره شده قبلی بازگردانید.
برای افزودن فرگمنت به اکتیویتی نیز از عنصر <fragment> استفاده میکنیم.
<fragment android:name="com.example.fragments" android:id="@+id/fragment1" android:layout_weight="1" android:layout_width="0dp" android:layout_height="match_parent" />
به این نکته دقت کنید که به هر فرگمنت در اندروید یک شناسه منحصر به فرد اختصاص دهید. میتوان این کار را به وسیله ویژگی های android:id یا android:tag انجام داد.