在关Fragment间参数的传递,有两种情况:

  • 第一种情况:同一个container中不同fragment间的参数传递。这种情况一般发生在fragment跳转时,上一个Fragment将参数传递给下一个Fragment。
  • 第二种情况:是同一个Activity中,不个container间Fragment的参数传递。

第一种情况:Fragment跳转时传递参数及结果回传的方法

效果图:

1、点击“加载第二个Fragment按钮”,加载出第二个Fragment,同时传递过去参数:“从Fragment1传来的参数”这几个String;

2、当用户点击第二个Fragment中的几个图片时,将点中的结果返回给第一个Fragment,将用户的选择在第一个Fragment显示出来

一、基本架构搭建

首先,我们要把整个架构搭起来,然后再进行参数传递和回传

(一)、基本XML构建:

根据上面的效果,大家很容易看到两个Fragment的布局:

1、Fragment1的布局:(fragment1.xml)

很简单,垂直布局,上面一个ImageView来盛装返回过来的图片结果,下面一个Button来用来点击加载第二个Fragment;

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  android:layout_width="match_parent"  android:layout_height="match_parent"  android:background="#ffffff"  android:orientation="vertical">  <ImageView  android:id="@+id/img_result"  android:layout_width="100dp"  android:layout_height="100dp"  android:scaleType="center"/>  <Button  android:id="@+id/load_fragment2_btn"  android:layout_width="fill_parent"  android:layout_height="wrap_content"  android:text="加载第二个Fragment"/>  </LinearLayout>

2、Fragment2的布局:(fragment2.xml)

这个也是垂直布局,上面的一个TextView用来盛装从Fragment1传过来的String参数,下面的几个ImageView用来显示几个供用户选择的图片

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  android:layout_width="match_parent"  android:layout_height="match_parent"  android:background="#ffffff"  android:orientation="vertical">  <TextView  android:id="@+id/textview"  android:layout_width="wrap_content"  android:layout_height="wrap_content"  android:text="This is fragment 2"  android:textColor="#000000"  android:textSize="25sp" />  <ImageView  android:id="@+id/img1"  android:layout_width="100dip"  android:layout_height="100dp"  android:scaleType="center"  android:src="@drawable/animal1"/>  <ImageView  android:id="@+id/img2"  android:layout_width="100dip"  android:layout_height="100dp"  android:scaleType="center"  android:src="@drawable/animal2"/>  <ImageView  android:id="@+id/img3"  android:layout_width="100dip"  android:layout_height="100dp"  android:scaleType="center"  android:src="@drawable/animal3"/>  <ImageView  android:id="@+id/img4"  android:layout_width="100dip"  android:layout_height="100dp"  android:scaleType="center"  android:src="@drawable/animal4"/>  </LinearLayout>

(二)对应的Fragment类

1、在MainActivity初始化时,将Fragment1显示出来:
MainActivity对应的XML文件:(main_activity.xml)

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  xmlns:tools="http://schemas.android.com/tools"  android:id="@+id/main_layout"  android:layout_width="match_parent"  android:layout_height="match_parent"  tools:context=".MainActivity">  <TextView  android:text="@string/hello_world"  android:layout_width="wrap_content"  android:layout_height="wrap_content" />  </RelativeLayout>

对应的代码:

public class MainActivity extends Activity {  @Override  protected void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  setContentView(R.layout.activity_main);  Fragment1 fragment1 = new Fragment1();  getFragmentManager().beginTransaction().replace(R.id.main_layout, fragment1).commit();  }
}

2、Fragment1:在用户点击时,将fragment2添加到当前页面显示出来;

