您的位置:首页 > 其它

fragment基础【替换、传值、回掉】

2016-01-07 02:48 274 查看
总结知识点:

fragment的替换、fragment调用activity中的参数和组件、activity调用fragment中的参数、回掉监听事件

1.fragment的替换。先看下面的一张图,应用场景【左边不同位置的单击事件,在右侧显示不同的内容:音乐歌词播放器--》对应歌曲曲目列表和曲目信息】

需要掌握:会FragmentTransaction的相关方法、了解FragmentManager类、addOnBackStackChangedListener、getBackStackEntryCount、getBackStackEntryAt方法.


j

重要代码:

private void showContent(int position) {
//新的fragment
MyContentFragment contentFragment = MyContentFragment.getInstance(position);
//旧的fragment
MyContentFragment mf = (MyContentFragment) fm.findFragmentById(R.id.content1);

if(mf == null||mf.getMindex()!=position){
//需要将新的fragment替换成旧的
//开启事务
FragmentTransaction ft = fm.beginTransaction();//
ft.replace(R.id.content1, contentFragment);
ft.addToBackStack("fragment"+position);
//提交
ft.commit();


下面代码主要看Bundle在fragment内部传参。

public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
//根据星期日期不同,显示不同的内容
Bundle bundle = this.getArguments();
int index = bundle.getInt("index");
this.mIndex = index;
String name = bundle.getString("name");
String content = contents[index];
TextView tv = new TextView(getActivity());
tv.setText(name+content);
tv.setGravity(Gravity.CENTER);
return tv;
}

public static MyContentFragment getInstance(int index){
MyContentFragment contentFragment = new MyContentFragment();//创建fragment
Bundle bundle = new Bundle();//
bundle.putInt("index", index);
bundle.putString("name", "坑总");
contentFragment.setArguments(bundle);//设置参数进去
return contentFragment;
}

2)Fragment中可以调用Activity中的字段和方法

fragment中掉activity中的组件:

//先将dota数据改成activity里面的sleep
mActivity = (MainActivity) this.getActivity();
TextView tv = (TextView) mActivity.findViewById(R.id.tv);</span>


activity中调用fragment中相关信息:如图,



这里强调为什么调用fragment中的组件,Adapter相关信息呢?这里设计到生命周期的问题。在activity的oncreatView中的时候,只是加载布局,并未填充数据,等。我在显示onResume()【界面数据加载完成】,再获取!

3)接口回掉:
应用场景:

 在某些案例中,可能需要Fragment与Activity共享事件。在Fragment内部定义一个回调接口是一个好方法,并且规定由持有它的Activity实现这个回调方法。当Activity通过接口接受回调时,它能在必要时与布局中的其他Fragment共享信息。

例如,如果一个音乐播放器的应用程序在一个Activity中有两个Fragment---一个用来显示歌曲列表(Fragment A),另一个用来显示歌曲信息(Fragment B),然后在列表项目被选中时Fragment A必须告诉Activity,以便它能告诉Fragment B显示对应的歌曲信息。在下面的例子中在Fragment A的内部声明了onMp3ChangedListener接口。 

先看一个入门:activity中实现TextView的OnClickListener事件。可是发现TextView中并没有接口回掉,OnClickListener。看源码,TextView的父类View中确实有这个接口OnClickListener.

那么我们自己实现一个CallBack回掉。

步骤:1.定义一个接口--》2)哪个类中要回掉它,哪个类就集成它。    一般要共享事件,那么就在activity中的控件中去绑定它。

简单例子:

定义接口

import android.view.View;

public interface OnTextViewClickListener {
void onTextViewClick(View v);
}


控件中定义,让外界可以监听:

public class MyTextView extends View{
private float touchX,touchY;
private OnTextViewClickListener onTextViewClickListener;

public OnTextViewClickListener getOnTextViewClickListener() {
return onTextViewClickListener;
}

public void setOnTextViewClickListener(
OnTextViewClickListener onTextViewClickListener) {
this.onTextViewClickListener = onTextViewClickListener;
}

public MyTextView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
touchX = event.getX();
touchY = event.getY();
break;
case MotionEvent.ACTION_UP:
float x = event.getX();
float y = event.getY();
Log.i("INFO", "DownX:"+touchX+"----upX:"+x);
if(touchX == x &&touchY == y){
//产生了onclick事件
onTextViewClickListener.onTextViewClick(this);
}
break;
default:
break;
}


使用它的activity去实现接口,并绑定:

public class MainActivity extends Activity implements OnTextViewClickListener{</span>
<span style="font-size:18px;">  //定会回调函数
public void onTextViewClick(View v) {
// TODO Auto-generated method stub
Toast.makeText(this, "ontextViewClick", 1000).show();
}


理解这个思想后,来看看上面场景的应用:

public static class FragmentA extends ListFragment {
...
//持有它的Activity必须实现这个回调方法
public interface onMp3ChangedListener{
public void onMp3Changed(int index);//index表示的是歌曲在列表中的序号
}
...
}


