相關(guān)文章:
1、《Fragment詳解之一——概述》
2、《Fragment詳解之二——基本使用方法》
3、《Fragment詳解之三——管理Fragment(1)》
4、《Fragment詳解之四——管理Fragment(2)》
5、《Fragment詳解之五——Fragment間參數(shù)傳遞》
6、《Fragment詳解之六——如何監(jiān)聽fragment中的回退事件與怎樣保存fragment狀態(tài)》
在關(guān)Fragment間參數(shù)的傳遞,有兩種情況:
- 第一種情況:同一個(gè)container中不同fragment間的參數(shù)傳遞。這種情況一般發(fā)生在fragment跳轉(zhuǎn)時(shí),上一個(gè)Fragment將參數(shù)傳遞給下一個(gè)Fragment。
- 第二種情況:是同一個(gè)Activity中,不個(gè)container間Fragment的參數(shù)傳遞。
有關(guān)第一種情況,以前寫過一篇文章,詳細(xì)說明了上一個(gè)Fragment將參數(shù)傳遞給下一個(gè)Fragment,及數(shù)據(jù)回傳的方法。詳細(xì)參見:
《Fragment跳轉(zhuǎn)時(shí)傳遞參數(shù)及結(jié)果回傳的方法》
下面詳細(xì)看看這兩種參數(shù)傳遞方法。
一、同一個(gè)container間的參數(shù)傳遞。
有關(guān)這個(gè)問題,請(qǐng)大家移步以前寫的一篇文章:《Fragment跳轉(zhuǎn)時(shí)傳遞參數(shù)及結(jié)果回傳的方法》,在這篇文章中有關(guān)Fragment跳轉(zhuǎn)時(shí)的參數(shù)傳遞和結(jié)果回傳已經(jīng)講的很清楚了,這里就沒必要重新再寫一遍,下面是這篇文章的效果圖:
- 1、在界面開始時(shí),點(diǎn)擊“加載第二個(gè)Fragment”按鈕
- 2、調(diào)起Fragment2,并向其傳遞一個(gè)參數(shù)“從Fragment1傳來的參數(shù)”,顯示在Fragment2中
- 3、點(diǎn)擊Fragment2中的四個(gè)小動(dòng)物中的一個(gè),會(huì)向Fragment1回傳用戶點(diǎn)擊的是哪個(gè)動(dòng)物,在Fragment1中顯示出來。
看起來挺有意思?那就移步到這篇文章里看看吧
二、同一個(gè)Activity,不同container間的參數(shù)傳遞
這里到了這篇文章的重點(diǎn)內(nèi)容了哦,這可并不是說上一部分不重要哈,其實(shí)上一部分要比這部分重要!同一個(gè)container中不同F(xiàn)ragment間的參數(shù)傳遞一般的工程都會(huì)用到的,所以大家一定要看。而我這里不講,是因?yàn)橐郧坝兄v過,這里就沒必要再重復(fù)一遍了,好了,廢話說了好多……開整吧。
先看看效果圖:
1、在這個(gè)Actiivty中有兩個(gè)Fragment;
2、Fragment1中有一個(gè)listView,當(dāng)我們點(diǎn)擊ListView的Item的時(shí)候,把Item上的內(nèi)容更新到Fragment2上
這里有多種實(shí)現(xiàn)方法,最可取的是方法三。我們由簡(jiǎn)到易慢慢講。
我們想使兩個(gè)fragment實(shí)例要能通信,那如果我們都能通過findViewById()找到所有的控件,直接操控的話,豈不就實(shí)現(xiàn)了。而通過findViewById()能找到所有控件實(shí)例的地方就是在Activity中了,所以這就有了方法一。
方法一:直接在Activity中操作
在Activity中找到對(duì)應(yīng)的控件實(shí)例,然后直接操控即可。
先看看MainActivity的布局:activity_main.xml
[html] view plaincopy
<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>??
在這個(gè)布局中,橫向放兩個(gè)fragment,由于這里的fragment是靜態(tài)添加的,所以每個(gè)fragment都是有id值的,所以這時(shí)候如果我們要獲取某個(gè)fragment的實(shí)例,就可以通過FragmentManager::findFragmentById()來找到了。
然后是這兩個(gè)fragment的布局。
fragment1.xml:
[html] view plaincopy
<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的布局中,除了一個(gè)標(biāo)識(shí)當(dāng)前Fragment的TextView,就是一個(gè)listview;
fragment2.xml:
[html] view plaincopy
<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中非常干凈,只有一個(gè)TextView來顯示當(dāng)前用戶在fragment1中的點(diǎn)擊結(jié)果。
下面看看在MainActivity中是如何實(shí)現(xiàn)的吧
[java] view plaincopy
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]);??????????}??????});??}??
其中:
[java] view plaincopy
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,然后直接對(duì)他們進(jìn)行操作。即下面的代碼:
[java] view plaincopy
listView.setOnItemClickListener(new?AdapterView.OnItemClickListener()?{??????@Override??????public?void?onItemClick(AdapterView<?>?parent,?View?view,?int?position,?long?id)?{??????????mFragment2_tv.setText(mStrings[position]);??????}??});??
當(dāng)用戶點(diǎn)擊listView的一個(gè)item時(shí),將值setText到fragment2的textView中。
源碼在文章底部給出
可見,直接在activity中操作各個(gè)fragment的控件就可以實(shí)現(xiàn)消息互傳。但,這樣真的好嗎?如果每個(gè)fragment中的控件都在Activity中操作,那還要fragment干嘛!最最起碼,應(yīng)該每個(gè)fragment負(fù)責(zé)自己的控件操作才對(duì)嘛!
所以,我們對(duì)這種方法進(jìn)行改進(jìn),將點(diǎn)擊Item的賦值操作放到fragment1中去。所以,這就有方法二;
方法二:直接在fragment中操作
在這里我們會(huì)把所有方法寫在Fragment1中,這里涉及到兩方面的內(nèi)容:
第一:在Fragment中如何獲得自己控件的引用,比較這里Fragment1里的listview控件。
第二:在Fragment中如何獲得其它Fragment頁面中控件的引用,比如這里Fragment2里的TextView控件。
首先,獲取自己控件引用的方法:
方法一:在onCreateView()中獲取。
就比如這里獲取自己的listView控件的引用,代碼如下:
[java] view plaincopy
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()中,還沒有創(chuàng)建視圖,所以在這里如果使用getView()方法將返回空。所以如果要獲取其實(shí)圖中指定控件的引用,只用用inflater.inflate()返回的rootView;在這個(gè)rootView()中用findViewById來查找。
方法二:在onActivityCreated()函數(shù)中獲取。
從
《Fragment詳解之一——概述》的流程圖中可以看到,onActivityCreated()回調(diào)會(huì)在Activity的OnCreate()執(zhí)行完成后再執(zhí)行,也就是說,onActivityCreated()會(huì)在Activity的OnCreate()工作完成以后才會(huì)執(zhí)行。所以當(dāng)執(zhí)行到onActivityCreated()的時(shí)候Activity已經(jīng)創(chuàng)建完成,它其中的各個(gè)fragment也視圖等等的也都已經(jīng)創(chuàng)建完成。所在可以在這里獲取跟Activity相關(guān)的各種資源。第二個(gè)問題中的獲取其它Fragment頁面中控件的引用也是在onActivityCreated()中來做的。先看看在onActivityCreated()中如何獲得自己視圖中控件的引用吧
[java] view plaincopy
public?void?onActivityCreated(Bundle?savedInstanceState)?{??????super.onActivityCreated(savedInstanceState);????????listView?=?(ListView)?getView().findViewById(R.id.list);??}???
然后,獲得其它Fragment頁面中控件的引用的方法
在上面已經(jīng)說了,要獲取Activity中的資源,就必須等Acitivity創(chuàng)建完成以后,所以必須放在onActivityCreated()回調(diào)函數(shù)中。
其獲取方法為:
[java] view plaincopy
public?void?onActivityCreated(Bundle?savedInstanceState)?{??????super.onActivityCreated(savedInstanceState);????????mFragment2_tv?=?(TextView)?getActivity().findViewById(R.id.fragment2_tv);????}??
上面講了一堆之后,下面就看看在Fragment1中如何實(shí)現(xiàn)的吧。
由上面的講述可知,無論是獲取自己視圖中控件的引用還是獲取其它fragment中控件的引用都可以放在onActivityCreated()函數(shù)中,所以我們就把它們?nèi)糠旁趏nActivityCreated()中來實(shí)現(xiàn)了。
[java] view plaincopy
public?void?onActivityCreated(Bundle?savedInstanceState)?{??????super.onActivityCreated(savedInstanceState);????????mFragment2_tv?=?(TextView)?getActivity().findViewById(R.id.fragment2_tv);??????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);??????????}??????});??}??
難度不大,也是獲取到了每個(gè)控件以后,直接對(duì)他們進(jìn)行操作。
源碼在文章底部給出
我們這里直接在fragment1中操作了fragment2的控件,這樣就違背了模塊分離的思想,我們應(yīng)該讓他們各自處理各自的代碼才好。所以,考慮到將他們分離,我們這里就出現(xiàn)了方法三。
方法三:在各自的fragment中操作
好,我們先想想要怎么解決這個(gè)問題,首先,我們把各自的事件放在各自的fragment中處理,即在fragment1中能得到當(dāng)前用戶點(diǎn)擊的ITEM的String字符串,在fragment2中可以設(shè)置textview的值。那問題來了,各自獲得了各自的東東,那通過什么讓他們交互呢?
答案顯然是activity。
很顯然,在activity中可以直接通過FragmentManager::findFragmentById()來獲取fragment2的實(shí)例。進(jìn)而調(diào)用fragment2中的任意方法,這就實(shí)現(xiàn)了與fragment2的通信。
那fragment1又怎么把結(jié)果回傳給Activity呢?大家如果在看到這里之前先看了《Fragment跳轉(zhuǎn)時(shí)傳遞參數(shù)及結(jié)果回傳的方法》就很容易想到,用回調(diào)!請(qǐng)記住。在不同頁面中回傳結(jié)果,回調(diào)是萬能的解決方案。
1、Fragment2設(shè)置textView函數(shù):
先看個(gè)簡(jiǎn)單的,fragment2中的處理代碼:
[java] view plaincopy
public?class?Fragment2?extends?Fragment?{??????private?TextView?mTv;??????…………??????public?void?setText(String?text)?{??????????mTv.setText(text);??????}??}??
2、Fragment1中的處理方式:
(1)、定義接口及變量
由于是用回調(diào),所以要先定義一個(gè)接口及對(duì)應(yīng)的變量:
[java] view plaincopy
private?titleSelectInterface?mSelectInterface;?????public?interface?titleSelectInterface{??????public?void?onTitleSelect(String?title);??}??
(2)、接口變量賦值
接口是給activity用的,所以要在activity中給這里的接口變量賦值,可以有很多方法,當(dāng)然可以選擇寫一個(gè)setXXX()函數(shù)來賦值,但如果用戶忘了怎么辦?所以我們要強(qiáng)制用戶賦值。所以采用強(qiáng)轉(zhuǎn)的方式,在fragment與activity相關(guān)聯(lián)時(shí),進(jìn)行強(qiáng)轉(zhuǎn)賦值:
[java] view plaincopy
public?void?onAttach(Activity?activity)?{??????super.onAttach(activity);????????try?{??????????mSelectInterface?=?(titleSelectInterface)?activity;??????}?catch?(Exception?e)?{??????????throw?new?ClassCastException(activity.toString()?+?"must?implement?OnArticleSelectedListener");??????}??}??
采用強(qiáng)轉(zhuǎn)的方式的問題在于,如果用戶的activity沒有implements titleSelectInterface,就會(huì)拋出錯(cuò)誤,所以在調(diào)試過程中就會(huì)發(fā)現(xiàn)。
(3)、調(diào)用接口變量
下一步就是在fragment1中在用戶點(diǎn)擊listView的item的時(shí)候,將結(jié)果回傳給Activity了,代碼如下:
[java] view plaincopy
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中實(shí)現(xiàn)titleSelectInterface接口
首先是MainActivity必須實(shí)現(xiàn)titleSelectInterface接口,然后結(jié)果會(huì)在onTitleSelect(String title)中返回,在結(jié)果返回后利用fragment2.setText()操作textView;代碼如下:
[java] view plaincopy
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);??????}??}??
在上面代碼中可以看出,在結(jié)果返回后,通過findFragmentById()來獲得fragment2的實(shí)例,這里首次出現(xiàn)了findFragmentById()函數(shù)的用法,這個(gè)函數(shù)主要用來靜態(tài)添加的fragment中,通過fragment的ID值來獲取它的實(shí)例。在獲得fragment2的實(shí)例以后,通過調(diào)用我們寫好了setText()方法來將結(jié)果顯示在textView中。
[java] view plaincopy
Fragment2?fragment2?=?(Fragment2)manager.findFragmentById(R.id.fragment2);??
OK啦,到這里這篇文章就結(jié)束啦,源碼過來啦。
參考文章:
1、《android Fragments詳解五:與activity通訊》?
2、《Inter-Fragment Communication》
總結(jié)
以上是生活随笔為你收集整理的Fragment详解之五——Fragment间参数传递的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。