一、什么是Fragment
直译 碎片,可以将页面分成若干块展示在用户面前,Fragment是为了简化Activity而出的,所以也算是Activity的一部分。
此外Fragment有自己的声明周期和接收、处理用户的事件,这样就不必要在一个Activity里面写一堆事件、控件的代码了。更为重要的是,你可以动态的添加、替换、移除某个Fragment。
二、Fragment怎么用?
1.Fragment添加到activity中的两种方法
方法1:直接在activity的布局文件中声明。然后绑定用即可。
activity布局文件:
<LinearLayout 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"
android:orientation="horizontal"
tools:context="com.example.fragmentdemo.MainActivity" >
<fragment
android:id="@+id/title"
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_weight="1"
android:name="com.example.fragmentdemo.title"/>
<fragment
android:id="@+id/content"
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_weight="3"
android:name="com.example.fragmentdemo.content"/>
</LinearLayout>
MainActivity:
package com.example.fragmentdemo;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
public class MainActivity extends Activity {
content content1;
title title1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
content1=(content)getFragmentManager().findFragmentById(R.id.content);
title1=(title)getFragmentManager().findFragmentById(R.id.title);
}
}
Fragment的子类文件 content:
package com.example.fragmentdemo;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class content extends Fragment{
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View view=inflater.inflate(R.layout.conten_layout, container, false);
return view;
}
}
Fragment的子类文件 title:
package com.example.fragmentdemo;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class title extends Fragment{
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view=inflater.inflate(R.layout.title_layout, container, false);
// TODO Auto-generated method stub
return view;
}
}
content和title的布局文件就不写了,下面是效果图:
方法2:通过编码将fragment添加到activity
activity布局文件:
<?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="horizontal" >
<fragment
android:id="@+id/titleFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:name="com.example.fragmentdemo.title"/>
<FrameLayout
android:id="@+id/contentFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3" >
</FrameLayout>
</LinearLayout>
mainactivity:
package com.example.fragmentdemo;
import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.os.Bundle;
public class MainActivity2 extends Activity{
private content content1;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.main2);
addContentLayout();
}
private void addContentLayout()
{
FragmentManager fm=getFragmentManager();
//开启事务
FragmentTransaction ft=fm.beginTransaction();
content1=new content();
//添加fragment
ft.add(R.id.contentFragment, content1);
//提交
ft.commit();
}
}
//方法: 开启事务->添加->提交
2.Fragment的出入栈操作
activity的布局文件:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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/button1"
android:onClick="oneClick"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="one" />
<Button
android:id="@+id/button2"
android:onClick="twoClick"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:text="two" />
<FrameLayout
android:id="@+id/content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_below="@+id/button1" >
</FrameLayout>
</RelativeLayout>
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" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:gravity="center"
android:textAppearance="?android:attr/textAppearanceLarge" />
</LinearLayout>
mainactivity:
package com.example.fragmentdemo;
import android.app.Activity;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
public class PopBackStack extends Activity{
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
setContentView(R.layout.pop_back);
super.onCreate(savedInstanceState);
}
public void oneClick(View view)
{
popBackfragment p1=new popBackfragment("one");
FragmentTransaction ft=getFragmentManager().beginTransaction();
ft.replace(R.id.content, p1);
//将当前Fragment添加到activity中
ft.addToBackStack(null);
ft.commit();//提交
}
public void twoClick(View view)
{
popBackfragment p1=new popBackfragment("two");
FragmentTransaction ft=getFragmentManager().beginTransaction();
ft.replace(R.id.content, p1);
//将当前Fragment添加到activity中
ft.addToBackStack(null);
ft.commit();//提交
}
@Override
//键盘按下时
//此处让fragment依次出栈
public boolean onKeyDown(int keyCode, KeyEvent event) {
if(keyCode==KeyEvent.KEYCODE_BACK)
{
if(getFragmentManager().getBackStackEntryCount()==0)
{
finish();
}else
{
getFragmentManager().popBackStack();
}
return true;
}
return super.onKeyDown(keyCode, event);
}
}
fragment子类文件:
package com.example.fragmentdemo;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebView.FindListener;
import android.widget.TextView;
public class popBackfragment extends Fragment{
private String title;
public popBackfragment(String title)
{
this.title=title;
}
//该传参方法易丢失参数,标准的传参方法见后文
public popBackfragment()
{
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view= inflater.inflate(R.layout.back_layout, container, false);
TextView v=(TextView)view.findViewById(R.id.textView1);
v.setText(title);
return view;
}
}
3.标准传参方法
(利用bundle传参数)
//此传参数方法易丢失参数
// private String title;
// public popBackfragment(String title)
// {
// this.title=title;
// }
//此为官方推荐的标准传参方法
public static popBackfragment getInstance(String title)
{
popBackfragment p=new popBackfragment();
Bundle b=new Bundle();
b.putString("title", title);
p.setArguments(b);
return p ;
}
setText也要改变:
v.setText(getArguments().getString("title"));
mainactivity中fragment子类对象传参数的部分也要变化:
public void oneClick(View view)
{
popBackfragment p1=popBackfragment.getInstance("one");
FragmentTransaction ft=getFragmentManager().beginTransaction();
ft.replace(R.id.content, p1);
//将当前Fragment添加到activity中
ft.addToBackStack(null);
ft.commit();//提交
}
4.Fragment与Activity之间的交互,以及Fragment与Fragment间的交互
哪个类是事件的触发源,就在那里定义接口!!!
思路概要:
1))在Fragment子类1中定义一个回调接口
//定义一个回调接口
public static interface myMenuListener
{
public void changeValue(String value);
}
2))在Activity中实现该Fragment子类1接口,并实现接口方法
public class MenuFragment extends Fragment implements OnClickListener{
@Override
//此处 实现了menu接口中的change方法,将其反馈的参数传过来,
//然后又联系上了main方法,将传来的value传给main中的change方法
//实现了双方的连接
public void changeValue(String value) {
// TODO Auto-generated method stub
mainfragment.changeTextViewValue(value);
}
}
3))在Fragment子类1中声明接口对象,并利用onAttach方法实例化
public class MenuFragment extends Fragment implements OnClickListener{
private myMenuListener mymenulistener;
//就绪时
public void onAttach(Activity activity) {
// TODO Auto-generated method stub
super.onAttach(activity);
mymenulistener=(myMenuListener)activity;//此处实例化mymenulistener
}
由此在Fragment子类一中的值即可传递到Activity中。
4))在Activity中将布局文件中的两个Fragment绑定
public class MainActivity3 extends Activity implements MenuFragment.myMenuListener{
private MainFragment mainfragment;
private MenuFragment menufragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.main3);
menufragment=(MenuFragment)getFragmentManager().findFragmentById(R.id.menuFragment);
mainfragment=(MainFragment)getFragmentManager().findFragmentById(R.id.mainFragment);
}
注意:布局文件中的fragment也与Fragment子类已经连接
<fragment
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:id="@+id/menuFragment"
android:name="com.example.fragmentdemo.MenuFragment"/>
<fragment
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3"
android:id="@+id/mainFragment"
android:name="com.example.fragmentdemo.MainFragment"/>
5))在Fragment子类2中定义好传值的方法,并在Activity实现接口方法中调用该方法。
子类2中定义的方法:
public class MainFragment extends Fragment{
public void changeTextViewValue(String value)
{
textView_value.setText(value);
}
}
Activity实现接口方法中调用该方法:
@Override
//此处 实现了menu接口中的change方法,将其反馈的参数传过来,
//然后又联系上了main方法,将传来的value传给main中的change方法
//实现了双方的连接
public void changeValue(String value) {
// TODO Auto-generated method stub
mainfragment.changeTextViewValue(value);
}
以下是具体的代码:
MainActivity:
package com.example.fragmentdemo;
import android.app.Activity;
import android.os.Bundle;
public class MainActivity3 extends Activity implements MenuFragment.myMenuListener{
private MainFragment mainfragment;
private MenuFragment menufragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.main3);
menufragment=(MenuFragment)getFragmentManager().findFragmentById(R.id.menuFragment);
mainfragment=(MainFragment)getFragmentManager().findFragmentById(R.id.mainFragment);
}
@Override
//此处 实现了menu接口中的change方法,将其反馈的参数传过来,
//然后又联系上了main方法,将传来的value传给main中的change方法
//实现了双方的连接
public void changeValue(String value) {
// TODO Auto-generated method stub
mainfragment.changeTextViewValue(value);
}
}
Fragment子类1:
package com.example.fragmentdemo;
import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
public class MenuFragment extends Fragment implements OnClickListener{
private myMenuListener mymenulistener;
public MenuFragment()
{
}
@Override
//就绪时
public void onAttach(Activity activity) {
// TODO Auto-generated method stub
super.onAttach(activity);
mymenulistener=(myMenuListener)activity;//此处实例化mymenulistener
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View view = inflater.inflate(R.layout.fragment_menu, container, false);
view.findViewById(R.id.bt_news).setOnClickListener(this);
view.findViewById(R.id.bt_music).setOnClickListener(this);
return view;
}
// public void newsClick(View v)
// {
// mymenulistener.changeValue("news");
// }
// public void musicClick(View v)
// {
// mymenulistener.changeValue("music");
// }
//定义一个回调接口
public static interface myMenuListener
{
public void changeValue(String value);
}
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch(v.getId())
{
case R.id.bt_news:
mymenulistener.changeValue("news");
break;
case R.id.bt_music:
mymenulistener.changeValue("music");
break;
}
}
}
Fragment子类2:
package com.example.fragmentdemo;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class MainFragment extends Fragment{
private TextView textView_value;
public MainFragment()
{
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View view = inflater.inflate(R.layout.fragment_main, container, false);
textView_value=(TextView)view.findViewById(R.id.value);
return view;
}
public void changeTextViewValue(String value)
{
textView_value.setText(value);
}
}
MainActivity的布局文件: