Fragment ——第四步 传值
在关Fragment间参数的传递,有两种情况:
- 第一种情况:同一个container中不同fragment间的参数传递。这种情况一般发生在fragment跳转时,上一个Fragment将参数传递给下一个Fragment。
- 第二种情况:是同一个Activity中,不个container间Fragment的参数传递。
有关第一种情况,以前写过一篇文章,详细说明了上一个Fragment将参数传递给下一个Fragment,及数据回传的方法。详细参见: 《Fragment跳转时传递参数及结果回传的方法》
下面详细看看这两种参数传递方法。
一、同一个container间的参数传递。
有关这个问题,请大家移步以前写的一篇文章:《Fragment跳转时传递参数及结果回传的方法》,在这篇文章中有关Fragment跳转时的参数传递和结果回传已经讲的很清楚了,这里就没必要重新再写一遍,下面是这篇文章的效果图:
- 1、在界面开始时,点击“加载第二个Fragment”按钮
- 2、调起Fragment2,并向其传递一个参数“从Fragment1传来的参数”,显示在Fragment2中
- 3、点击Fragment2中的四个小动物中的一个,会向Fragment1回传用户点击的是哪个动物,在Fragment1中显示出来。
看起来挺有意思?那就移步到这篇文章里看看吧
二、同一个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);
Fragment ——第四步 传值相关推荐
- 如何优雅的实现 Activity、Fragment 相互之间的 Bundle 传值
1.简介 从事过 Android 开发的同学,肯定遇到过 Activity 与 Activity 间的 Bundle 传值,或者 Activity 与 Fragmnet 中的 Bundle 传值,或者 ...
- 云信小课堂丨简单四步,快速搭建协同办公系统!
Vol. 8 企业作为社会分工参与的主体,在自身发展以及内部协作中,势必会涉及到各类自有技术和商业信息的互动与交流,而这类信息由于有着高度的保密性和隐私性,所以如微信.QQ 等通用的即时通讯工具很难满 ...
- android glide加载不出图片_Glide实现共享元素无缝转场效果,只需四步!
原文: How to Use Shared Element Transition with Glide in 4 steps 作者:Bartłomiej Osmałek 读完这篇文章, 你就会知道使用 ...
- android 转场动画 共享元素,关于android:四步通过Glide实现共享元素无缝转场效果...
读完这篇文章, 你就会晓得应用Glide等图片加载库实现共享元素转场成果,以及如何解决各种可能加载状态.通过共享转场动画,能够晋升利用交互体验,让用户应用起来更愉悦. 共享元素转场成果是Materia ...
- 简单四步,快速判断真菌是否成功侵染宿主植物
撰文 | 同同 涉及植物研究的小伙伴们应该对于真菌植物共生都有所了解,根瘤菌和大豆的共生就是教科书级别的经典案例.植物与真菌的共生作为农业生产中一种重要的共生关系,一直是农业科研工作者的研究热点. ...
- 大佬教你修改pycharm编辑器 简单的四步教你搞定界面风格修改
教你配置属于自己的PYcharm界面色彩风格,PYthon学习必备 GO 第一步,换成深色背景,保护视力 PyCharm默认的背景是白色的,比较刺眼.还是换成深色的比较好,而且感觉比较酷一点. 修改方 ...
- 在深谈TCP/IP三步握手四步挥手原理及衍生问题—长文解剖IP
如果对网络工程基础不牢,建议通读<细说OSI七层协议模型及OSI参考模型中的数据封装过程?> 下面就是TCP/IP(Transmission Control Protoco/Interne ...
- excel筛选排序从小到大_数据横向排序和筛选,Ctrl+F搭配通配符quot;*quot;,只需简单四步完成...
数据的排序和筛选,相信大家都有操作过.但我们在利用Excel表格进行数据排序筛选的时候,基本都是数据的纵向操作,也就是按列的方式进行数据操作.今天我们就来学习一下,如何对数据进行横向的排序和筛选. 如 ...
- java web每天定时执行任务(四步轻松搞定)
第一步: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 ...
最新文章
- NumberOf1Bits(leetcode191)
- 正则表达式手机固话php,手机和固话正则的记忆方法
- 中班音乐计算机反思,中班歌曲《不再麻烦好妈妈》活动反思
- TVP5158的多路复用技术
- 美国国家公路交通安全管理局对特斯拉Autopilot系统展开正式调查
- netty 关闭chnnal_Netty 源码学习——服务端流程分析
- Scala的所有符号运算符都意味着什么?
- ZT: Delphi编程规范1.0.0.0 (yckxzjj )
- 关于“Windows无法验证设备所需的驱动程序的数字签名”错误的解决方法
- 什么是人工智能(AI)数据平台?
- WordPress插件曝出零日漏洞,已被积极在野利用
- 群晖NAS存储空间损毁 硬盘损毁处理
- studio3下载安装使用
- SEED LABS初入
- linux子进程崩溃父进程如何得知并重启子进程,子进程崩溃父进程如何得知并重启子进程...
- #1353 : 满减优惠(01背包变形)
- android常用的存储方式,Android 常见数据存储方式
- JAVA:实现PerfectCube完美立方公式算法(附完整源码)
- 编程实现多边形的平移、比例(缩放)、旋转、对称和错切等二维仿射变换(大有门道)
- 【Get深一度】相控阵-FDA设计思路-相控阵雷达原理