 然后,持有这个Fragment的Activity要实现onMp3ChangedListener接口,并且要重写onMp3Changed()方法把来自Fragment A的事件通知给Fragment B。要确保持有Fragment的Activity实现这个接口, Fragment A 的onAttach()回调方法(当Fragment被添加到Activity时系统调用这个方法)通过类型转换onAttach()传入的Activity来实例化一个onMp3ChangedListener的实例。

onMp3ChangedListener的实例。
public static class FragmentA extends ListFragment {
onMp3ChangedListener mListener;
...
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mListener = (onMp3ChangedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement OnArticleSelectedListener");    }
...
}


 如果这个Activity没有实现这个接口,那么Fragment会抛出ClassCastException异常。

如果成功,那么mListener成员就会拥有Activity实现的onMp3ChangedListener对象的引用,以便Fragment A能够通过onMp3ChangedListener接口定义的回调方法和Activity共享事件。例如,Fragment A继承了ListFragment,那么用户每次点击列表项时,系统都会调用Fragment中的onListItemClick()方法,然后调用onMp3Changed()方法和Activity共享事件: 
public static class FragmentA extends ListFragment {
OnArticleSelectedListener mListener;
...
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
mListener.onMp3Changed(position);
}
...
}


 传递给onListItemClick()的position参数是被点击项目的行ID,Activity(或其他的Fragment)使用这个ID从歌曲列表中获取对应的歌曲信息。 

工作中遇到这样的一个问题:

MainActivity中嵌套4个Fragment作为底部的四个Tab,每次点击MainActivity下面的四个Tab图标切换到四个Fragment,那么怎么实现每次Fragment切换的需求,并且Fragment每次不会重新实例话,只是影藏和显示的动态切换呢。

      最基本的知道fragment相关的FragmentTransaction的相关方法的用法,特别是.replace(),.add(),.show(),.hide()的用法。思路:首先添加【add】fragment进去,然后.show(),.hide()即可.

参考项目中的代码:

private void setSelect(int i) {
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
hideFragment(transaction);
switch (i) {
case 0:
if (mTab01 == null) {
mTab01 = new MainFragment();
transaction.add(R.id.id_content, mTab01);
} else {
if(!mTab01.isAdded()){
transaction.add(R.id.id_content, mTab01);
}else{
transaction.show(mTab01);
}
//transaction.replace(R.id.id_content, mTab01);
}
tabExerseImg.setImageResource((R.drawable.exerise_y));
id_tab_exerse_tv.setTextColor(Color.parseColor("#55aee5"));
transaction.commit();
break;

case 1:
if (mTab02 == null) {
mTab02 = new ExaminationFragment();
transaction.add(R.id.id_content, mTab02);
} else {
if(!mTab01.isAdded()){
transaction.add(R.id.id_content, mTab02);
}else{
transaction.show(mTab02);
}
//transaction.replace(R.id.id_content, mTab02);
}
//.refreshData();
tabExameImg.setImageResource((R.drawable.examination_y));
id_tab_exame_tv.setTextColor(Color.parseColor("#55aee5"));
transaction.commit();

break;

case 2:
if (mTab03 == null) {
mTab03 = new FoundFragment();
transaction.add(R.id.id_content, mTab03);
} else {
if(!mTab03.isAdded()){
transaction.add(R.id.id_content, mTab03);
}else{
transaction.show(mTab03);
}
}
tabFindImg.setImageResource((R.drawable.found_y));
id_tab_find_tv.setTextColor(Color.parseColor("#55aee5"));
transaction.commit();
break;

case 3:
if (mTab04 == null) {
mTab04 = new MineFragment();
transaction.add(R.id.id_content, mTab04);
} else {
if(!mTab04.isAdded()){
transaction.add(R.id.id_content, mTab04);
}else{
transaction.show(mTab04);
}
}
tabMineImg.setImageResource((R.drawable.mine_y));
id_tab_mine_tv.setTextColor(Color.parseColor("#55aee5"));
transaction.commit();
break;
default:
break;
}
transaction.commit();
}

private void hideFragment(FragmentTransaction transaction) {
if (mTab01 != null) {
transaction.hide(mTab01);
}
if (mTab02 != null) {
transaction.hide(mTab02);
}
if (mTab03 != null) {
transaction.hide(mTab03);
}
if (mTab04 != null) {
transaction.hide(mTab04);
}

}
Fragment应用场景:1.大型设备适配:平板  2.组合控件:ViewPager、ViewGroup  3.界面大量切换的时候【试卷、书签】
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息