編輯:關於Android編程
Android在3.0中引入了Fragments的概念,主要目的是用在大屏幕設備上(如平板電腦上)支持更加動態和靈活的UI設計。平板電腦的屏幕要比手機大,有更多的空間來放更多的UI組件,並且這些組件之間會產生更多的交互,Fragment在應用中應該是一個模塊化和可重用的組件,因為Fragment定義了它自己的布局,已經通過使用它自己的生命周期回調方法定義了他自己的行為,也可以將Fragment包含到多個Activity中。更多詳細介紹可查看官方文檔
1、Fragment可以作為Activity界面的一部分組成出現。
2、可以在一個Activity中同時出現多個Fragment,並且一個Fragment也可以在多個Activity 中使用。
3、在Activity運行過程中,可以添加,移除和替換Fragment。
4、Fragment可以響應自己的輸入事件,並且有自己的生命周期,他們的生命周期受宿主Activity生命周期的影響和限制。
創建一個Fragment,必須創建一個Fragment子類或繼承已存在的子類,創建好子類後可在onCreateView()方法中加載Fragment中的布局文件,Fragment第一次繪制它的用戶界面的時候,系統會調用此方法,為了繪制Fragment的UI,此方法必須返回一個View,如果不顯示UI,返回null即可。
public class MyFragment extends Fragment{
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
//在這裡加載Fragment的布局文件,將其轉換成View對象最後返回,(下面有詳細的案例)...
return super.onCreateView(inflater, container, savedInstanceState);
}
}
在Activity的layout文件中聲明Fragment,需要特別注意的是在標簽中的需要包含一個android:name屬性來指定這個layout中實例化的Fragment類(把Fragment的全類名寫在這個屬性裡面),同時也要給這個Fragment一個唯一的標識。
標識一個Fragment的方法(兩種):
1、在Activity的layout文件中聲明Fragment
public class MyFragment extends Fragment{
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
//加載Fragment自己的布局文件並轉換成View對象
View view = inflater.inflate(R.layout.myfragment, container, false);
//注意findViewById前的view
TextView text=(TextView) view.findViewById(R.id.text);
Button button=(Button) view.findViewById(R.id.button);
//.........
return view;
}
}
Fragment的布局文件
以上就是在Activity中加載布局文件是會靜態加載Fragment,注:在Activity中也可以通過findViewById查找Fragment中的布局控件。
動態加載需要撰寫代碼將Fragment添加到一個Activity layout中,add()添加一個Fragment(指定要添加的fargment和插入的View),與此類似的還有remove(),replace()。
要完成動態Fragment加載還需要處理Fragment事務,根據用戶的交互情況,對Fragmeeng進行添加,移除,替換以及執行其他動作,提交給Activity的每一套變化被稱作一個事務。獲取Fragment事務代碼如下:
FragmentManager fragmentManager = getFragmentManager(); FragmentTransaction beginTransaction = fragmentManager.beginTransaction();
每一個事物都是同時執一套變化,可以在一個事物中設置你所有想執行的變化,包括add(),remove(),replace(),然後提交給Activity,必須調用commit()方法(和mysql" target="_blank" title="MySQL知識庫">數據庫事務提交類似)
如果允許用戶通過按下BACK按鍵返回到前一個Fragment狀態,調用commit()之前可以加入addToBackStack()方法。
1、創建一個Fragment
public class MyFragment2 extends Fragment{
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
//加載Fragment自己的布局文件並轉換成View對象
View view = inflater.inflate(R.layout.myfragment, container, false);
TextView text=(TextView) view.findViewById(R.id.text);
text.setText("動態加載Fragment");
//................
return view;
}
}
這時就不需要在Activity的布局文件中聲明Fragment標簽,而是Activity中使用代碼將他添加到布局文件中來
MyFragment2 fragment2=new MyFragment2(); FragmentManager fragmentManager = getFragmentManager();//獲得fragment管理者 FragmentTransaction beginTransaction = fragmentManager.beginTransaction();//開啟事務 beginTransaction.add(R.id.frame, fragment2);//第一個參數為要把fragment加載到那個布局中 beginTransaction.addToBackStack(null);//按back鍵可回退上一個fragment狀態 beginTransaction.commit();//提交事務
在學習Fragment聲明周期前我們應該要了解Activity的生命周期,Fragment作為Activity的一部分所以他的生命周期一定會受到宿主Activity生命周期的影響。
Fragment聲明周期圖

Fragment與Activity生命周期對比圖

