Fragment ها
بسم الله الرحمن الرحیم
Fragment ها
فصل دوم-بخش دهم
در بخش قبلی شما یاد گرفتید که activity چیست و چگونه از ان استفاده می کنید.
در صفحه نمایش ها با عرضه صفحه کم معمولا activity کل صفحه را در بر می گیرید و انواع view ها که در بر گیرنده UI برنامه می باشد را در بر می گیرید. یک activity به طور ذاتی در بر گیرنده View ها می باشند. با این ها زمان های وجود دارد که یک activity در وسایل که دارای صفحه نمایش ها بزرگ هستند استفاده می شود مانند tablet ها و این قدری بزرگ تر از activity ها می باشند و به خاطر همین View ها کمی خارج از محل خود هستند View ها باید در صفحه مرتب تنظیم شوند تا کل صفحه را در بر گیرند. که این کار کمی پیچیده می باشد.بهترین راه استفاده از “mini-activity ” ها می باشد. که هر کدام شامل view خودش می باشد. در زمان اجرا هر activity شامل یک یا بیشتر "mini-activity" می باشد. که بستگی به صفحه نمایش دستگاه دارد.
در اندروید نسخه 3.0 و بالاتر "miniactivity" ها با عنوان Fragment شناخته می شوند.
این طور فکر کنید که fragment ها قالب دیگری از activity ها می باشند. شما fragment ها ایجاد می کنید که View ها می باشد درست مانند activity ها .
Fragment ها همیشه در activity ها جاسازی می شوند.
به عنوان مثال شکل زیر دو Fragment را نمایش می دهد.Fragment1 می تواند شامل ListView باشد لیست از کتاب ها می باشد که به کاربر نمایش داده می شود. و fragment2 شامل TextViews and ImageViews باشد که در بر گیرنده متن و تصاویر مربوط به کتاب انتخاب شده می باشد.
حال فرض کنید که برنامه اندروید در حال اجرا است و Tablet در حالت portrait (حالتی که فقط یک activity در صفحه نمایش داده می شود.) قرار دارد در این مورد ممکن است fragment1 در یک activyt جاسازی شود و fragment 2 در activity دیگر قرار گیرد زمانی که ایتمی از fragment1 انتخاب شود fragment2 اجرا شود.
حال فرض کنید در حالت landscape mode قرار دارد هر دو این Fragment ها می توانند در یک activity جاسازی سوند.
به مثال زیر توجه کنید .
یک پروژه جدید به نام Fragments. ایجاد کنید
در مسیر یک فایل xml جدید به نامres/layout ایجاد کنید و دستوارت زیر را به آن اضافه کنید.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#00FF00"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="This is fragment #1"
android:textColor="#000000"
android:textSize="25sp" />
</LinearLayout>
و در همان مسیر یک فایل دیگر با نامfragment2.xml ایجاد کنید و دستورات زیر به آن اضافه کنید.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#FFFE00"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="This is fragment #2"
android:textColor="#000000"
android:textSize="25sp" />
</LinearLayout>
در فایل main,xml دستوارات زیر را وارد نماییید.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<fragment
android:name="com.MehrdadJavidi.Fragments.Fragment1"
android:id="@+id/fragment1"
android:layout_weight="1"
android:layout_width="0px"
android:layout_height="match_parent" />
<fragment
android:name="com.MehrdadJavidi.Fragments.Fragment2"
android:id="@+id/fragment2"
android:layout_weight="1"
android:layout_width="0px"
android:layout_height="match_parent" />
</LinearLayout>
در زیر شاخته com.MehrdadJavidi.Fragments دو فایل جاوا بانام Fragment1.java , Fragment2 ایجاد کنید
دستورات زیر را درFragment1.java اضافه کنید.
package com.MehrdadJavidi.fragments;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
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 وارد کنید
package com.MehrdadJavidi.fragments;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
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.fragment1, container, false);
}
}
F11 را بزنید و برنامه را اجرا کنید. مشاهده می کنید که دو Fragmnet در یک activity قرار دارند.
توضیحات
یک Fragment بسیار شبیه یک activity رفتار می کند. او یک کلاس Java می باشد که UI با فرمت Xml را بار گذاری می کند. و فایل Xml شامل تمام Ui ها ی که در activity استفاده می شد می باشد از قبیل TextView ها ,EditTextها ,Button و مواردی از این قبیل.
کلاس جاوا برای یک fragment نیار دارد تا از کلاس پایه Fragment مشتق(Extend) شود.
public class Fragment1 extends Fragment
}
}
برای استفاده از Ui برای Fragment ها باید از متد onCreateView() را override کنید
این متد نیاز دارد تا یک View بر گرداند مانند زیر
public View onCreateView(LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
/**---Inflate the layout for this fragment---*/
return inflater.inflate(
R.layout.fragment1, container, false);
در اینجا شما از یک شی LayoutInflater استفاده کردید که به شما امکان تعیین Ui ها از فایل Xml می دهد.( R.layout.fragment1)
و پارامتر container به یک ViewGroup, اشاره می کند که activity می باشد که شما در حال جاسازی کردن (embed) Fragment ها در آن هستید می باشد.. و پارا متر savedInstanceState شما را قادر می سازد که Fragment ها را که هنوز در حالت قبلی هستند را بازیابی کنید .
برای اضافه کردن Fragment ها به یک activity شما از <Fragment> استفاده می کنید.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<fragment
android:name="com.MehrdadJavidi.Fragments.Fragment1"
android:id="@+id/fragment1"
android:layout_weight="1"
android:layout_width="0px"
android:layout_height="match_parent" />
<fragment
android:name="com.MehrdadJavidi.Fragments.Fragment2"
android:id="@+id/fragment2"
android:layout_weight="1"
android:layout_width="0px"
android:layout_height="match_parent" />
</LinearLayout>
توجه داشته باشید که در اینجا لازم است که هر Fragment یک راه شناسایی منحصر به فرد داشته باشد که شما می توانید از android:id یا android:tagاستفاده کنید
اضافه کردن Fragment ها به صورت Dynamic
در حالی که Fragment ها شما قادر می سازند که Ui ها به قسمت های مختلفی پیکر بندی کنید, قدرت اصلی Fragment ها این می باشد که شما می توانید آن های را به صورت Dynamic در زمان اجرا به activity خود اضافه کنید. در بخش قبلی شما دیدید که ما Fragment ها و فایل Xml را مربوط به آن های را قبل از اجرا برنامه تنظیم کردیم. اگر ما بتوانیم Fragment ها را ایجاد و در زمان اجرای برنامه آن را به Activity اضافه کنیم. این می تواند بسیار مفید باشد . این کار شما را قاد می سازد تا یک User InterFace به صورت customizable برای برنامه کاربردی خود ایجاد کنید . به عنوان مثال اگر برنامه شما بر روی یک smartPhone اجرا شد شما ممکن تنها یک Fragment را در activity قرار دهید ولی اگر بر روی یک tablet اجرا شد شما ممکن است بیش از یک Fragment را در activity قرار دهیم به دلیل این که صفحه نمایش tablet ها بزرگتر از amrtphone ها می باشد.
حال آن را با یک مثال شرح می دهیم.
در همان پروژه قبلی فایل main.xml را به صورت زیر تغییر دهید. و <Fragment> ها را به صورت Comment در بیاوربد.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<!-- <fragment
android:name="com.MehrdadJavidi.Fragments.Fragment1"
android:id="@+id/fragment1"
android:layout_weight="1"
android:layout_width="0px"
android:layout_height="match_parent" />
<fragment
android:name="com.MehrdadJavidi.Fragments.Fragment2"
android:id="@+id/fragment2"
android:layout_weight="1"
android:layout_width="0px"
android:layout_height="match_parent" />
-->
</LinearLayout>
. و د ر فایل mainActivity.java دستورات زیر را اضافه کنید.
package com.MehrdadJavidi.fragments;
import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.view.Display;
import android.view.WindowManager;
public class MainActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction =
fragmentManager.beginTransaction();
/**---get the current display info---*/
WindowManager wm = getWindowManager();
Display d = wm.getDefaultDisplay();
if (d.getWidth() > d.getHeight())
{
/**---landscape mode---*/
Fragment1 fragment1 = new Fragment1();
/** android.R.id.content refers to the content*/
/** view of the activity*/
fragmentTransaction.replace(
android.R.id.content, fragment1);
}
else
{
/**---portrait mode---*/
Fragment2 fragment2 = new Fragment2();
fragmentTransaction.replace(
android.R.id.content, fragment2);
}
fragmentTransaction.commit();
}
}
حال برنامه را با زدن F11 اجرا کنید.
مشاهده می کنید زمانی که emulator در حالت portrait می باشد Fragment2 که زرد می باشد نمایش داده می شود . و اگر Ctrl+F11 را فشار دهیم. emulator به حالت landscape, می رود و fragment 1 که سبز می باشد نمایش داده می شود.
توضیحات
شما برای اضافه کردن یک Fragment باید یک از کلاس FragmentManager که در برگیرنده یک نمونه از آن مباشد استفاده کنید
FragmentManager fragmentManager = getFragmentManager();
شما همچنین نیاز دارید که از کلاس FragmentTransaction برا ی انجام transactions ها به activity خود استفا ده می کنید(از قبیل اضافه کردن و خذف کردن و جایگزین کردن و..)
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction =
fragmentManager.beginTransaction();
در این مثال شما نیاز دارید که بدانید که وسایل که استفاده می کنیم در حالت portrait می باشد یا در حالت landscape. که برای این کار از کلاس WindowManager استفاده می کنیم. زمانی که این را تشخیص دادیم متد replace() مربروط FragmentTransaction برای اضافه کردن Fragment و View آن استفاده می کنیم.
Fragment1 fragment1 = new Fragment1();
/** android.R.id.content refers to the content*/
/** view of the activity
fragmentTransaction.replace(
android.R.id.content, fragment1);
برای اینکه اطمینان حاص کنیم که تغییرات اتفاق افتاد ه از متد commit() را فراخوانی می کنیم.
fragmentTransaction.commit();
چرخه زندگی Fragment
همانند activity ها Fragment ها هم دارای یک چرخه زندگی می باشند.
برای متوجه شدند چرخه زندگی Fragment ها ان را با یک مثال شرح م دهیم.
در پروژه قبلی به فایل Fragment1.java رفته و دستورات زیر را وارد کنید.
import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class Fragment1 extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
Log.d("Fragment 1", "onCreateView");
/**---Inflate the layout for this fragment---*/
return inflater.inflate(
R.layout.fragment1, container, false);
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
Log.d("Fragment 1", "onAttach");
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("Fragment 1", "onCreate");
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Log.d("Fragment 1", "onActivityCreated");
}
@Override
public void onStart() {
super.onStart();
Log.d("Fragment 1", "onStart");
}
@Override
public void onResume() {
super.onResume();
Log.d("Fragment 1", "onResume");
}
@Override
public void onPause() {
super.onPause();
Log.d("Fragment 1", "onPause");
}
@Override
public void onStop() {
super.onStop();
Log.d("Fragment 1", "onStop");
}
@Override
public void onDestroyView() {
super.onDestroyView();
Log.d("Fragment 1", "onDestroyView");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d("Fragment 1", "onDestroy");
}
@Override
public void onDetach() {
super.onDetach();
Log.d("Fragment 1", "onDetach");
}
}
برنامه را اجرا کنید . در محیط emulator کلید ctrl+F11 را فشار دهید.
در پنجره LogCat موارد زیر ا مشاهده می کنید
کلید Home را در emulator را فشار دهید در پنجره LogCat موارد زیر ا مشاهده می کنید
حال دکمه Home را نگه دارید و دوباره برنامه اجرا کنید. در پنجره LogCat موارد زیر ا مشاهده می کنید
حال دکمه back را نگه دارید . در پنجره LogCat موارد زیر ا مشاهده می کنید
توضیحات
همانند activity ها Fragment ها دارای چرخه زندگی خودشان را دارند.
همان طور که مشاهده کردید زمانی که یک Fragment اجرا می شود در وضعیت های زیر قرار می گیربد.
- onAttach()
- onCreate()
- onCreateView()
- onActivityCreated()
زمانی که fragment برای کاربر نمایان می شود در وضعیت های زیر قرا می گیرد.
- onStart()
- onResume()
زمانی که یک Fragment د ر حالت background قرار می گیرد به وضعیت ها زیر می رود
- onPause()
- onStop()
زمانی که Fragment از بین می رود (destroyed می شود) وضعیت های زیر را طی می کند.
- onPause()
- onStop()
- onDestroyView()
- onDestroy()
- onDetach()
همانند activity ها شما می توانید یک نمونه از Fragmetn را با شی Bundle فراخونی کنید که در وضعیت های زیر قرار می گیرید.
- onCreate()
- onCreateView()
- onActivityCreated()
بیشتر وضعیت های یک Fragment بسیار شبیه یک Activity می باشد و لی با همین حال بعضی از وضعیت ها را که جدید می باشند را شرح می دهم.
- onAttached() : زمانی فرا خوانی می شود که Fragment با activity پیوند خورده (associated)است.
- onCreateView()-برای ساخت View برای fragment فراخوانی می شود
- onActivityCreated()– زمان فراخوانی میشود که متد onCreate() مربوط به activity اجرا شده باشد.
- onDestroyView()- زمانی که View مربوط به Fragmetn در حال Remove شدن باشد .
- onDetach()- زمانی که یک Fragment در از activity جدا می شود.
توجه کنید که یکی از تفاوت های اصلی بین activity و Fragment این می باشد که زمانی که یک activity به background می رود. Activity در Stack به نام back جاسازی می شود که این اجازه می دهد تا زمانی که دکمهback را می زنیم به حات resumedبرود. در حالی که برای Fragment ها چنین اتفاقی نمی افتد و به صورت اتوماتیک در Back Stack زمانی که در background هستند جا سازی نمی شود.
برای اینکه fragment ها در back Stack قرار گیرند شما باید از متدی به نام addToBackStack() استفا ده کنید.
WindowManager wm = getWindowManager();
Display d = wm.getDefaultDisplay();
if (d.getWidth() > d.getHeight())
{
/**---landscape mode---*/
Fragment1 fragment1 = new Fragment1();
/** android.R.id.content refers to the content*/
/** view of the activity*/
fragmentTransaction.replace(
android.R.id.content, fragment1);
}
else
{
/**---portrait mode---*/
Fragment2 fragment2 = new Fragment2();
fragmentTransaction.replace(
android.R.id.content, fragment2);
}
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
ارتباط بین fragment ها
در اغلب موارد ممکن است که یک activity شامل بیش از یک Fragment باشد که با هم در ارتباط می باشند. در این موارد بسیار مهم می باشد که fragment ها بتوانند بتوانند باهم داده های را با هم رد و بدل کنند. به عنوان مثال ممکن در یک Fragment لیستی از ایتم های باشد و زمانی که کاربر آن را انتخاب کرد جزئئات آن در Fragmet دیگر نمایش داده می شود.
مثال از ارتباط بین fragment ها
درهمان پروژه قبلی دستورات را به فایل Fragment1.xml اضافه کنید
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#00FF00" >
<TextView
android:id="@+id/lblFragment1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="This is fragment #1"
android:textColor="#000000"
android:textSize="25sp" />
</LinearLayout>
دستورات در فایلfragment2.xml اضافه کنید
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#FFFE00" >
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="This is fragment #2"
android:textColor="#000000"
android:textSize="25sp" />
<Button
android:id="@+id/btnGetText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Get text in Fragment #1"
android:textColor="#000000"
android:onClick="onClick" />
</LinearLayout>
در فایل main.xml آنهای که به صورت Comment هستند از حالت Comment در آورد.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<fragment
android:name="com.MehrdadJavidi.Fragments.Fragment1"
android:id="@+id/fragment1"
android:layout_weight="1"
android:layout_width="0px"
android:layout_height="match_parent" />
<fragment
android:name="com.MehrdadJavidi.Fragments.Fragment2"
android:id="@+id/fragment2"
android:layout_weight="1"
android:layout_width="0px"
android:layout_height="match_parent" />
</LinearLayout>
فایل mainActivity.java به صورت زیر تغییر دهید. و دستوات به صورت comment در آورد.
package com.MehrdadJavidi.fragments;
import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.view.Display;
import android.view.WindowManager;
public class MainActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/*FragmentManager fragmentManager = getFragmentManager();*/
FragmentTransaction fragmentTransaction =
fragmentManager.beginTransaction();
/**---get the current display info---*/
WindowManager wm = getWindowManager();
Display d = wm.getDefaultDisplay();
if (d.getWidth() > d.getHeight())
{
/**---landscape mode---*/
Fragment1 fragment1 = new Fragment1();
/** android.R.id.content refers to the content*/
/** view of the activity*/
fragmentTransaction.replace(
android.R.id.content, fragment1);
}
else
{
/**---portrait mode---*/
Fragment2 fragment2 = new Fragment2();
fragmentTransaction.replace(
android.R.id.content, fragment2);
}
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();*/
}
}
و در فایل Fragment2.java دستورات زیر وارد کنید
package com.MehrdadJavidi.fragments;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
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);
}
@Override
public void onStart() {
super.onStart();
/**---Button view---
Button btnGetText = (Button)
getActivity().findViewById(R.id.btnGetText);
btnGetText.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
TextView lbl = (TextView)
getActivity().findViewById(R.id.lblFragment1);
Toast.makeText(getActivity(), lbl.getText(),
Toast.LENGTH_SHORT).show();
}
برنامه را با زدن F11 اجرا کنید.
توضیحات
به دلیل این که fragment ها در activityها قرار دارند شما باید ابتدا activity جاری را با متد getActivity() و سپس view ی که در آن قرار دارد را با متد findViewById() بدست آورید .
TextView lbl = (TextView)
getActivity().findViewById(R.id.lblFragment1);
Toast.makeText(getActivity(), lbl.getText(),
Toast.LENGTH_SHORT).show();
متد, getActivity() activityی که fragment در ان قرار دارد را بر می گرداند
نظرات (۱)
با عرض سلام
اگر امکانش هست در مورد خطا و مشکل بیشتر توضیح بدهید، طبیعتا با این اطلاعات نمی توان علت مشکل را متوجه شد.
همچنین می توانید از طریق لینک زیر مثالی را که برای شما آماده کرده ایم دانلود و بررسی نمایید.