Fragment(优化布局)
Fragment?
Fragment中文解釋可以理解為“碎片”,Activity的碎片
一個Activity可以有多個Fragment,一個Frgament可以在多個Activity中
Fragment可以看作是一個Activity。
Fragment也可以看作為Activity的一個控件。
?
為什么Fragment可以看作是一個Activity?
Fragment的生命周期與Activity類似?
?
Fragment的生命周?
?
? ? ? ? ??
?
二,與Activity生命周期的對比
?
? ? ?
就是多了onAttach()與Activity關(guān)聯(lián)時調(diào)用,只調(diào)用一次 ? ? ?onDetach()與Activity失去關(guān)聯(lián)時調(diào)用,只調(diào)用一次
onCreateView() 插入Activity時調(diào)用,只調(diào)用一次? onDestoryView()移除Activity時調(diào)用,只調(diào)用一次
onActivityCreatde()Activity的onCreate()方法發(fā)生時調(diào)用
?
?
為什么說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 }這樣就可以實現(xiàn)把R.layout.fragment布局文件變成view對象并在創(chuàng)建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"/>?
效果是一模一樣的。
這種方法叫靜態(tài)加載。
所以當然我們也可以和之前自定義控件一樣,再Activity中實現(xiàn)自定義控件里面的小控件的響應事件,用<fragment>還能再Fragment中設置。
<include>方法是在Activity文件種直接findViewById這些控件,fragment也可以這樣在Activity種findViewById。
還可以在fragment類種定義,不過findViewById方法要在View對象中實現(xiàn),例如:
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中也定義了,這樣的話會只執(zhí)行Activity中的響應。
?
說完了靜態(tài)加載,當然也有動態(tài)加載拉。
動態(tài)加載則需要使用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”就是隱藏,然后調(diào)用方法變成“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可調(diào)用getActivity()方法獲取它所在的Activity
(2)Activity可調(diào)用FragmentManager的findFrgamentById()或findFragmentByTah()方法獲取Fragment
(3)Activity ->Frgament:在Activity中創(chuàng)建Bundle數(shù)據(jù)包,并調(diào)用Fragment的setArgument(Bundle bundle)方法
(4)Fragment ->Activity:需要在Fragment中定義一個內(nèi)部會調(diào)接口,再讓包含該Fragment的Activity實現(xiàn)該回調(diào)接口。這樣Fragment可以用該回調(diào)方法將數(shù)據(jù)傳遞給Activity。
?
實現(xiàn)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內(nèi)部的信息的標識名 5 fragment.setArguments(bundle);在Fragment中:?
1 //Fragment.getArguments方法獲取傳遞過來的bundle對象的信息標識名為“text”的數(shù)據(jù) 2 String text = getArguments().getString("text");//"text"是bundle內(nèi)部的信息的標識名?
?
實現(xiàn)4:
在Fragment中:
(定義內(nèi)部接口)
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中調(diào)用自定義接口的get方法:listener.get(s);
在Activity中:
連接自定義接口,實現(xiàn)get方法:
?1 @Override 2 public void get(String s) { 3 tv.setText(s); 4 }?
?
下面我用一個案例來總結(jié)上面所學的知識:
這個app定義了兩個Activity和兩個Fragment
第一個MianActivity包含兩個按鈕一個是靜態(tài)加載,一個是動態(tài)加載,有一個EditText和TextView用來與MyFragment通信,還有一個Linerlayout用來放動態(tài)加載的Fragment
第二個MainActivtiy2靜態(tài)加載了MyFragemnt,Myfragemnt有一個按鈕,在MianActivity2實現(xiàn)了響應事件
第一個MyFragment關(guān)鍵是有一個按鈕,用來實現(xiàn)動態(tài)加載響應后切換到MyFragment2,還有一個TextView用來與MainActivity通信
第二個MyFragment2關(guān)鍵是有一個按鈕,用ViewStud墮態(tài)加載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);//靜態(tài)加載按鈕bt1.setOnClickListener(new OnClickListener() {public void onClick(View v) {Intent intent = new Intent(MainActivity.this,MainActivity2.class);startActivity(intent);}}); //動態(tài)加載按鈕bt2.setOnClickListener(new OnClickListener() {public void onClick(View v) {n++;MyFragment fragment = new MyFragment();//向fragment中發(fā)送信息String text = et.getText().toString();Bundle bundle = new Bundle();bundle.putString("text", text);//"text"是bundle內(nèi)部的信息的標識名Fragment.setArguments方法發(fā)送bundle對象給Activity fragment.setArguments(bundle);//加載frgamentFragmentManager fragmentManger = getFragmentManager();//Fragment管理器FragmentTransaction beginTransaction = fragmentManger.beginTransaction();//Fragment事務if(n==1)beginTransaction.add(R.id.line, fragment);//添加FragmentelsebeginTransaction.replace(R.id.line, fragment);//替換FragmentbeginTransaction.addToBackStack(null);//把命令加載到棧beginTransaction.commit();//加載棧中的事務 }});}@Overridepublic void get(String s) {tv.setText(s);} }MainAtivity2:
public class MainActivity2 extends Activity {private Button bt;@Overrideprotected 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”的數(shù)據(jù)String text = getArguments().getString("text");//"text"是bundle內(nèi)部的信息的標識名 tv.setText(text);listener.get(s);//點擊按鈕切換另外一個MyFragment2bt.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;@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {// TODO Auto-generated method stubView 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的界面
運行結(jié)果:
??
????
??因為這只是示例的例子,所以沒用優(yōu)化,第五張圖的上面的改變按鈕是按不了的,因為隱藏的控件已經(jīng)出來了,再按程序會崩潰
第二個按鈕是沒有響應事件的,因為它是直接調(diào)用布局,沒用再MainActivitiy中設置隱藏控件的子控件的響應。
雖然再MyFragment中有設置,但是它沒用調(diào)用MyFragment,而是直接調(diào)用布局。
include也是同樣道理,但是fragment卻不同,因為它是布局調(diào)用MyFragment對象。
?
?
如果有什么錯誤,或者我理解錯誤或不當?shù)?#xff0c;懇請大家糾正,謝謝!嘻嘻嘻
轉(zhuǎn)載于:https://www.cnblogs.com/xiaolai1995/p/6527964.html
總結(jié)
以上是生活随笔為你收集整理的Fragment(优化布局)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Oracle查询数据库中所有表的记录数
- 下一篇: 工作中Docker使用命令笔记