Fragment android
Fragment中文解釋能夠理解爲「碎片」,Activity的碎片app
一個Activity能夠有多個Fragment,一個Frgament能夠在多個Activity中ide
Fragment能夠看做是一個Activity。佈局
Fragment也能夠看做爲Activity的一個控件。優化
爲何Fragment能夠看做是一個Activity?this
Fragment的生命週期與Activity相似 spa
Fragment的生命周 3d
二,與Activity生命週期的對比code
就是多了onAttach()與Activity關聯時調用,只調用一次 onDetach()與Activity失去關聯時調用,只調用一次xml
onCreateView() 插入Activity時調用,只調用一次 onDestoryView()移除Activity時調用,只調用一次
onActivityCreatde()Activity的onCreate()方法發生時調用
爲何說Fragment相對與一個控件呢?
其實Fragment的一個重要做用就是把佈局文件變成一個View對象,而後把View對象插入到Activity中
怎麼把佈局變成View對象呢?
1 public class MyFragment extends Fragment{ 2 @Override 3 public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) { 4 View view = inflater.inflate(R.layout.fragment, container, false); 5 return view; 6 } 7 }
這樣就能夠實現把R.layout.fragment佈局文件變成view對象並在建立MyFragment對象時返回,至關與把這個佈局變成了一個自定義的控件
而後就能夠在咱們的另一個佈局文件中直接用咱們的View對象。把這個佈局插入到Activity類中。
在xml文件中加入這個控件就能夠了,注意必定要定義id,和name,name屬性爲Fragement類的具體位置(包名.類名)
1 <fragment 2 android:id="@+id/fragment" 3 android:layout_width="wrap_content" 4 android:layout_height="wrap_content" 5 android:name="com.example.z_fragment.MyFragment"/>
這個效果就和咱們以前講過的自定義控件的一個方法同樣。代碼以下
1 <include layout="@layout/fragment" 2 android:layout_width="wrap_content" 3 android:layout_height="wrap_content"/>
效果是如出一轍的。
這種方法叫靜態加載。
因此固然咱們也能夠和以前自定義控件同樣,再Activity中實現自定義控件裏面的小控件的響應事件,用<fragment>還能再Fragment中設置。
<include>方法是在Activity文件種直接findViewById這些控件,fragment也能夠這樣在Activity種findViewById。
還能夠在fragment類種定義,不過findViewById方法要在View對象中實現,例如:
1 public class MyFragment extends Fragment{ 2 private Button bt; 3 public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) { 4 View view = inflater.inflate(R.layout.fragment, container, false); 5 bt = (Button)view.findViewById(R.id.btf); 6 bt.setOnClickListener(new OnClickListener() { 7 public void onClick(View v) { 8 } 9 }); 10 return view; 11 } 12 }
不過值得注意的是,若是fragment中定義了響應的具體事件,Activity中也定義了,這樣的話會只執行Activity中的響應。
說完了靜態加載,固然也有動態加載拉。
動態加載則須要使用FragmentManger類中的事務 經過事務的add(),remove(),replace()等方法,添加,刪除,替換Fragment對象。
1 MyFragment fragment = new MyFragment(); 2 //加載frgament 3 FragmentManager fragmentManger = getFragmentManager();//Fragment管理器 4 FragmentTransaction beginTransaction = fragmentManger.beginTransaction();//Fragment事務 5 beginTransaction.add(R.id.line, fragment);//添加Fragment 6 beginTransaction.addToBackStack(null);//把命令加載到棧 7 beginTransaction.commit();//加載棧中的事務
上面的代碼是把fragment對象加載到Activity佈局文件中的中的一個編號爲(R.id.line)的線性佈局當中。
這樣咱們就能夠在應用進行的時候隨時插入或者移出frgament,或者控件
提及隨時插入或者移出控件還有一種方法(ViewStub標籤)
1 <ViewStub 2 android:id="@+id/vs" 3 android:layout ="@layout/fragment"" 4 android:layout_width="wrap_content" 5 android:layout_height="wrap_content"/>
而後經過實例化這個控件,經過它的inflate()惰性加載的方法把裏面的東西顯示出來
其實控件自身也有隱藏的屬性,android:visibility=「gone」就是隱藏,而後調用方法變成「visbe」就不隱藏。
說到這裏,順便說一些佈局注意事項把,咱們用佈局的時候儘可能多用線性佈局和相對佈局 LinearLayout和RelativeLayout。
nergae標籤能夠把控件組合起來:
例如:
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:orientation="vertical" > 6 <ProgressBar 7 android:id="@+id/progressBar1" 8 style="?android:attr/progressBarStyleLarge" 9 android:layout_width="wrap_content" 10 android:layout_height="wrap_content" /> 11 <TextView 12 android:id="@+id/textView1" 13 android:layout_width="wrap_content" 14 android:layout_height="wrap_content" 15 android:text="TextView" /> 16 </LinearLayout>是這樣的
1 <?xml version="1.0" encoding="utf-8"?> 2 <merge xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:orientation="vertical" > 6 <ProgressBar 7 android:id="@+id/progressBar1" 8 style="?android:attr/progressBarStyleLarge" 9 android:layout_width="wrap_content" 10 android:layout_height="wrap_content" /> 11 <TextView 12 android:id="@+id/textView1" 13 android:layout_width="wrap_content" 14 android:layout_height="wrap_content" 15 android:text="TextView" /> 16 </merge>
至關與一個禎佈局。
好,讓咱們回到Fragment的最後一個知識點,Fragment與Activity通訊。
(1)Fragment可調用getActivity()方法獲取它所在的Activity
(2)Activity可調用FragmentManager的findFrgamentById()或findFragmentByTah()方法獲取Fragment
(3)Activity ->Frgament:在Activity中建立Bundle數據包,並調用Fragment的setArgument(Bundle bundle)方法
(4)Fragment ->Activity:須要在Fragment中定義一個內部會調接口,再讓包含該Fragment的Activity實現該回調接口。這樣Fragment能夠用該回調方法將數據傳遞給Activity。
實現3:
在Activity中:
1 MyFragment fragment = new MyFragment(); 2 String text = et.getText().toString(); 3 Bundle bundle = new Bundle(); 4 bundle.putString("text", text);//"text"是bundle內部的信息的標識名 5 fragment.setArguments(bundle);
在Fragment中:
1 //Fragment.getArguments方法獲取傳遞過來的bundle對象的信息標識名爲「text」的數據 2 String text = getArguments().getString("text");//"text"是bundle內部的信息的標識名
實現4:
在Fragment中:
(定義內部接口)
1 private String s="收到了"; 2 private MyListener listener; 3 public interface MyListener{ 4 public void get(String s); 5 } 6 public void onAttach(Activity activity){ 7 listener =(MyListener)activity;//把Activity強制變成自定義接口 8 super.onAttach(activity); 9 }
而後在onCreateView中調用自定義接口的get方法:listener.get(s);
在Activity中:
鏈接自定義接口,實現get方法:
1 @Override 2 public void get(String s) { 3 tv.setText(s); 4 }
下面我用一個案例來總結上面所學的知識:
這個app定義了兩個Activity和兩個Fragment
第一個MianActivity包含兩個按鈕一個是靜態加載,一個是動態加載,有一個EditText和TextView用來與MyFragment通訊,還有一個Linerlayout用來放動態加載的Fragment
第二個MainActivtiy2靜態加載了MyFragemnt,Myfragemnt有一個按鈕,在MianActivity2實現了響應事件
第一個MyFragment關鍵是有一個按鈕,用來實現動態加載響應後切換到MyFragment2,還有一個TextView用來與MainActivity通訊
第二個MyFragment2關鍵是有一個按鈕,用ViewStud墮態加載fragment。
示例代碼:
MianActivity:
public class MainActivity extends Activity implements MyListener{ private Button bt1,bt2; private EditText et; private TextView tv; private int n=0; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bt1 = (Button)findViewById(R.id.button1); bt2 = (Button)findViewById(R.id.button2); et = (EditText)findViewById(R.id.et); tv = (TextView)findViewById(R.id.tv); //靜態加載按鈕 bt1.setOnClickListener(new OnClickListener() { public void onClick(View v) { Intent intent = new Intent(MainActivity.this,MainActivity2.class); startActivity(intent); } }); //動態加載按鈕 bt2.setOnClickListener(new OnClickListener() { public void onClick(View v) { n++; MyFragment fragment = new MyFragment(); //向fragment中發送信息 String text = et.getText().toString(); Bundle bundle = new Bundle(); bundle.putString("text", text);//"text"是bundle內部的信息的標識名 ////Fragment.setArguments方法發送bundle對象給Activity fragment.setArguments(bundle); //加載frgament FragmentManager fragmentManger = getFragmentManager();//Fragment管理器 FragmentTransaction beginTransaction = fragmentManger.beginTransaction();//Fragment事務 if(n==1) beginTransaction.add(R.id.line, fragment);//添加Fragment else beginTransaction.replace(R.id.line, fragment);//替換Fragment beginTransaction.addToBackStack(null);//把命令加載到棧 beginTransaction.commit();//加載棧中的事務 } }); } @Override public void get(String s) { tv.setText(s); } }
MainAtivity2:
public class MainActivity2 extends Activity { private Button bt; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main2); bt = (Button)findViewById(R.id.btf); bt.setOnClickListener(new OnClickListener() { public void onClick(View v) { Toast toast = Toast.makeText(MainActivity2.this, "被點了", Toast.LENGTH_SHORT); toast.show(); } }); } }
MyFragment:
public class MyFragment extends Fragment{ private Button bt; private TextView tv; private String s="收到了"; private MyListener listener; public interface MyListener{ public void get(String s); } public void onAttach(Activity activity){ listener =(MyListener)activity;//把Activity強制變成自定義接口 super.onAttach(activity); } public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment, container, false); bt = (Button)view.findViewById(R.id.btf); tv = (TextView)view.findViewById(R.id.tvf1); //Fragment.getArguments方法獲取傳遞過來的bundle對象的信息標識名爲「text」的數據 String text = getArguments().getString("text");//"text"是bundle內部的信息的標識名 tv.setText(text); listener.get(s); //點擊按鈕切換另一個MyFragment2 bt.setOnClickListener(new OnClickListener() { public void onClick(View v) { MyFragment2 fragment = new MyFragment2(); FragmentManager fragmentManger = getFragmentManager(); FragmentTransaction beginTransaction = fragmentManger.beginTransaction(); beginTransaction.replace(R.id.line, fragment); beginTransaction.addToBackStack(null); beginTransaction.commit(); } }); return view; } }
MyFragment2:
public class MyFragment2 extends Fragment{ private Button bt; private ViewStub vs; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // TODO Auto-generated method stub View view = inflater.inflate(R.layout.fragment2, container, false); bt = (Button)view.findViewById(R.id.btf2); vs = (ViewStub)view.findViewById(R.id.vs); bt.setOnClickListener(new OnClickListener() { public void onClick(View v) { vs.inflate(); } }); return view; } }
MainAtivity界面:
MianAtivity2和MyFragment2的界面:(其中MyFragmnet2隱藏了一個MyFragemnt界面)
MyFragmet2的界面
運行結果:
由於這只是示例的例子,因此沒用優化,第五張圖的上面的改變按鈕是按不了的,由於隱藏的控件已經出來了,再按程序會崩潰
第二個按鈕是沒有響應事件的,由於它是直接調用佈局,沒用再MainActivitiy中設置隱藏控件的子控件的響應。
雖然再MyFragment中有設置,可是它沒用調用MyFragment,而是直接調用佈局。
include也是一樣道理,可是fragment卻不一樣,由於它是佈局調用MyFragment對象。
若是有什麼錯誤,或者我理解錯誤或不當的,懇請你們糾正,謝謝!嘻嘻嘻