public class Fragment1 extends Fragment {  @Override  public View onCreateView(LayoutInflater inflater, ViewGroup container,  Bundle savedInstanceState) {  View view = inflater.inflate(R.layout.fragment1, container, false);  Button btn = (Button)view.findViewById(R.id.load_fragment2_btn);  btn.setOnClickListener(new View.OnClickListener(){  @Override  public void onClick(final View view) {  Fragment2 fragment2 = new Fragment2();  FragmentTransaction transaction = getFragmentManager().beginTransaction();  transaction.add(R.id.main_layout, fragment2);  transaction.addToBackStack(null);  transaction.commit();  }  });  return view;  }
}

3、Fragment2:至于目前的它还是很简单的,只要能显示出来 就好了,所以他的代码为:

public class Fragment2 extends Fragment implements View.OnClickListener {  @Override  public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {  View view = inflater.inflate(R.layout.fragment2, container, false);  return view;  }  }

二、Fragment间参数传递

在Fragment2中,新建一个函数:newInstance(String  text)来接收传过来的参数:

新建一个Fragment2实例,然后将参数通过SetArguments设置到其中;

public static Fragment2 newInstance(String text) {  Fragment2 fragment = new Fragment2();  Bundle args = new Bundle();  args.putString("param", text);  fragment.setArguments(args);  return fragment;
}

然后在Fragment2的OnCreateView的时候再从arguments中获取参数:

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {  View view =  inflater.inflate(R.layout.fragment2, container, false);  if (getArguments() != null) {  String mParam1 = getArguments().getString("param");  TextView tv =  (TextView)view.findViewById(R.id.textview);  tv.setText(mParam1);  }  return view;
}

在Fragment1中,在调起Fragmen2t时,通过调用newInstance函数来获取实例并传递参数:

public class Fragment1 extends Fragment {  @Override  public View onCreateView(LayoutInflater inflater, ViewGroup container,  Bundle savedInstanceState) {  View view = inflater.inflate(R.layout.fragment1, container, false);  Button btn = (Button)view.findViewById(R.id.load_fragment2_btn);  btn.setOnClickListener(new View.OnClickListener(){  @Override  public void onClick(final View view) {  Fragment2 fragment2 = Fragment2.newInstance("从Fragment1传来的参数");  FragmentTransaction transaction = getFragmentManager().beginTransaction();  transaction.add(R.id.main_layout, fragment2);  transaction.addToBackStack(null);  transaction.commit();  }  });  return view;  }
}

(三)、从Fragment2向Fragment1回传参数

这里只有利用回调,有关回调传递参数的问题,我在前一篇文章中:《详解Dialog(三)——自定义对话框视图及参数传递》第三部分:参数传递;详细讲过,大家可以先看源码,如果源码不懂,可以参考下这篇文章,这里就不再赘述。


第二种情况:不同container间Fragment的参数传递

二、同一个Activity,不同container间的参数传递

这里到了这篇文章的重点内容了哦,这可并不是说上一部分不重要哈,其实上一部分要比这部分重要!同一个container中不同Fragment间的参数传递一般的工程都会用到的,所以大家一定要看。而我这里不讲,是因为以前有讲过,这里就没必要再重复一遍了,好了,废话说了好多……开整吧。
先看看效果图:
1、在这个Actiivty中有两个Fragment;
2、Fragment1中有一个listView,当我们点击ListView的Item的时候,把Item上的内容更新到Fragment2上

这里有多种实现方法,最可取的是方法三。我们由简到易慢慢讲。
我们想使两个fragment实例要能通信,那如果我们都能通过findViewById()找到所有的控件,直接操控的话,岂不就实现了。而通过findViewById()能找到所有控件实例的地方就是在Activity中了,所以这就有了方法一。

方法一:直接在Activity中操作

在Activity中找到对应的控件实例,然后直接操控即可。
先看看MainActivity的布局:activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  android:id="@+id/main_layout"  android:layout_width="match_parent"  android:layout_height="match_parent"  android:orientation="horizontal"  android:baselineAligned="false" >  <fragment  android:id="@+id/fragment1"  android:name="com.harvic.com.harvicblog5_1.Fragment1"  android:layout_width="0dip"  android:layout_height="match_parent"  android:layout_weight="1" />  <fragment  android:id="@+id/fragment2"  android:name="com.harvic.com.harvicblog5_1.Fragment2"  android:layout_width="0dip"  android:layout_height="match_parent"  android:layout_weight="1" />
</LinearLayout>

