Fragment:
碎片,是一種可以嵌在活動中的UI片段.
1.靜態:在佈局文件定義一個
<fragment
android:id="@+id/fragment1"
android:name="com.example.gp08_day23_fragment2.fragment.TestFragment"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
//獲取碎片管理器----可以直接在 activity獲取到
manager = getFragmentManager();
//使用碎片管理器得到需要的碎片對象
Fragment fragment = manager.findFragmentById(R.id.fragment1);
//得到碎片對象中的佈局對象
View view = fragment.getView();
2.動態:
—-FragmentManager
—-事務的使用
—-activity給fragment傳值(Bundle對象)
2.1動態添加fragment步驟:
1)在佈局文件中給fragment佔個位,一般用FrameLayout
2)創建fragment實例
3)獲取到FragmentManager,在活動中可以直接調用getFragmentManager()
4)開啓一個事務,通過調用beginTransaction方法開啓
5)向容器內加入fragment,一般使用replace()方法實現,需要傳入容器的id(就是在佈局文件中佔的位置)和fragment實例
6)提交事務,調用commit()方法完成。
2.2先介紹一下傳值
傳值:
//使用碎片管理器對象得到事務對象
FragmentTransaction transaction = manager.beginTransaction();//開啓事務
// Fragment f = manager.findFragmentByTag("flag");
// if(f==null)
// {
// TestFragment fragment = new TestFragment();
// transaction.add(R.id.container, fragment, "flag");
// }
TestFragment fragment = new TestFragment();
//activity給fragment傳參數
Bundle bundle = new Bundle();
bundle.putString("msg", "hehe"+new Date());
fragment.setArguments(bundle);
//replace是替換掉之前的fragment對象(remove--->add)
transaction.replace(R.id.container, fragment);
//提交事務
transaction.commit();//事務只能提交一次
接收:
public class TestFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
TextView textView = new TextView(getActivity());
textView.setTextSize(20);
//獲取傳遞過來的參數
Bundle bundle = getArguments();
String value = bundle.getString("msg");
textView.setText(value);
return textView;
}
}
關鍵是這個:
//activity給fragment傳參數
Bundle bundle = new Bundle();
bundle.putString(“msg”, “hehe”+new Date());
fragment.setArguments(bundle);
3.生命週期
Fragment的生命週期:11個方法
* 1):初始化:對應於 activity的onCreate()
* onAttach(Activity) 和所屬的activity關聯
* onCreate(Bundle )fragment的初始化
* onCreateView()初始化fragment顯示的UI視圖
* onActivityCreated()當activity的 onCreate()方法執行完(說明 activity的初始化已經完成)
* 2):顯示,隱藏
* onStart(),onResume(),onPause(),onStop()
* 3):銷燬
* onDestroyView() 銷燬fragment顯示的UI視圖(View 對象)
* onDestroy() 銷燬的是fragment
* onDettach() 和所屬的activity斷開
實例:源碼地址見後面
和Activity聯動:
創建時:從外到內創建
關閉時:從內到外銷燬
4.自定義模擬回退棧
// 作爲回退棧
private LinkedList<Fragment> stack = new LinkedList<Fragment>();
public void addFragment(View v) {
TestFragment fragment = new TestFragment();
Bundle bundle = new Bundle();
bundle.putString("msg", "hahahaha" + new Date());
fragment.setArguments(bundle);
// 如果棧爲空直接入棧,不爲空則把當前的activity隱藏,然後加入新的fragment
if (stack.size() == 0)
getFragmentManager().beginTransaction()
.add(R.id.container, fragment).commit();
else getFragmentManager().beginTransaction().hide(stack.peek())// 隱藏棧頂的
.add(R.id.container, fragment).commit();
// 入棧
stack.push(fragment);
}
// 點擊回退按鈕顯示上一個fragment
public void backFragment(View v) {
if (!stack.isEmpty()) {
getFragmentManager().beginTransaction().remove(stack.poll())
.commit();
}
if (!stack.isEmpty()) getFragmentManager().beginTransaction().show(stack.peek()).commit();
}
效果圖:
5.使用baskToStack(null);方法
public void addFragment(View v) {
TestFragment fragment = new TestFragment();
Bundle bundle = new Bundle();
bundle.putString("msg", "xixi" + new Date());
fragment.setArguments(bundle);
FragmentTransaction tran = getFragmentManager().beginTransaction();
tran.add(R.id.container, fragment);//remove1 add 2
tran.addToBackStack(null);//把事務加入當前的回退棧 回滾
tran.commit();
}
// 點擊回退按鈕顯示上一個fragment
public void backFragment(View v) {
onBackPressed();
}
效果和自定義回退棧相同。
–>使用回退棧的作用主要是返回時返回到上一個fragment
6.橫屏豎屏動態變化佈局
1)創建一個在橫屏時加載的佈局文件夾
豎屏佈局:只有一個fragment
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<fragment
android:id="@+id/fragment"
android:layout_width="200dp"
android:layout_height="match_parent" android:name="com.beiing.fragmentlandscapefragment.FilesFragment"
/>
</RelativeLayout>
橫屏佈局:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<fragment
android:id="@+id/fragment"
android:layout_width="200dp"
android:layout_height="match_parent" android:name="com.beiing.fragmentlandscapefragment.FilesFragment"
/>
<FrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_toRightOf="@id/fragment"
/>
</RelativeLayout>
2)判斷橫屏豎屏:根據橫屏豎屏得到不同的操作
// 判斷屏幕方向
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
ContentFragment fragment = new ContentFragment();
fragment.setArguments(bundle);
getFragmentManager().beginTransaction()
.replace(R.id.container, fragment)
.addToBackStack(null)
.commit();
}
else
{
Intent intent = new Intent(getActivity(),ContentActivity.class);
intent.putExtras(bundle);
startActivity(intent);
}
效果圖:
我的總結:
1)實際開發中,fragment使用非常多,用法大都是在一個顯示界面中底部放上一些按鈕,中間一個fragment,這樣就不用一個activity一個activity的跳了
2)引包的時候注意,一個是android.app.Fragment,還有一個向下兼容的
android.support.v4.app.Fragment;用後一個包的fragment時activity也要用這個包的FragmentActivity
3)在實現1)說的那種類似標籤頁時,需要注意不要每次都通過事務FragmentTransaction的replace()方法去變換界面,這樣會導致該fragment重新創建,如果這個fragment裏面有從網絡獲取數據的操作,這樣,變換一次加載一次,誰受得了,解決方法是,在MainActivity中定義相應fragment的成員,然後一次加入FragmentManager中,然後想要顯示哪個fragment只用調用FragmentTransaction 的show方法和hide方法。後面具體項目會遇到。