通過上面的Fragment與Activity生命周期對比圖可以看出每個Activity生命周期所對應的狀態下都會至少對應一個Fragment生命周期的回調方法。接下來就對Fragment的所有生命周期方法進行了解。(直接在代碼中解釋)<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwcmUgY2xhc3M9"brush:java;"> public class MyFragment3 extends Fragment { private TextView tv; // 啟動Fragment——>屏幕鎖屏——>屏幕解鎖——> // 切換到其他的Fragment——>回到桌面——>回到應用——>退出Fragment /** * 每次創建都會繪制Fragment的View組件時回調該方法(在onCreate和onActivityCreated之間調用) */ @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // TODO Auto-generated method stub View view = inflater.inflate(R.layout.fragment2, container, false); TextView tv = (TextView) view.findViewById(R.id.text); tv.setText("第一個Fragment"); Log.i("Main", "Fragment1---onCreateView()"); return view; } /** * 當Fragment被添加到Activity時候會回調這個方法,並且只調用一次 */ @Override public void onAttach(Activity activity) { // TODO Auto-generated method stub super.onAttach(activity); Log.i("Main", "Fragment1---onAttach()"); } /** * 創建Fragment時會回調,只會調用一次 */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.i("Main", "Fragment1---onCreate()"); } /** * 當Fragment所在的Activty啟動完成後調用 */ @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); Log.i("Main", "Fragment1---onActivityCreated()"); } /** * 啟動Fragment * */ @Override public void onStart() { super.onStart(); Log.i("Main", "Fragment1---onStart()"); } /** * 恢復Fragment時會被回調,調用onStart()方法後面一定會調用onResume()方法 */ @Override public void onResume() { super.onResume(); Log.i("Main", "Fragment1---onResume()"); } /** * 暫停Fragment */ @Override public void onPause() { super.onPause(); Log.i("Main", "Fragment1---onPause()"); } /** * 停止Fragment */ @Override public void onStop() { super.onStop(); Log.i("Main", "Fragment1---onStop()"); } /** * 銷毀Fragment所包含的View組件時,和onCreateView所創建的View組件對應 */ @Override public void onDestroyView() { super.onDestroyView(); Log.i("Main", "Fragment1---onDestroyView()"); } /** * 銷毀Fragment時會被回調 */ @Override public void onDestroy() { super.onDestroy(); Log.i("Main", "Fragment1---onDestroy()"); } /** * Fragment從Activity中刪除時會回調該方法,並且這個方法只會調用一次 */ @Override public void onDetach() { super.onDetach(); Log.i("Main", "Fragment1---onDetach()"); } }
上面對Fragment的生命周期已經做了詳細的介紹,下面可以通過一個案例來演示來詳細了解以下操作對Fragment的生命周期的影響。(直接貼測試結果)
啟動fragment
onAttach()->onCreate()->onCreateView()->onActivityCreated()->onStart()->onResume()屏幕鎖屏或按HOME鍵回到手機主界面
onPause()->onStop()屏幕解鎖或長按HOME重新回到應用(Fragment)
onStart()->onResume()退出Fragment
onPause()->onStop()->onDestroyView()->onDestroy()->onDetach()
第一個Fragment切換到第二個Fragment(相對於第一個Fragment替換第二個Fragment)
第一個fragment調用的方法:
onPause()->onStop()->onDestoryView()->onDestory()->onDetach();第二個fragment調用的方法:
onAttach()->onCreate()->onCreateView()->onActivityCreated()->onStart()->onResume()
Fragment的生命周期方法
1、onAttach(); // 當fragment被添加到activity中時會回調這個方法;只會調用一次
2、onCreate(); // 在fragment創建的時候回調這個方法;只會調用一次;
3、onCreateView(): // 每次創建都會繪制Fragment的View組件時調用該方法,相當於fragment綁定一個布局,布局文件轉換成view返回回來;
4、onActivityCreated(); // fragment所在的activity啟動完成後調用;
5、onStart(): // 啟動Fragment時會被回調,
6、onResume(); // 調用onStart()方法後面一定會調用這個方法,恢復fragment時回調
7、onPause(): // 暫停Fragment
8、onStop(); // 停止Fragment
9、onDestroyView(): // 銷毀Fragment所包含的View組件,與onCreateView相對應
11、onDetach(): // Fragment從Activity中刪除時回調這個方法,並且只調用一次
10、onDestroy(): // 銷毀Fragment時會被回調
知識點:
如果想在彼此之間建立通信,首先就要咋彼此的地盤中找到對方
1、在fragment可調用getActivity()方法獲取他所在的宿主Activity
2、Acitvity可調用FragmentManager的findFragmentById()或findFragmentByTag()方法獲取Fragment
在Fragment與Activity通信都會傳遞一些數據
1、Activity傳遞數據到Fragment:在Activity中創建Bundle數據包,並調用Fragment的setArguments(Bundle bundle)方法,然後在Fragment類裡面通過getArguments方法獲取Bundle數據包。
2、Fragment傳遞數據到Activity:需要在Fragment中定義一個內部回調接口,再讓包含該Fragment的Activity實現該回調接口。這樣Fragment可調用該回調方法將數據傳遞給Activity。
示例代碼:
Activity向動態加載的Fragment傳值(而且是在Fragment添加到Layout布局之前發送數據):
MyFragment5 fragment5 = new MyFragment5();
Bundle bundle = new Bundle();
bundle.putString("name", text);
fragment5.setArguments(bundle);
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction beginTransaction = fragmentManager.beginTransaction();
beginTransaction.add(R.id.layout, fragment5, "fragment5");//在動態加載時設置FragmentTag(fragment5)
beginTransaction.commit();
動態加載的Fragment取值:
String text=getArguments().get("name")+"" ;
//向靜態加載fragment傳值
FragmentManager fragmentManager = getFragmentManager();
Fragment findFragmentById = fragmentManager.findFragmentById(R.id.frag);//查找已加載進來的fragment
MyFragment frag=(MyFragment) findFragmentById;//類型轉換
frag.setAaa("fragment靜態傳值");//調用MyFragment中接收數據變量的set方法將數據進去,在Fragment中直接調用get方法獲取數據
靜態加載的Fragment取值:
public class MyFragment extends Fragment{
private String aaa;
public String getAaa() {
return aaa;
}
public void setAaa(String aaa) {
this.aaa = aaa;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.myfragment, container, false);
String value = getAaa();//獲取傳遞過來的值
return view;
}
}
Fragment向Activity傳遞數據
public class MyFragment5 extends Fragment{
private String code="Thank you,Activity!";
public MyListener listener;//3.為接口聲明一個對象
//1.內部回調接口(為了向Activity傳遞數據),讓Activity實現該接口極其方法
public interface MyListener
{
public void thank(String code);
}
/**
* 2.實現Fragment生命周期的onAttach方法
* 當Fragment被添加到Activity時候會回調這個方法,並且只調用一次
*/
@Override
public void onAttach(Activity activity) {
listener=(MyListener) activity;//引用宿主Activity對象
super.onAttach(activity);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment2, container, false);
//直接通過listener(Activity)對象的的thank方法向Activity傳值
listener.thank(code);
return view;
}
}
Activity接收數據
public class MainActivity extends Activity implements MyListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
@Override
public void thank(String code) {
// 在接口實現的方法中得到Fragment中傳過來的數據
Toast.makeText(MainActivity.this, code,Toast.LENGTH_SHORT).show();
}
}
上述已經介紹完成了Fragment常用的一些方法,相信看完,大家一定清楚了Fragment的產生理由,以及如何使用Fragment,最後需要說一下Fragment的例子,Android官方已經提供了Fragment的各種使用的Demo例子,在我們SDK下面的API Demo裡面就包含了Fragment的各種使用例子,需要看Demo的朋友,直接看API Demo那個程序就可以了,不用到處去找。裡面分開不同功能,實現了不同的類。可以根據需要查看具體代碼。
Android 微信6.1 tab欄圖標和字體顏色漸變的實現
相信大家都見到了微信圖標顏色漸變的過程,是不是感覺很牛逼?不得不說微信團隊確實是很厲害的團隊,不管是從設計還是開發人員。今天我帶大家來看看,微信 tab 欄圖標和字體顏色
Android小知識庫
The APK file does not exist on disk.Error while Installing APK解決方案:Android Studio獲取SH
Android四大組件之 Activity(上)
(一)概述本節開始講解Android的四大組件之一的Activity(活動);官方文檔:Activity是一個應用程序的組件,他在屏幕上提供了一個區域,允許用戶在上面做一
Android自定義控件深入學習 Android生成隨機驗證碼
在上一篇的文章中介紹了自定義控件的屬性,詳情見《詳解Android自定義控件屬性TypedArray以及attrs》。那麼在這基礎上實現隨機驗證碼生成,裡面的代碼是自定義