在这个布局中,横向放两个fragment,由于这里的fragment是静态添加的,所以每个fragment都是有id值的,所以这时候如果我们要获取某个fragment的实例,就可以通过FragmentManager::findFragmentById()来找到了。
然后是这两个fragment的布局。
fragment1.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  android:layout_width="match_parent"  android:layout_height="match_parent"  android:background="#ff00ff"  android:orientation="vertical" >  <TextView  android:layout_width="wrap_content"  android:layout_height="wrap_content"  android:text="This is fragment 1"  android:textColor="#000000"  android:textSize="25sp" />  <ListView  android:id="@+id/list"  android:layout_width="match_parent"  android:layout_height="match_parent"></ListView>
</LinearLayout>

可以看到fragment1的布局中,除了一个标识当前Fragment的TextView,就是一个listview;
fragment2.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  android:layout_width="match_parent"  android:layout_height="match_parent"  android:background="#ffff00"  android:orientation="vertical" >  <TextView  android:id="@+id/fragment2_tv"  android:layout_width="wrap_content"  android:layout_height="wrap_content"  android:text="This is fragment 2"  android:textColor="#000000"  android:textSize="25sp" />  </LinearLayout>

可以看到在fragment2中非常干净,只有一个TextView来显示当前用户在fragment1中的点击结果。
下面看看在MainActivity中是如何实现的吧

protected void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  setContentView(R.layout.activity_main);  ArrayAdapter arrayAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,mStrings);  ListView listView = (ListView)findViewById(R.id.list);  listView.setAdapter(arrayAdapter);  mFragment2_tv = (TextView)findViewById(R.id.fragment2_tv);  listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {  @Override  public void onItemClick(AdapterView<?> parent, View view, int position, long id) {  mFragment2_tv.setText(mStrings[position]);  }  });
}

其中:

private String[] mStrings = {"Abbaye de Belloc", "Abbaye du Mont des Cats", "Abertam", "Abondance", "Ackawi",  "Acorn", "Adelost", "Affidelice au Chablis", "Afuega'l Pitu", "Airag", "Airedale", "Aisy Cendre",  "Allgauer Emmentaler", "Abbaye de Belloc", "Abbaye du Mont des Cats", "Abertam", "Abondance", "Ackawi",  "Acorn", "Adelost", "Affidelice au Chablis", "Afuega'l Pitu", "Airag", "Airedale", "Aisy Cendre",  "Allgauer Emmentaler"};

难度不大,通过(ListView)findViewById(R.id.list);找到fragment1中的listview,通过(TextView)findViewById(R.id.fragment2_tv);找到fragment2中的textView,然后直接对他们进行操作。即下面的代码:

listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {  @Override  public void onItemClick(AdapterView<?> parent, View view, int position, long id) {  mFragment2_tv.setText(mStrings[position]);  }
});

当用户点击listView的一个item时,将值setText到fragment2的textView中。

可见,直接在activity中操作各个fragment的控件就可以实现消息互传。但,这样真的好吗?如果每个fragment中的控件都在Activity中操作,那还要fragment干嘛!最最起码,应该每个fragment负责自己的控件操作才对嘛!
所以,我们对这种方法进行改进,将点击Item的赋值操作放到fragment1中去。所以,这就有方法二;

方法二:直接在fragment中操作

在这里我们会把所有方法写在Fragment1中,这里涉及到两方面的内容:
第一:在Fragment中如何获得自己控件的引用,比较这里Fragment1里的listview控件。
第二:在Fragment中如何获得其它Fragment页面中控件的引用,比如这里Fragment2里的TextView控件。 
首先,获取自己控件引用的方法: 
方法一:在onCreateView()中获取。 
就比如这里获取自己的listView控件的引用,代码如下:

