Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android學習八(android碎片fragment的使用)

android學習八(android碎片fragment的使用)

編輯:關於Android編程

碎片(Fragment)是一種可以嵌入在活動當中的UI片段,它能讓程序更加合理和充分地利用屏幕的空間。首先建立一個平板的模擬器1034*600,環境使用android4.2.2.在建立一個android的項目,項目名為FragmentTest。

碎片的簡單使用

新建一個左側碎片布局left_fragment.xml代碼如下

 



這個布局值放置了一個按鈕,並讓它水平居中顯示。然後在新建一個右側布局right_fragment.xml代碼如下所示:

 

 



上面這個布局的背景色設置成綠色,並放置了一個TextView用於顯示一段文本。接著新建一個LeftFragment類繼承自Fragment。注意,這裡可能會有2個不同的包下的Fragment供我們選擇,建議使用android.app.Fragment,因為我們的程序是面向Android4.0以上系統的,另一個包下的Fragment主要是用於兼容低版本的Android系統。LeftFragment的代碼如下所示:

 

 

package com.wj.fragmenttest;

import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class LeftFragment extends Fragment {

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		View view=inflater.inflate(R.layout.left_fragment,container, false);
		return view;
	}

}


 

在新建一個RightFragment代碼如下所示:

 

package com.wj.fragmenttest;

import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class RightFragment extends Fragment {

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		View view=inflater.inflate(R.layout.right_fragment,container, false);
		return view;
	}

}

以上的代碼比較的簡單就不在多說了額。

 

接下來修改activity_main.xml,代碼如下:

 


  
    
    
    
    
    
    



 

上面的代碼我們使用了fragment標簽在布局中添加碎片。

運行程序,結果如下所示:

\

 

 

 

上面添加碎片是靜態添加的,那麼接下來就讓我們來試試動態添加碎片吧。

新建一個布局文件,文件名為another_right_fragment.xml,代碼如下所示:

 



    



然後新建AnotherRightFragment作為另一個右側碎片,代碼如下:

 

 

package com.wj.fragmenttest;

import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class AnotherRightFragment extends Fragment {

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		View view=inflater.inflate(R.layout.another_right_fragment,container, false);
		return view;
	}

}

接下來修改activity_main.xml文件,代碼如下:

 

 


  
    
    <framelayout android:id="@+id/right_layout" android:layout_height="match_parent" android:layout_weight="1" android:layout_width="0dp">
    
    </framelayout>
    
    


這裡使用了FrameLayout布局方式,在之後的代碼中我們將替換FrameLayout裡的內容,從而實現動態添加碎片的功能。修改MainActivity中的代碼:

 

 

package com.wj.fragmenttest;

import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends Activity implements OnClickListener{

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		Button button=(Button) findViewById(R.id.button1);
		button.setOnClickListener(this);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	@Override
	public void onClick(View v) {
		// TODO Auto-generated method stub
		switch(v.getId()){
		case R.id.button1:
			//創建碎片
			AnotherRightFragment fragment=new AnotherRightFragment();
			//獲得布局管理器
			FragmentManager fragmentManager=getFragmentManager();
			//獲得碎片的事物
			FragmentTransaction transaction=fragmentManager.beginTransaction();
			//替換id為R.id.right_layout裡面的內容
			transaction.replace(R.id.right_layout, fragment);
			transaction.commit();//提交事務
			break;
		default:
			break;
		}
	}

}

運行程序:

 

\

 

 

點擊左邊的按鈕,結果如下:

\

 

結合代碼可以看出,動態添加碎片主要分為5步。

1.創建待添加的碎片實例。

2.獲取到FragmentManager,在活動中可以直接調用getFragmentManager()方法得到。

3.開啟一個事物,通過調用beginTransaction()方法開啟。

4.向容器內加入碎片,一般使用replace()方法實現,需要傳入容器的id和待添加的碎片實例。

5.提交事務,調用commit()方法來完成。

 

在碎片中模擬返回棧

通過點擊按鈕添加了一個碎片之後,這時按下back鍵程序就會直接退出。如果這裡我們想模仿類似返回棧的效果,按下back鍵可以返回到上一個碎片,該如何實現了,看如下操作:

其實比較的簡單,在FragmentTransaction中提供了一個addToBackStack()方法,可以用於將一個事務添加到返回棧中,修改MainActivity中的代碼如下:

 

package com.wj.fragmenttest;

import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends Activity implements OnClickListener{

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		Button button=(Button) findViewById(R.id.button1);
		button.setOnClickListener(this);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	@Override
	public void onClick(View v) {
		// TODO Auto-generated method stub
		switch(v.getId()){
		case R.id.button1:
			//創建碎片
			AnotherRightFragment fragment=new AnotherRightFragment();
			//獲得布局管理器
			FragmentManager fragmentManager=getFragmentManager();
			//獲得碎片的事物
			FragmentTransaction transaction=fragmentManager.beginTransaction();
			//替換id為R.id.right_layout裡面的內容
			transaction.replace(R.id.right_layout, fragment);
			transaction.addToBackStack(null);
			transaction.commit();//提交事務
			break;
		default:
			break;
		}
	}

}

