Fragment چیست؟
Fragment را می توان بعنوان یک زیر مجموعه و یا یک بخش از اکتیویتی، در نظر گرفت. Fragment نیز مانند اکتیویتی از دو قسمت xml وjava تشکیل شده.هر اکتیویتی می تواند چندین فرگمنت را در خود جای دهد و هر فرگمنت می تواند در چندین اکتیویتی استفاده شود.بنابراین فرگمنت به تنهایی قابلیت اجرا ندارد.
به عبارت دیگر می توان گفت وقتی می خواهیم در طراحی نرم افزار اندروید اکتیویتی ثابت باشد و تنها قسمتی از اکتیویتی تغییر کند از فرگمنت ها استفاده می کنیم. پس فرگمنت مانند یک برچسب روی اکتیویتی عمل می کند.
ساخت Fragment
برای ساخت Fragment در اندروید لازم است کتابخانه ای بنام FragNavController را در گردل اد کنیم:
implementation 'com.ncapdevi:frag-nav:2.1.0'
در این پروژه سعی داریم دو فرگمنت ایجاد کنیم. ابتدا ظاهر فرگمنت ها را طراحی می کنیم.
یک Layout بنام fragment_one و یک Layout بنام fragment_two ایجاد کنید و سورس کدهای زیر را در آن ها وارد کنید:
fragment_one:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:gravity="center"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="number1"/> <Button android:id="@+id/btn_fragment" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="openDialog" /> </LinearLayout
Fragment_two:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="number2"/> <Button android:id="@+id/btn_fragment" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="openDialog" /> </LinearLayout>
همانطور که می بینید، ظاهر هر فرگمنت از یک TextView و یک Button تشکیل شده است:
ظاهر فرگمنت ها را طراحی کردیم، حالا میریم سراغ اکتیویتی که قراره فرگمنت داخل آن نمایش داده شود.
یک اکتیویتی بنام TestFragmentActivity ایجاد کرده و داخل xml آن سورس کد زیر را وارد کنید:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> <FrameLayout android:id="@+id/fl_fragment" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_above="@+id/ll_button_nv"> </FrameLayout> <LinearLayout android:id="@+id/ll_button_nv" android:layout_width="match_parent" android:layout_height="50dp" android:layout_alignParentBottom="true" android:orientation="horizontal" android:weightSum="2"> <Button android:id="@+id/btn_openOneFragment" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:text="number1" /> <Button android:id="@+id/btn_openTwoFragment" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:text="number2" /> </LinearLayout> </RelativeLayout>
ابتدا یک RelativeLayout با طول و عرض match_parent تعریف می کنیم، سپس یک LinearLayout با طول match_parent و عرض 50 تعریف کرده و داخل آن دو Button قرار می دهیم و layout_alignParentBottom آن را true می کنیم تا پایین صفحه قرار گیرد. برای اینکه اندازه ی دو Button برابر باشد، داخل LinearLayout، weightSum را برابر 2 قرار می دهیم، همچنین داخل Button ها طول را برابر صفر و layout_weight را برابر 1 قرار می دهیم.
برای اینکه یک فرگمنت داخل اکتیویتی قرار دهیم باید یک لایه ی FrameLayout ایجاد کنیم پس یک FrameLayout با طول و عرض match_parent ایجاد کرده وآن را بالای LinearLayout قرار می دهیم.
ظاهر اکتیویتی را هم طراحی کردیم که بصورت زیر می باشد:
کد جاوای Fragment
دو کلاس بنام های OneFragment و TwoFragment ایجاد کرده و سورس کدهای زیر را در آن ها وارد کنید:
OneFragment:
import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; public class OneFragment extends Fragment { Button btn_fragment; OnTabButtons onTabButtons; public static OneFragment newInstance() { Bundle args = new Bundle(); OneFragment fragment = new OneFragment(); fragment.setArguments(args); return fragment; } @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View fragmentView = inflater.inflate(R.layout.fragment_one , container , false); return fragmentView; } @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); btn_fragment = (Button) view.findViewById(R.id.btn_fragment); btn_fragment.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onTabButtons.onTab(); } }); } public interface OnTabButtons{ public void onTab(); } public OneFragment setOnTabButtons(OnTabButtons onTabButtons){ this.onTabButtons = onTabButtons; return this; } }
TwoFragment:
import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; public class TwoFragment extends Fragment { Button btn_fragment; OnTabButtons onTabButtons; public static TwoFragment newInstance() { Bundle args = new Bundle(); TwoFragment fragment = new TwoFragment(); fragment.setArguments(args); return fragment; } @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View fragmentView = inflater.inflate(R.layout.fragment_two , container , false); return fragmentView; } @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); btn_fragment = (Button) view.findViewById(R.id.btn_fragment); btn_fragment.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onTabButtons.onTab(); } }); } public interface OnTabButtons { public void onTab(); } public TwoFragment setOnTabButtons(OnTabButtons onTabButtons){ this.onTabButtons = onTabButtons; return this; } }
ابتدا باید کلاس را extend کنیم به Fragment سپس Button داخل فرگمنت را تعریف کنیم.
برای ساخت هرفرگمنت به سه متد نیاز داریم:
- newInstance
- onCreateView
- onViewCreated
برای نوشتن این متدها کافیست اسم آن ها را بنویسیم ، بصورت خودکار متدها را برامون میاره.
متد newInstanceدر واقع بین کلاس فرگمنت و اکتیویتی ارتباط برقرار می کند و در صورتی که بخواهیم اطلاعاتی از این کلاس به اکتیویتی پاس دهیم از طریق این متد این کار را انجام می دهیم.
داخل متد onCreateView، با inflater ظاهر فرگمنت را فراخوانی کرده و آن را return می کنیم و در آخر هر کاری که می خواهیم روی فرگمنت انجام دهیم ، داخل متد onViewCreate می نویسیم.
داخل متد onViewCreate، دکمه ای که برای فرگمنت قرار دادیم findViewById کرده و برای آن setonClickListener می نویسیم.
می خواهیم وقتی روی دکمه ی داخل فرگمنت کلیک شد، اکتیویتی متوجه شود بعبارتی می خواهیم اطلاعاتی از کلاس فرگمنت به اکتیویتی پاس دهیم، پس از interface استفاده کرده و برای اینکه بتونیم interface رو به اکتیویتی پاس دهیم ، یک متد از نوع خود کلاس فرگمنت بنام setOnTabButtons، ایجاد کرده و interface را به ورودی آن می دهیم.
حالا داخل onClick که برای دکمه ی فرگمنت نوشتیم، تابع داخل interface را فراخوانی می کنیم.
همین عملیات را درTwoFragment نیز انجام می دهیم.
کد جاوای Activiity
حالا داخل اکتیویتی که می خواهید فرگمنت در آن نشان داده شود، سورس کد زیر را وارد کنید:
import android.content.Context; import android.support.v4.app.Fragment; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.Switch; import android.widget.Toast; import com.elahe.test.fragment.OneFragment; import com.elahe.test.fragment.TwoFragment; import com.ncapdevi.fragnav.FragNavController; public class TestFragmentActivity extends AppCompatActivity { Context context = this; Button btn_openFrgOne , btn_openFrgTwo; FragNavController fragNavController; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test_fragment); initView(); onClick(); initFragment(savedInstanceState); } private void initFragment(Bundle savedInstanceState) { fragNavController = FragNavController.newBuilder(savedInstanceState , getSupportFragmentManager(),R.id.fl_fragment).transactionListener(new FragNavController.TransactionListener() { @Override public void onTabTransaction(Fragment fragment, int i) { } @Override public void onFragmentTransaction(Fragment fragment, FragNavController.TransactionType transactionType) { } }).rootFragmentListener(new FragNavController.RootFragmentListener() { @Override public Fragment getRootFragment(int i) { Fragment fragment = null; switch (i) { case FragNavController.TAB1: fragment = OneFragment.newInstance().setOnTabButtons(new OneFragment.OnTabButtons() { @Override public void onTab() { Toast.makeText(context, "OneFragment", Toast.LENGTH_SHORT).show(); } }); break; case FragNavController.TAB2: fragment = TwoFragment.newInstance().setOnTabButtons(new TwoFragment.OnTabButtons() { @Override public void onTab() { Toast.makeText(context, "TwoFragment", Toast.LENGTH_SHORT).show(); } }); break; } return fragment; } },2).build(); } private void onClick() { btn_openFrgOne.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { fragNavController.switchTab(FragNavController.TAB1); } }); btn_openFrgTwo.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { fragNavController.switchTab(FragNavController.TAB2); } }); } private void initView() { btn_openFrgOne = (Button) findViewById(R.id.btn_openOneFragment); btn_openFrgTwo = (Button) findViewById(R.id.btn_openTwoFragment); } }
در این اکتیویتی ابتدا Context و Button ها وکتابخانه FragNavController را تعریف می کنیم.
برای اینکه کدها نظم بهتری داشته باشند سه متد بنام های initView() وonClick() و initFragment(savedInstanceState) ایجاد کرده و آن ها را در onCreate فراخوانی می کنیم.
داخل متد initView ، Button ها را findViewById می کنیم.داخل متد onClick برای Button ها setOnClickListener می نویسیم و داخل متد initFragment، کدهای مربوط به فرگمنت را می نویسیم.
برای ساخت فرگمنت، داخل متد initFragment با کد زیر، یک فرگمنت ایجاد می کنیم:
fragNavController = FragNavController.newBuilder(savedInstanceState , getSupportFragmentManager(),R.id.fl_fragment).transactionListener(new FragNavController.TransactionListener() {
وقتی این خط رو نوشتیم دو تا متد onTabTransaction و onFragmentTransaction رو میاره که فعلا به این دو متد کاری نداریم.
بعد از ایمپورت کردن متدها یک خطا نشان داده می شود که برای رفع آن باید بعد ازپرانتز، کد زیر را بنویسیم:
.rootFragmentListener(new FragNavController.RootFragmentListener() {
با نوشتن این خط، یک متد بنام getRootFragment ، نوشته می شود که برای مشخص کردن تعداد فرگمنت ها و خود فرگمنت ها می باشد.
داخل متد getRootFragment ، ابتدا یک فرگمنت با مقدار null ایجاد کرده، سپس با دستور switch فرگمنت را مقدار دهی می کنیم.
کتابخانه ی FragNavController، بصورت خودکار 20، Tab ایجاد و آن ها را نام گذاری کرده. پس شماره ی Tab را از کتابخانه می گیریم و می نویسیم اگر Tab1 بود مقدار فرگمنت را برابر OneFragment و اگرTab2 بود مقدار فرگمنت را برابر TwoFragment قرار دهد:
switch (i) { case FragNavController.TAB1: fragment = OneFragment.newInstance().setOnTabButtons(new OneFragment.OnTabButtons() { @Override public void onTab() { Toast.makeText(context, "OneFragment", Toast.LENGTH_SHORT).show(); } }); break; case FragNavController.TAB2: fragment = TwoFragment.newInstance().setOnTabButtons(new TwoFragment.OnTabButtons() { @Override public void onTab() { Toast.makeText(context, "TwoFragment", Toast.LENGTH_SHORT).show(); } }); break; }
همچنین با فراخوانی متد setOnTabButtons از داخل کلاس فرگمنت ، متد داخل interface ایمپورت می شود که این متد مربوط به زمانی است که روی دکمه ی داخل فرگمنت کلیک شود. ما برای آن یک Toast تنظیم کردیم، یعنی با کلیک بر روی دکمه ی داخل فرگمنت این Toast نشان داده می شود.
در آخر fragment را return می کنیم. با خطایی برخورد می کنیم که برای رفع آن باید تیکه کد },2).build();
را بعد از کروشه وارد کنیم که تعداد فرگمنت را مشخص می کند.
مرحله ی آخر این است که با کلیک بر روی دکمه های داخل اکتیویتی، فرگمنت ها تغییر کنند. بدین منظور به متد() onClick رفته و با دستور switchTab، مشخص می کنیم با کلیک بر روی هرButton، کدام فرگمنت نشان داده شود:
private void onClick() { btn_openFrgOne.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { fragNavController.switchTab(FragNavController.TAB1); } }); btn_openFrgTwo.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { fragNavController.switchTab(FragNavController.TAB2); } }); }
ساخت فرگمنت به پایان رسید. با اجرا کردن app ، صفحه ی زیر نشان داده می شود:
با کلیک بر روی دکمه های پایین، فرگمنت مربوطه نشان داده می شود.اگر دکمه ی Number2 را کلیک کنید فرگمنت عوض شده و TextView به Number2 تغییر می کند و با کلیک بر روی دکمه ی btn_Fragment یک Toast نشان داده می شود.
این مقاله بصورت انحصاری در تیم توسعه محتوای شرکت طراحی سایت پدیده تجارت ساخته شده.کپی فقط با ذکر منبع مجاز است
نویسنده: الهه ابراهیمی