public View onCreateView(LayoutInflater inflater, ViewGroup container,  Bundle savedInstanceState) {  View rootView = inflater.inflate(R.layout.fragment1, container, false);  listView = (ListView)rootView.findViewById(R.id.list);//获取自己视图里的控件引用,方法一  return rootView;
}

由于在onCreateView()中,还没有创建视图,所以在这里如果使用getView()方法将返回空。所以如果要获取其实图中指定控件的引用,只用用inflater.inflate()返回的rootView;在这个rootView()中用findViewById来查找。
方法二:在onActivityCreated()函数中获取。
从《Fragment详解之一——概述》的流程图中可以看到,onActivityCreated()回调会在Activity的OnCreate()执行完成后再执行,也就是说,onActivityCreated()会在Activity的OnCreate()工作完成以后才会执行。所以当执行到onActivityCreated()的时候Activity已经创建完成,它其中的各个fragment也视图等等的也都已经创建完成。所在可以在这里获取跟Activity相关的各种资源。第二个问题中的获取其它Fragment页面中控件的引用也是在onActivityCreated()中来做的。先看看在onActivityCreated()中如何获得自己视图中控件的引用吧

public void onActivityCreated(Bundle savedInstanceState) {  super.onActivityCreated(savedInstanceState);  listView = (ListView) getView().findViewById(R.id.list);//获取自己视图里的控件引用,方法二
}

然后,获得其它Fragment页面中控件的引用的方法
在上面已经说了,要获取Activity中的资源,就必须等Acitivity创建完成以后,所以必须放在onActivityCreated()回调函数中。
其获取方法为:

public void onActivityCreated(Bundle savedInstanceState) {  super.onActivityCreated(savedInstanceState);  mFragment2_tv = (TextView) getActivity().findViewById(R.id.fragment2_tv);//获取其它fragment中的控件引用的唯一方法!!!  }

上面讲了一堆之后,下面就看看在Fragment1中如何实现的吧。
由上面的讲述可知,无论是获取自己视图中控件的引用还是获取其它fragment中控件的引用都可以放在onActivityCreated()函数中,所以我们就把它们全部放在onActivityCreated()中来实现了。

public void onActivityCreated(Bundle savedInstanceState) {  super.onActivityCreated(savedInstanceState);  mFragment2_tv = (TextView) getActivity().findViewById(R.id.fragment2_tv);//获取其它fragment中的控件引用的唯一方法!!!  listView = (ListView) getView().findViewById(R.id.list);//获取自己视图里的控件引用,方法二  ArrayAdapter arrayAdapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, mStrings);  listView.setAdapter(arrayAdapter);  listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {  @Override  public void onItemClick(AdapterView<?> parent, View view, int position, long id) {  String str = mStrings[position];  mFragment2_tv.setText(str);  }  });
}

难度不大,也是获取到了每个控件以后,直接对他们进行操作。

源码在文章底部给出

我们这里直接在fragment1中操作了fragment2的控件,这样就违背了模块分离的思想,我们应该让他们各自处理各自的代码才好。所以,考虑到将他们分离,我们这里就出现了方法三。

方法三:在各自的fragment中操作

好,我们先想想要怎么解决这个问题,首先,我们把各自的事件放在各自的fragment中处理,即在fragment1中能得到当前用户点击的ITEM的String字符串,在fragment2中可以设置textview的值。那问题来了,各自获得了各自的东东,那通过什么让他们交互呢?
答案显然是activity。
很显然,在activity中可以直接通过FragmentManager::findFragmentById()来获取fragment2的实例。进而调用fragment2中的任意方法,这就实现了与fragment2的通信。
那fragment1又怎么把结果回传给Activity呢?大家如果在看到这里之前先看了《Fragment跳转时传递参数及结果回传的方法》就很容易想到,用回调!请记住。在不同页面中回传结果,回调是万能的解决方案。
1、Fragment2设置textView函数:
先看个简单的,fragment2中的处理代码:

public class Fragment2 extends Fragment {  private TextView mTv;  …………  public void setText(String text) {  mTv.setText(text);  }
}

2、Fragment1中的处理方式:
(1)、定义接口及变量
由于是用回调,所以要先定义一个接口及对应的变量:

private titleSelectInterface mSelectInterface;  public interface titleSelectInterface{  public void onTitleSelect(String title);
}

(2)、接口变量赋值
接口是给activity用的,所以要在activity中给这里的接口变量赋值,可以有很多方法,当然可以选择写一个setXXX()函数来赋值,但如果用户忘了怎么办?所以我们要强制用户赋值。所以采用强转的方式,在fragment与activity相关联时,进行强转赋值:

public void onAttach(Activity activity) {  super.onAttach(activity);  try {  mSelectInterface = (titleSelectInterface) activity;  } catch (Exception e) {  throw new ClassCastException(activity.toString() + "must implement OnArticleSelectedListener");  }
}

采用强转的方式的问题在于,如果用户的activity没有implements titleSelectInterface,就会抛出错误,所以在调试过程中就会发现。
(3)、调用接口变量
下一步就是在fragment1中在用户点击listView的item的时候,将结果回传给Activity了,代码如下:

public void onActivityCreated(Bundle savedInstanceState) {  super.onActivityCreated(savedInstanceState);  listView = (ListView) getView().findViewById(R.id.list);//获取自己视图里的控件引用,方法二  ArrayAdapter arrayAdapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, mStrings);  listView.setAdapter(arrayAdapter);  listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {  @Override  public void onItemClick(AdapterView<?> parent, View view, int position, long id) {  String str = mStrings[position];  mSelectInterface.onTitleSelect(str);  }  });
}

(4)、在Activity中实现titleSelectInterface接口
首先是MainActivity必须实现titleSelectInterface接口,然后结果会在onTitleSelect(String title)中返回,在结果返回后利用fragment2.setText()操作textView;代码如下:

public class MainActivity extends FragmentActivity implements Fragment1.titleSelectInterface {  ……  @Override  public void onTitleSelect(String title) {  FragmentManager manager = getSupportFragmentManager();  Fragment2 fragment2 = (Fragment2)manager.findFragmentById(R.id.fragment2);  fragment2.setText(title);  }
}

在上面代码中可以看出,在结果返回后,通过findFragmentById()来获得fragment2的实例,这里首次出现了findFragmentById()函数的用法,这个函数主要用来静态添加的fragment中,通过fragment的ID值来获取它的实例。在获得fragment2的实例以后,通过调用我们写好了setText()方法来将结果显示在textView中。

Fragment2 fragment2 = (Fragment2)manager.findFragmentById(R.id.fragment2);

转载于:https://www.cnblogs.com/cuishuang/p/5728245.html

Fragment-传递参数相关推荐

  1. Android开发之fragment传递参数的两种方法

    非常简单一种是通过bundle,另外一种是通过fragment提供的instantiate(过时方法),都是kotlin版本,直接上代码吧: 方法一: //fragment传递参数方法一val fra ...

  2. android fragment传递参数_fragment之间传值的两种方法

    在Activity中加载Fragment的时候.有时候要使用多个Fragment切换.并传值到另外一个Fragment.也就是说两个Fragment之间进行参数的传递.查了很多资料.找到两种方法.一种 ...

  3. Android Fragment传递参数Fragment.setArguments(Bundle bundle)

    Fragment在Android3.0开始提供,并且在兼容包中也提供了Fragment特性的支持.Fragment的推出让我们编写和管理用户界面更快捷更方便了. 但当我们实例化自定义Fragment时 ...

  4. Android解惑 - 为什么要用Fragment.setArguments(Bundle bundle)来传递参数

     Android解惑 - 为什么要用Fragment.setArguments(Bundle bundle)来传递参数 时间 2014-04-19 23:05:55 CSDN博客 原文  http ...

  5. Bundle与Intent机制,Intent显式/隐式意图,传递参数及参数序列化,各种跳转(如打开浏览器),Intent的Size

    intent传递有没有大小限制,是多少?- http://blog.csdn.net/wingichoy/article/details/50679322 Android Intent调用 Uri的使 ...

  6. Fragment传递数据

    文章目录 Fragment与Activity之间 Activity向Fragment传递数据 通过构造方法的参数传递 代码示例 Fragment对外提供设置数据的方法,也就是public类型的方法 代 ...

  7. HarmonyOS 界面跳转以及界面跳转的同时传递参数

    HarmonyOS 不带参数界面之间跳转 package com.example.myapplication.slice; import com.example.myapplication.Resou ...

  8. 【Qt】信号和槽对值传递参数和引用传递参数的总结

    在同一个线程中 当信号和槽都在同一个线程中时,值传递参数和引用传递参数有区别: 值传递会复制对象:(测试时,打印传递前后的地址不同) 引用传递不会复制对象:(测试时,打印传递前后的地址相同) 不在同一 ...

  9. python获取当前进程id_Python进程,多进程,获取进程id,给子进程传递参数操作示例...

    本文实例讲述了Python进程,多进程,获取进程id,给子进程传递参数操作.分享给大家供大家参考,具体如下: 线程与线程之间共享全局变量,进程之间不能共享全局变量. 进程与进程相互独立  (可以通过s ...

  10. ref和out 传递参数(C#)

    1.参数传递默认都是传递栈空间里面存储的内容 2.如果添加了ref那么传递的都是栈空间地址,而不再是栈空间里面的内容 3.如果添加了out,那么传递的也是栈空间的地址 1 //写一个方法计算一个int ...

最新文章

  1. mysql5.7文本编辑器_Windows下mysql-5.7.28下载、安装、配置教程
  2. boost::intrusive_ref_counter相关的测试程序
  3. 适配器模式在Mybatis中的妙用
  4. java servlet 3.1,Servlet 3.1规范学习小记
  5. 统计自然语言处理基础_聚类
  6. 3个开源TTS(四)eSpeak1.06的源码调试环境vim+vimgdb
  7. eclipse上windowsbuilder 安装
  8. 从苏宁电器到卡巴斯基第22篇:单证这一年(下)
  9. Cannot use the diamond generic notation when running in JDK inferior to 1.7 mode
  10. STM32驱动0.96寸OLED屏幕
  11. 网络字节序与主机字节序的转换 - HEN_MAN的专栏 - 博客频道 - CSDN.NET
  12. 工程师思维是什么?芯片工程师要有哪些思维习惯?
  13. 网页设计配色应用实例剖析——黄色系
  14. opencv(c++)------图像分割(阙值、自适应阙值、grabCut、floodfill、wathershed)
  15. vmwaretools与open-vm-tools都无法使用的解决方法
  16. 导出excel时,弹出的下载窗口一闪而过
  17. 购买了虚拟主机还要云服务器,购买了虚拟主机还要云服务器
  18. 【ansj分词,英文被转换为了小写】
  19. Python:根据身高、体重计算BMI指数
  20. 微积分小课堂:微分(从宏观变化了解微观趋势)

热门文章

  1. Windows10下VB6.0开发——常用的字符串处理函数工具
  2. angular语言前端开发_详解使用angular-cli发布i18n多国语言Angular应用_唇印_前端开发者...
  3. 免费WiFi初体验——个小白的WiFi旅程
  4. 线程管理(一)线程的创建和运行
  5. 网站性能测试工具Apache Benchmark的使用说明
  6. MPLS ×××中Cisco和华为配置需求不同点
  7. cnblogs 博客园模板技巧
  8. 水晶报表2008部署
  9. [转帖]Beyond Compare如何进行二进制比较
  10. $.ajax与$.post、$.get的区别