这个周末终于把猫鼠游戏补完了,想想上星期想写这篇博客,结果一直拖到现在.下面开工吧.
Fragment用法
我们直接用V4的Fragment吧,因为毕竟要兼容低版本.
看看API上如何说的吧.
- Your activity must extend FragmentActivity
- You must call getSupportFragmentManager() to get the FragmentManager
这里我们继承
ActionBarActivity,他实际上是FragmentActivity的子类.
MainActivity的代码:
public class MainActivity extends ActionBarActivity {
private FragmentManager mFragmentManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentOne fragmentOne = new FragmentOne();
mFragmentManager = getSupportFragmentManager();
FragmentTransaction mTransaction = mFragmentManager.beginTransaction();
mTransaction.add(R.id.content,fragmentOne , "fragmentOne");
mTransaction.commit();
}
布局文件:
<RelativeLayout 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"
tools:context="com.mio.fragmentdemo.MainActivity" >
<FrameLayout
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
FragmentOne代码:
public class FragmentOne extends Fragment implements OnClickListener {
@Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_one,container,false);
Button mButton = (Button) view.findViewById(R.id.bt);
mButton.setOnClickListener(this);
return view;
}
@Override
public void onClick(View v) {
FragmentTwo fragmentTwo = new FragmentTwo();
FragmentManager mFragmentManager = getActivity().getSupportFragmentManager();
FragmentTransaction mTransaction = mFragmentManager.beginTransaction();
mTransaction.replace(R.id.content, fragmentTwo, "fragmentTwo");
mTransaction.addToBackStack(null);
mTransaction.commit();
}
}
主要就是onCreateView方法是控制显示的View内容的.这样我们就完成了Fragment的使用.
fragment的add与replace
不过细心的人发现了,上面我们用了add方法,下面我们用了replace方法,他们到底有什么区别呢?
首先fragment也是有生命周期的.让我们看看官方的Api吧.
OK,知道了生命周期就简单了,实际上replace会调用onDestoryView的方法也就是从fragment1到fragment2如果用replace的话,会调用fragment1的onDestoryView方法,而add不会.
fragment的事务
fragment的"任务栈"
上面的代码有下面的方法
<span style="font-size:12px;">mTransaction.addToBackStack(null);</span>
他是做什么的呢?实际上就是事务的回滚,和数据库一样.
简单的说就是:
在你调用 commit() 之前,调用addToBackStack() ,则用户按返回键就会回到commit前的fragment状态。
fragment的通信
1.与activity之间通信
fragment是attach到activity上的,所以可以通过getActivity() 方法拿到activity的实例,同样宿主activity也可以通过FragmentManager的findFragmentById() 或者 findFragmentByTag()方法获得fragment的引用.
2.fragment之间的通信
fragment之间通过"桥梁"---activity是最好的了.具体方法是通过接口回调,可参考帖子:
http://blog.csdn.net/xyz_lmn/article/details/8631195
大概是:fragment1里有一个接口里面有个回调方法,activity拿到fragment1实例并实现接口及接口中的回调,在回调的方法中同样可以拿到fragment2,这样就达到了fragment1操作fragment2的效果!
接口回调复习
Demo
有三个fragment,他们的布局都如下图
点击按钮就会进入下个fragment,其中fragment1是attach在MainActivity上的.
如何达到这个效果?很简单吧?
直接按照我最上面的代码就可以了嘛!监听按钮事件,点击就add/replace下一个fragment就可以了.
但这样好吗?
最好别这么做,不规范!
Activity是Control!让activity去做这些事.
如下代码:
MainActivity:
public class MainActivity extends ActionBarActivity implements OneFragmentClickListener {
private FragmentManager mFragmentManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/**
* 一开始MainActivity加载一个fragmentOne
*/
FragmentOne fragmentOne = new FragmentOne();
mFragmentManager = getSupportFragmentManager();
FragmentTransaction mTransaction = mFragmentManager.beginTransaction();
mTransaction.add(R.id.content,fragmentOne , "fragmentOne");
mTransaction.commit();
}
/**
* 写在fragmentOne中的回调方法
*/
@Override
public void oneFragmentClick() {
FragmentTwo fragmentTwo = new FragmentTwo();
FragmentTransaction mTransaction = mFragmentManager.beginTransaction();
mTransaction.replace(R.id.content, fragmentTwo, "fragmentTwo");
mTransaction.addToBackStack(null);
mTransaction.commit();
//设置fragment2的按钮需要设置回调接口
fragmentTwo.setTwoFragmentListener(new TwoFragmentClickListener() {
@Override
public void twoFragmentClick() {
Toast.makeText(MainActivity.this, "搞定,这里写进入fragment3的逻辑即可", 0).show();
}
});
}
fragmentOne:
public class FragmentOne extends Fragment implements OnClickListener {
/**
* 暴漏按钮作用的接口,复用性高,耦合性低
* @author mio
*
*/
public interface OneFragmentClickListener{
void oneFragmentClick();
}
@Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_one,container,false);
Button mButton = (Button) view.findViewById(R.id.bt);
mButton.setOnClickListener(this);
return view;
}
/**
* 只要是实现了此接口的,点击事件会自动调用oneFragmentClick方法.
*/
@Override
public void onClick(View v) {
if(getActivity() instanceof OneFragmentClickListener){
((OneFragmentClickListener) getActivity()).oneFragmentClick();
}
}
}
public class FragmentTwo extends Fragment implements OnClickListener {
private TwoFragmentClickListener mTwoFragmentClickListener;
/**
* 接口
* @author mio
*
*/
public interface TwoFragmentClickListener{
void twoFragmentClick();
}
/**
* 设置这个接口
* @param twoFragmentClickListener
*/
public void setTwoFragmentListener(TwoFragmentClickListener twoFragmentClickListener){
mTwoFragmentClickListener=twoFragmentClickListener;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_two, container, false);
Button mButton = (Button) view.findViewById(R.id.bt);
mButton.setOnClickListener(this);
return view;
}
/**
* 只有设置了这个接口,才能保证不为null,也就才能调用方法
*/
@Override
public void onClick(View v) {
if(mTwoFragmentClickListener!=null){
mTwoFragmentClickListener.twoFragmentClick();
}
Toast.makeText(getActivity(), "你没有设置回调接口哟", 0).show();
}
}
上面便是正确的用法,其中用到了两种接口的使用方式.
第一种是直接回调.
只要MainActivity实现接口即可.
第二种监听回调.
只要设置了监听即可.(其实这里也就发现了,监听说白了就是设置接口)
下面附上不规范的以及规范的Demo: