Android Fragment 例子
创建一个Fragment的例子,实现的功能大致如下:点击按钮1,显示Fragment1的内容,点击按钮2,显示Fragment2的内容
步骤:
1、新建一个Android项目,生成了一个MainActivity.java文件
2、为这个MainActivity配置布局文件activity_main.xml
3、分别创建Fragment1和Fragment2文件
4、再为Fragments配置布局文件,完成与配置文件相关的代码
5、再回过头来编写MainActivity中的逻辑代码
具体步骤如下:
1、新建一个Android项目,生成了一个MainActivity.java文件
2、为这个MainActivity配置布局文件activity_main.xml
在本例中,我们定义两个不同的按钮,当按钮被点击的时候,fragment的内容就显示在下方。
所以布局就很简单了,我们使用线性LinearLayout的布局,两个button一个fragment
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <Button android:id="@+id/btn1" android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="selectFrag" android:text="Fragment1" /> <Button android:id="@+id/btn2" android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="selectFrag" android:text="Fragment2" /> <fragment <span style="color:#FF6666;"> android:name="com.example.fragmentexample.FragmentOne" android:id="@+id/fragment_place"</span> android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>注意:当在布局添加Fragment时,必须定义android:name和android:id,android:name定义了一个我们想要实例化的Fragment类,id代表唯一的fragment。在该类中我们定义FragmentOne为默认显示的Fragment
3、分别创建Fragment1和Fragment2文件
public class FragmentOne extends Fragment { @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { // TODO Auto-generated method stub //将该fragment填入布局 return inflater.inflate(R.layout.fragment_one, container, false); } }
创建Fragment差异之一,就是你必须使用oncreateView()回调方法来定义布局。这也是运行一个fragment所需要唯一回调的方法。
inflate()方法的三个参数:
想要加载的layout的resourceID
加载的layout的父ViewGroup
布尔值指示在加载期间,展开的layout是否应当附着到ViewGroup中
4、再为Fragments配置布局文件,完成Fragment与配置文件相关的代码,两个fragment的配置文件基本相同,只是更改了背景颜色来区别
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:background="#00ffff"> <TextView android:id="@+id/textView1" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" android:text="This is fragment1" android:textStyle="bold" /> </LinearLayout>
5、再回过头来编写MainActivity中的逻辑代码
import android.support.v7.app.ActionBarActivity; import android.app.Fragment; import android.app.FragmentManager; import android.app.FragmentTransaction; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.View; public class MainActivity extends ActionBarActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @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 boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } public void selectFrag(View view) { Fragment fr; if(view==findViewById(R.id.btn2)) { fr=new FragmentTwo(); }else { fr=new FragmentOne(); } FragmentManager fm=getFragmentManager(); FragmentTransaction fragmentTransaction=fm.beginTransaction(); fragmentTransaction.replace(R.id.fragment_place, fr); fragmentTransaction.commit(); } }在Activity中管理Fragment就必须要使用FragmentManager,通过调用getFragmentManager()得到它的实例。
Activity中使用fragment有一个很强的特性是:根据用户的交互情况,对fragment进行添加,移除,替换以及执行其他动作。提交给activity的每一套变化被称为一个使用。通常用FragmentTransaction中的API来处理。FragmentManager对象的beginTransaction()方法即可开启返回FragmentTransaction对象。
运行结果如下所示:
Fragment分析
Fragment的生命周期
如Activity类似,Fragment也存在以下状态。
活动状态,当前Fragment位于前台,用户可见,可以获得焦点
暂停状态,其他Activity位于前台,该Fragment依然可见,只是不能获得焦点
停止状态,该Fragment不可见,失去焦点
销毁状态,该Fragment被完全删除,或该Fragment所在的Activity被结束
如下图所示,该图片摘自网络
、
OnAttach()当Fragment被添加到Activity时被回调,该方法只会被调用一次
OnCreate()创建Fragment时被回调,该方法只会被回调一次
onCreateView()每次创建、绘制Fragment的view组件时回调该方法,Fragment将会显示该方法返回的View组件
onActivityCreated()当Fragment所在的Activity被启动完成后回调该方法
onStart()启动Fragment时被回调
onResume()恢复Fragment时被回调,onStart()方法后一定回调onResume
onPause()暂停时被回调
onStop()停止时被回调
onDestory()销毁时被回调,该方法只调用一次
onDetch()当Fragment从Activity中被删除、替换完成时回调改方法,OnDestory()方法后一定回调onDetch()方法。该方法只会被调用一次。
例如第一个例子做下实验,验证Fragment执行的流程
MainActivity中添加测试语句
package com.example.fragmentexample; import android.support.v7.app.ActionBarActivity; import android.app.Fragment; import android.app.FragmentManager; import android.app.FragmentTransaction; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; public class MainActivity extends ActionBarActivity { final String TAG = "test"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Log.d(TAG, "------Activity onCreate-------"); } @Override protected void onStart() { // TODO Auto-generated method stub super.onStart(); Log.d(TAG, "------Activity onStart-------"); } @Override protected void onResume() { // TODO Auto-generated method stub super.onResume(); Log.d(TAG, "------Activity onResume-------"); } @Override protected void onPause() { // TODO Auto-generated method stub super.onPause(); Log.d(TAG, "------Activity onPause-------"); } @Override protected void onStop() { // TODO Auto-generated method stub super.onStop(); Log.d(TAG, "------Activity onStop-------"); } @Override protected void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); Log.d(TAG, "------Activity onDestroy-------"); } @Override protected void onRestart() { // TODO Auto-generated method stub super.onRestart(); Log.d(TAG, "------Activity onDestroy-------"); } @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 boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } public void selectFrag(View view) { Fragment fr; if(view==findViewById(R.id.btn2)) { fr=new FragmentTwo(); }else { fr=new FragmentOne(); } FragmentManager fm=getFragmentManager(); FragmentTransaction fragmentTransaction=fm.beginTransaction(); fragmentTransaction.replace(R.id.fragment_place, fr); fragmentTransaction.commit(); } }
FragmentOne中添加测试语句,同理FragmentTwo
package com.example.fragmentexample; import android.app.Activity; import android.app.Fragment; import android.os.Bundle; import android.support.annotation.Nullable; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; public class FragmentOne extends Fragment { final String TAG = "test"; @Override public void onAttach(Activity activity) { 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-------"); } public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { // TODO Auto-generated method stub Log.d(TAG, "------onCreateView-------"); return inflater.inflate(R.layout.fragment_one, container, false); } @Override public void onActivityCreated(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onActivityCreated(savedInstanceState); Log.d(TAG, "------onActivityCreated-------"); } @Override public void onStart() { // TODO Auto-generated method stub super.onStart(); Log.d(TAG, "------onStart-------"); } @Override public void onResume() { // TODO Auto-generated method stub super.onResume(); Log.d(TAG, "------onResume-------"); } @Override public void onPause() { // TODO Auto-generated method stub super.onPause(); Log.d(TAG, "------onPause-------"); } @Override public void onStop() { // TODO Auto-generated method stub super.onStop(); Log.d(TAG, "------onStop-------"); } @Override public void onDestroyView() { // TODO Auto-generated method stub super.onDestroyView(); Log.d(TAG, "------onDestroyView-------"); } @Override public void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); Log.d(TAG, "------onDestroy-------"); } @Override public void onDetach() { // TODO Auto-generated method stub super.onDetach(); Log.d(TAG, "------onDetach-------"); } }当运行程序时显示主界面时,输出的语句时,第一次就输出Fragment1中的方法,是因为我的默认显示是Fragment1
当点击按钮Fragment1时输出的语句是
当点击按钮Fragment2时输出的语句是
这是因为Fragment1彻底由Fragment2代替,必然经过销毁的过程,然后创建Fragment2,从加载到运行状态。与上图中的流程一一对应。