這裡在事務提交之前調用了FragmentManager的addToBackStack()方法,它可以接收一個名字用於描述返回棧的狀態,一般傳入null即可。現在重寫運行程序,並點擊按鈕將AnotherRightFragment添加到活動中,然後按下Back鍵,你會發現回到了RightFragment界面,再次按下Back鍵程序才會退出。

 

 

 

碎片和活動直接進行通信

為了方便碎片和活動直接進行通信,FragmentManager提供了一個類似與findViewById()的方法,專門用於從布局文件中獲取碎片的實例,代碼如下:

RightFragment rightFragment=(RightFragment) getFragmentManager().findFragmentById(R.id.right_fragment);

調用FragmentManager的findFragmentById方法,可以在活動中得到相應碎片的實例,然後就能輕松地調用碎片裡的方法了。

掌握了如何在活動中調用碎片裡的方法,那麼在碎片中又該如何調用活動中的方法呢?

在每個碎片中都可以通過調用getActivity()方法來得到和當前碎片相關聯的活動實例,代碼如下:

MainActivity mainActivity=(MainActivity) getActivity();

有了活動的實例之後,在碎片中調用活動裡的方法就變得輕而易舉了。另外當碎片中需要使用Context對象時,也可以使用getActivity()方法,因為活動本身就是一個Context對象了。

 

 

碎片的生命周期

和活動一樣,碎片也有自己的生命周期

運行狀態:當一個碎片是可見的,並且它所關聯的活動正處於運行狀態,該碎片也處於運行狀態。

暫停狀態:當一個活動進入暫停狀態時(由於另一個未占滿屏幕的活動被添加到了棧頂),與它相關聯的可見碎片就會進入到暫停狀態。

停止狀態:當一個活動進入停止狀態時,與它相關聯的碎片就會進入到停止狀態。或者通過用FragmentTransaction的remove,replace方法將碎片從活動中移除,但有在事務提交之前調用addToBackStack()方法,這時的碎片也會進入到停止狀態。總的來說停止狀態的碎片對用戶來說是完全不可見的,有可能會被回收。

銷毀狀態:碎片總是依附與活動而存在,因此當活動被撤銷時,與它關聯的碎片就會進入到銷毀狀態。或者通過調用FragmentTransaction的remove,replace方法將碎片從活動中移除,但在事務提交之前並沒有調用addToBackStack()方法,這時的碎片也會進入到銷毀狀態。

幾個重要的碎片回到方法:

1.onAttach():當碎片和活動建立關聯的時候調用

2.onCreateView():為碎片創建視圖(加載布局)時調用

3.onActivityCreated():確保與碎片相關聯的活動一定已經創建完畢的時候調用

4.onDestroyView():當與碎片關聯的視圖被移除的時候調用。

5.onDetach():當碎片和活動解除關聯的時候調用

下圖是碎片的生命周期圖:

\

 

 

修改RightFragment中的代碼,代碼如下:

 

package com.wj.fragmenttest;

import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class RightFragment extends Fragment {

	public static final String TAG=RightFragment;
	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		Log.d(TAG, onCreateView);
		View view=inflater.inflate(R.layout.right_fragment,container, false);
		return view;
	}
	@Override
	public void onActivityCreated(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onActivityCreated(savedInstanceState);
		Log.d(TAG, onActivityCreated);
	}
	@Override
	public void onAttach(Activity activity) {
		// TODO Auto-generated method stub
		super.onAttach(activity);
		Log.d(TAG, onAttach);
	}
	@Override
	public void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		Log.d(TAG, onCreate);
	}
	@Override
	public void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
		Log.d(TAG, onDestroy);
	}
	@Override
	public void onDestroyView() {
		// TODO Auto-generated method stub
		super.onDestroyView();
		Log.d(TAG, onDestroyView);
	}
	@Override
	public void onDetach() {
		// TODO Auto-generated method stub
		super.onDetach();
		Log.d(TAG, onDetach());
	}
	@Override
	public void onPause() {
		// TODO Auto-generated method stub
		super.onPause();
		Log.d(TAG, onPause);
	}
	@Override
	public void onResume() {
		// TODO Auto-generated method stub
		super.onResume();
		Log.d(TAG, onResume);
	}
	@Override
	public void onStart() {
		// TODO Auto-generated method stub
		super.onStart();
		Log.d(TAG, onStart);
	}
	@Override
	public void onStop() {
		// TODO Auto-generated method stub
		super.onStop();
		Log.d(TAG, onStop);
	}
	
	
	
	

}


 

在回調方法中打印了日志,運行程序,當RightFragment第一次被加載到屏幕的時候,方法調用如下所示:

當第一被加載的時候,會依次調用onAttach,onCreate,onCreateView,onActivityCreated,onStart,onResume方法。

\

 

然後點擊左邊的按鈕,輸出如下所示的日志:

\

 

 

 

由於AnotherRightFragment替換了RightFragment,此時的RightFragment進入了停止狀態,因此onPause,onStop,onDestroyView方法會得到執行。當然如果在替換的時候沒有調用addToBackStack方法,此時的RightFragment就會進入到銷毀狀態,onDestroy,onDetach方法就會得到執行。

按下Back鍵,RightFragment會重寫回到屏幕,打印如下信息:

\

 

 

由於RightFragment重新回到了運行狀態,因此onActivityCreated,onStart,onResume方法會得到執行。注意,此時onCreate和onCreateView方法並不會執行,因為我們借助了addToBackStack方法使得RightFragment和它的視圖並沒有銷毀,在按back鍵退出程序,打印信息如下:

\

 

依次執行了onPause,onStop,onDestroyView,onDestroy,onDetach方法。

另外,在碎片中也可以通過onSaveInstanceState方法保存數據的。因為進入停止狀態的碎片有可能在系統內存不足的時候被回收。保存下來的數據在onCreat,onCreateView和onActivityCreate這三個方法中重寫得到,他們都包含了一個Bundle類型的參數。

 

 

 

動態加載布局的技巧

動態加載布局的功能很強大,可以解決很多實踐中的問題,但是它畢竟只是在一個布局文件中進行一些添加和替換操作。如果程序能夠根據設備的分辨率或屏幕的大小在運行時決定加載哪個布局,那麼我們就可以發揮更多的空間了。

1.使用限定符

修改FragmentTest項目中的activity_main.xml文件,代碼如下:

 


  
   
   
    


這裡將多余的代碼都刪掉,值留下一個左側碎片,並讓它充滿整個父布局。接著在res目錄下新建layout-large文件夾,在這個文件夾下面新建一個布局,也叫activity_main.xml代碼如下所示:

 

 


  
    
    
    
   
    
    



 

可以看到layout/activity_main.xml布局只包含了一個碎片,即單頁模式,而layout-large/activity_main.xml布局包含了2個碎片,即雙頁模式。其中large就是一個限定符,那些屏幕被認定為是large的設備就會自動加載layout-large文件夾下的布局,而小屏幕的設備則還會加載layout文件夾下的布局。

將MainActivity中的按鈕點擊事件屏蔽掉,代碼如下:

 

package com.wj.fragmenttest;

import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends Activity implements OnClickListener{

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		Button button=(Button) findViewById(R.id.button1);
		button.setOnClickListener(this);
		
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	@Override
	public void onClick(View v) {
		// TODO Auto-generated method stub
		/*switch(v.getId()){
		case R.id.button1:
			//創建碎片
			AnotherRightFragment fragment=new AnotherRightFragment();
			//獲得布局管理器
			FragmentManager fragmentManager=getFragmentManager();
			//獲得碎片的事物
			FragmentTransaction transaction=fragmentManager.beginTransaction();
			//替換id為R.id.right_layout裡面的內容
			transaction.replace(R.id.right_layout, fragment);
			transaction.addToBackStack(null);
			transaction.commit();//提交事務
			break;
		default:
			break;
		}*/
	}

}

在平板模擬器上運行程序效果如下:

 

\

 

在啟動一個手機模擬器,並在這個模擬器上運行程序,效果如下:

\

 

 

這樣就實現了動態加載布局的功能。

android中常見的限定符

大小:

small提供給小屏幕設備的資源

normal提供給中等屏幕設備的資源

large提供給大屏幕設備的資源

xlarge提供給超大屏幕設備的資源

分辨率:

ldpi提供給低分辨率設備的資料(120dpi以下)

mdpi提供給中等分辨率設備的資源(120dpi到160dpi)

hdpi提供給高分辨率設備的資源(160dpi到240dpi)

xhdpi提供給高分辨率設備的資源(240dpi到320dpi)

方向:

land提供給橫屏設備的資源

port提供給豎屏設備的資源

 

 

2.使用最小寬度限定符

最小寬度限定符允許我們對屏幕的寬度指定一個最小值(以dp為單位),然後以這個最小值為臨界點,屏幕寬度大於這個值的設備就加載這個布局,屏幕寬度小於這個值的設備就加載另一個布局。

在res目錄下面新建layout-sw600dp文件夾,然後在這個文件夾下新建activity_main.xml布局,代碼如下:

 


  
    
    
    
   
    
    


當程序運行在屏幕寬度大於600dp的設備上時,就會加載layout-sw600dp/activity_main.xml布局,當程序運行在屏幕寬度小於600dp的設備時,則仍然加載默認的layout/activity_main.xml布局。

 

注意:最小寬度限定符是在android3.2版本引入的,由於我使用的好似最低兼容系統版本4.0,所以可以放心地使用它。

 

 

轉載請注明:http://blog.csdn.net/j903829182/article/details/40707273

 

 

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved