33.Android之Fragment学习
Fragment
Android是在Android 3.0 (API level 11)开始引入Fragment的。
可以把Fragment想成Activity中的模块,这个模块有自己的布局,有自己的生命周期,单独处理自己的输入,在Activity运行的时候可以加载或者移除Fragment模块。
可以把Fragment设计成可以在多个Activity中复用的模块。
当开发的应用程序同时适用于平板电脑和手机时,可以利用Fragment实现灵活的布局,改善用户体验。
如图:
Fragment的生命周期
因为Fragment必须嵌入在Acitivity中使用,所以Fragment的生命周期和它所在的Activity是密切相关的。
如果Activity是暂停状态,其中所有的Fragment都是暂停状态;如果Activity是stopped状态,这个Activity中所有的Fragment都不能被启动;如果Activity被销毁,那么它其中的所有Fragment都会被销毁。
但是,当Activity在活动状态,可以独立控制Fragment的状态,比如加上或者移除Fragment。
当这样进行fragment transaction(转换)的时候,可以把fragment放入Activity的back stack中,这样用户就可以进行返回操作。
Fragment的使用相关
使用Fragment时,需要继承Fragment或者Fragment的子类(DialogFragment, ListFragment, PreferenceFragment, WebViewFragment),所以Fragment的代码看起来和Activity的类似。
今天我就模仿微信界面写个fragment例子,来小结下fragment学习。
首先添加四个要添加的fragment类,如图:
weixinframent.java代码:
1 package com.example.fragmentdemo; 2 3 import android.app.Fragment; 4 import android.os.Bundle; 5 import android.view.LayoutInflater; 6 import android.view.View; 7 import android.view.ViewGroup; 8 9 public class weixinframent extends Fragment 10 { 11 12 public static final String FRAGMENT_TAG = weixinframent.class.getName(); 13 @Override 14 public View onCreateView(LayoutInflater inflater, ViewGroup container, 15 Bundle savedInstanceState) 16 { 17 return inflater.inflate(R.layout.layout1, container, false); 18 } 19 20 }
telfragment.java代码:
1 package com.example.fragmentdemo; 2 3 import android.app.Fragment; 4 import android.os.Bundle; 5 import android.view.LayoutInflater; 6 import android.view.View; 7 import android.view.ViewGroup; 8 9 public class telfragment extends Fragment 10 { 11 12 public static final String FRAGMENT_TAG = telfragment.class.getName(); 13 @Override 14 public View onCreateView(LayoutInflater inflater, ViewGroup container, 15 Bundle savedInstanceState) 16 { 17 return inflater.inflate(R.layout.layout2, container, false); 18 } 19 20 }
findfragment.java代码:
1 package com.example.fragmentdemo; 2 3 import android.app.Fragment; 4 import android.os.Bundle; 5 import android.view.LayoutInflater; 6 import android.view.View; 7 import android.view.ViewGroup; 8 9 public class findfragment extends Fragment 10 { 11 12 public static final String FRAGMENT_TAG = findfragment.class.getName(); 13 @Override 14 public View onCreateView(LayoutInflater inflater, ViewGroup container, 15 Bundle savedInstanceState) 16 { 17 return inflater.inflate(R.layout.layout3, container, false); 18 } 19 20 }
mefragment.java代码:
1 package com.example.fragmentdemo; 2 3 import android.app.Fragment; 4 import android.os.Bundle; 5 import android.view.LayoutInflater; 6 import android.view.View; 7 import android.view.ViewGroup; 8 9 public class mefragment extends Fragment 10 { 11 public static final String FRAGMENT_TAG = mefragment.class.getName(); 12 @Override 13 public View onCreateView(LayoutInflater inflater, ViewGroup container, 14 Bundle savedInstanceState) 15 { 16 return inflater.inflate(R.layout.layout4, container, false); 17 } 18 19 }
然后增加四个fragment对应的布局文件,如图:
layout1.xml:
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 7 <TextView 8 android:layout_width="match_parent" 9 android:layout_height="match_parent" 10 android:gravity="center" 11 android:text="这是一个微信 fragment" /> 12 13 </LinearLayout>
layout2.xml:
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 7 <TextView 8 android:layout_width="match_parent" 9 android:layout_height="match_parent" 10 android:gravity="center" 11 android:text="这是一个通信录 fragment" /> 12 13 </LinearLayout>
layout3.xml:
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 7 <TextView 8 android:layout_width="match_parent" 9 android:layout_height="match_parent" 10 android:gravity="center" 11 android:text="这是一个发现 fragment" /> 12 13 </LinearLayout>
layout4.xml:
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 7 <TextView 8 android:layout_width="match_parent" 9 android:layout_height="match_parent" 10 android:gravity="center" 11 android:text="这是一个我 fragment" /> 12 13 </LinearLayout>
接着修改主布局文件:
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 android:id="@+id/main_root"> 7 8 <RelativeLayout 9 android:layout_width="match_parent" 10 android:layout_height="match_parent" 11 android:orientation="vertical"> 12 13 <RelativeLayout 14 android:id="@+id/bottom_layout" 15 android:layout_width="fill_parent" 16 android:layout_height="wrap_content" 17 android:layout_alignParentBottom="true"> 18 19 <View 20 android:id="@+id/top_line" 21 android:layout_width="fill_parent" 22 android:layout_height="0.5dp" 23 android:layout_alignParentTop="true" 24 android:background="#19000000"/> 25 26 <LinearLayout 27 android:layout_width="fill_parent" 28 android:layout_height="48dp" 29 android:layout_below="@id/top_line" 30 android:background="#D3FFFFFF" 31 android:orientation="horizontal"> 32 33 <LinearLayout 34 android:id="@+id/tab1_layout" 35 android:layout_width="fill_parent" 36 android:layout_height="match_parent" 37 android:layout_weight="1" 38 android:orientation="vertical"> 39 40 <ImageView 41 android:id="@+id/imageView1" 42 android:layout_width="24dp" 43 android:layout_height="24dp" 44 android:layout_gravity="center_horizontal" 45 android:layout_marginTop="4dp" 46 android:background="@drawable/tab1"/> 47 48 <TextView 49 android:id="@+id/tab1_textview" 50 android:layout_width="fill_parent" 51 android:layout_height="wrap_content" 52 android:layout_marginTop="2dp" 53 android:gravity="center_horizontal" 54 android:text="微信" 55 android:textSize="10sp"/> 56 </LinearLayout> 57 58 <LinearLayout 59 android:id="@+id/tab2_layout" 60 android:layout_width="fill_parent" 61 android:layout_height="match_parent" 62 android:layout_weight="1" 63 android:orientation="vertical" 64 android:gravity="center"> 65 66 <RelativeLayout 67 android:layout_width="40dp" 68 android:layout_height="wrap_content"> 69 70 <LinearLayout 71 android:layout_width="30dp" 72 android:orientation="vertical" 73 android:layout_height="fill_parent" 74 android:layout_centerInParent="true"> 75 76 <ImageView 77 android:layout_width="24dp" 78 android:layout_height="24dp" 79 android:layout_gravity="center_horizontal" 80 android:layout_marginTop="4dp" 81 android:background="@drawable/tab2"/> 82 83 <TextView 84 android:id="@+id/tab2_textview" 85 android:layout_width="fill_parent" 86 android:layout_height="wrap_content" 87 android:layout_marginTop="2dp" 88 android:gravity="center_horizontal" 89 android:text="通信录" 90 91 android:textSize="10sp"/> 92 </LinearLayout> 93 94 <View 95 android:id="@+id/flag_red_dot" 96 android:layout_width="8dp" 97 android:layout_height="8dp" 98 android:layout_marginTop="4dp" 99 android:layout_alignParentRight="true" 100 android:visibility="gone" 101 /> 102 103 </RelativeLayout> 104 </LinearLayout> 105 106 <LinearLayout 107 android:id="@+id/tab3_layout" 108 android:layout_width="fill_parent" 109 android:layout_height="match_parent" 110 android:layout_weight="1" 111 android:orientation="vertical"> 112 113 <ImageView 114 android:layout_width="24dp" 115 android:layout_height="24dp" 116 android:layout_gravity="center_horizontal" 117 android:layout_marginTop="4dp" 118 android:background="@drawable/tab3"/> 119 120 <TextView 121 android:id="@+id/tab3_textview" 122 android:layout_width="fill_parent" 123 android:layout_height="wrap_content" 124 android:layout_marginTop="2dp" 125 android:gravity="center_horizontal" 126 android:text="发现" 127 128 android:textSize="10sp"/> 129 </LinearLayout> 130 131 <LinearLayout 132 android:id="@+id/tab4_layout" 133 android:layout_width="fill_parent" 134 android:layout_height="match_parent" 135 android:layout_weight="1" 136 android:orientation="vertical"> 137 138 <ImageView 139 android:layout_width="24dp" 140 android:layout_height="24dp" 141 android:layout_gravity="center_horizontal" 142 android:layout_marginTop="4dp" 143 android:background="@drawable/tab4"/> 144 145 <TextView 146 android:id="@+id/tab4_textview" 147 android:layout_width="fill_parent" 148 android:layout_height="wrap_content" 149 android:layout_marginTop="2dp" 150 android:gravity="center_horizontal" 151 android:text="我" 152 153 android:textSize="10sp"/> 154 </LinearLayout> 155 </LinearLayout> 156 </RelativeLayout> 157 158 <FrameLayout 159 android:id="@+id/content_frame" 160 android:layout_width="match_parent" 161 android:layout_height="match_parent" 162 android:layout_above="@id/bottom_layout"> 163 </FrameLayout> 164 165 </RelativeLayout> 166 167 </LinearLayout>
最后修改MainActivity文件:
1 package com.example.fragmentdemo; 2 3 import android.app.Activity; 4 import android.app.Fragment; 5 import android.app.FragmentManager; 6 import android.app.FragmentTransaction; 7 import android.os.Bundle; 8 import android.view.View; 9 import android.view.View.OnClickListener; 10 import android.widget.LinearLayout; 11 12 public class MainActivity extends Activity implements OnClickListener { 13 14 private LinearLayout m_weixintab; 15 private LinearLayout m_teltab; 16 private LinearLayout m_findtab; 17 private LinearLayout m_metab; 18 private LinearLayout m_curtab; 19 20 private weixinframent mweixin = null; 21 private telfragment mtel = null; 22 private findfragment mfind = null; 23 private mefragment mMe = null; 24 private Fragment mCurrentfragment = null; 25 26 @Override 27 protected void onCreate(Bundle savedInstanceState) { 28 super.onCreate(savedInstanceState); 29 setContentView(R.layout.activity_main); 30 31 m_weixintab = (LinearLayout) findViewById(R.id.tab1_layout); 32 m_teltab = (LinearLayout) findViewById(R.id.tab2_layout); 33 m_findtab = (LinearLayout) findViewById(R.id.tab3_layout); 34 m_metab = (LinearLayout) findViewById(R.id.tab4_layout); 35 36 m_weixintab.setOnClickListener(this); 37 m_teltab.setOnClickListener(this); 38 m_findtab.setOnClickListener(this); 39 m_metab.setOnClickListener(this); 40 41 m_weixintab.setSelected(true); 42 m_weixintab.setVisibility(View.VISIBLE); 43 44 if (null == savedInstanceState) { 45 mCurrentfragment = getweixinFragment(); 46 FragmentTransaction ft = getFragmentManager().beginTransaction(); 47 ft.add(R.id.content_frame, mCurrentfragment, 48 weixinframent.FRAGMENT_TAG); 49 ft.commit(); 50 } else { 51 mCurrentfragment = getweixinFragment(); 52 } 53 54 m_curtab = m_weixintab; 55 56 } 57 58 private weixinframent getweixinFragment() { 59 weixinframent fragment = (weixinframent) getFragmentManager() 60 .findFragmentByTag(weixinframent.FRAGMENT_TAG); 61 if (null == fragment) { 62 fragment = new weixinframent(); 63 } 64 return fragment; 65 } 66 67 private telfragment gettelFragment() { 68 telfragment fragment = (telfragment) getFragmentManager() 69 .findFragmentByTag(telfragment.FRAGMENT_TAG); 70 if (null == fragment) { 71 fragment = new telfragment(); 72 } 73 return fragment; 74 } 75 76 private findfragment getfindFragment() { 77 findfragment fragment = (findfragment) getFragmentManager() 78 .findFragmentByTag(findfragment.FRAGMENT_TAG); 79 if (null == fragment) { 80 fragment = new findfragment(); 81 } 82 return fragment; 83 } 84 85 private mefragment getmeFragment() { 86 mefragment fragment = (mefragment) getFragmentManager() 87 .findFragmentByTag(mefragment.FRAGMENT_TAG); 88 if (null == fragment) { 89 fragment = new mefragment(); 90 } 91 return fragment; 92 } 93 94 @Override 95 public void onClick(View v) { 96 97 FragmentTransaction ft = getFragmentManager().beginTransaction(); 98 String tag = null; 99 Fragment changefragment = null; 100 switch (v.getId()) { 101 case R.id.tab1_layout: 102 if (mweixin == null) { 103 m_curtab.setSelected(false); 104 m_weixintab.setSelected(true); 105 m_curtab = m_weixintab; 106 changefragment = this.getweixinFragment(); 107 tag = weixinframent.FRAGMENT_TAG; 108 } 109 break; 110 111 case R.id.tab2_layout: 112 if (mtel == null) { 113 m_curtab.setSelected(false); 114 m_teltab.setSelected(true); 115 m_curtab = m_teltab; 116 changefragment = this.gettelFragment(); 117 tag = telfragment.FRAGMENT_TAG; 118 } 119 break; 120 121 case R.id.tab3_layout: 122 if (mfind == null) { 123 m_curtab.setSelected(false); 124 m_findtab.setSelected(true); 125 m_curtab = m_findtab; 126 changefragment = this.getfindFragment(); 127 tag = findfragment.FRAGMENT_TAG; 128 } 129 break; 130 131 case R.id.tab4_layout: 132 if (mMe == null) { 133 m_curtab.setSelected(false); 134 m_metab.setSelected(true); 135 m_curtab = m_metab; 136 changefragment = this.getmeFragment(); 137 tag = mefragment.FRAGMENT_TAG; 138 } 139 break; 140 } 141 142 if (changefragment != null) { 143 Fragment f = getFragmentManager().findFragmentByTag(tag); 144 ft.hide(mCurrentfragment); 145 if (null == f) { 146 ft.add(R.id.content_frame, changefragment, tag); 147 } else { 148 ft.show(changefragment); 149 } 150 ft.commit(); 151 mCurrentfragment = changefragment; 152 } 153 154 } 155 156 }
说明:使用Fragment时,可以通过用户交互来执行一些动作,比如增加、移除、替换等。所有这些改变构成一个集合,这个集合被叫做一个transaction,可以调用FragmentTransaction中的方法来处理这个transaction,并且可以将transaction存进由activity管理的back stack中,这样用户就可以进行fragment变化的回退操作。
可以这样得到FragmentTransaction类的实例:
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
每个transaction是一组同时执行的变化的集合。用add(), remove(), replace()方法,把所有需要的变化加进去,然后调用commit()方法,将这些变化应用。
运行效果:
点击发现,界面变为如下图: