編輯:關於Android編程
碎片(Fragment)是一種可以嵌入在活動當中的UI片段,它能讓程序更加合理和充分地利用屏幕的空間。首先建立一個平板的模擬器1034*600,環境使用android4.2.2.在建立一個android的項目,項目名為FragmentTest。
碎片的簡單使用
新建一個左側碎片布局left_fragment.xml代碼如下
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,代碼如下所示:
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; } }
<framelayout android:id="@+id/right_layout" android:layout_height="match_parent" android:layout_weight="1" android:layout_width="0dp"> </framelayout>
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提供了一個類似與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文件,代碼如下:
可以看到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布局,代碼如下:
注意:最小寬度限定符是在android3.2版本引入的,由於我使用的好似最低兼容系統版本4.0,所以可以放心地使用它。
轉載請注明:http://blog.csdn.net/j903829182/article/details/40707273
有不少朋友為自己的手機鎖屏後設置了開鎖密碼,但如果忘記了手機解鎖圖案設置,不管是因為太過復雜,還是別的什麼原因,用上手機才是最重要的,下載吧小編就來分享一個
前面幾篇我們講解了 QtAndroid 名字空間的基本用法,這次我們使用前面講過的方法和類庫,展示一些簡單的小示例。我在《Qt on Android核心編程》一書中主要通
OpenGL ES是 OpenGL三維圖形API 的子集,針對手機、PDA和游戲主機等嵌入式設備而設計。 Ophone目前支持OpenGL ES 1.0 ,OpenGL
在微信小程序開發時,經常要用到一個控件會根據不同的情況和環境動態顯示與隱藏這種情況,下面就來實踐一把!上效果先它的實現方法有兩種,第一種方法:單選法,就是隱藏與顯示根據條