MainActivity和ViewPager中的多个Fragment通信问题

版权声明:本博客属个人原创,转载请注明。 https://blog.csdn.net/qq_33198758/article/details/82762655

一、MainActivity和单个Fragment通信

Activity和单个Fragment通信,非常简单,用接口回调的方法,很容易实现。具体可参见链接。但是对于Activity和多个Fragment之间的通讯,提及较少。下面讲一讲如何实现Activity和多个Fragment通讯。

二、MainActivity和多个Fragment通信

上一节已经实现了多个Fragment的滚动。

1、多个Fragment将信息传给Activity

第一步

上一节的基础上给三个Fragment:Fragment_Control、 Fragment_Oversee、Fragment_ConnectDevice分别添加三个按钮,ID分别为:button_control_send 、button_see_send 、button_connect_send 。再给三个Fragment分别添加接口:
Fragment_Control

package com.example.dx.testviewpager;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;

/**
 * Created by dx on 2018/9/8.
 */
public class Fragment_Control extends Fragment implements View.OnClickListener {
    private Button control_send;
    private onControlSend2Activity controlSend2Activity ;
    public View onCreateView(LayoutInflater inflater , ViewGroup container, Bundle savedInstanceState){
        View view=inflater .inflate(R.layout .activity_control ,container,false) ;
        control_send =(Button)view.findViewById(R.id.button_control_send ) ;
        control_send .setOnClickListener(this) ;
        return view;
    }
    //接口
    interface onControlSend2Activity
    {
        public void receiveDataFromControl(String content,int whichFragment);
    }
    //接口监听
    public void setOnConnectSend2ActivityListener(onControlSend2Activity on){
        this.controlSend2Activity =on;
    }
    @Override
    public void onClick(View v )
    {
        if(v.getId() ==R.id.button_control_send )
        {
            String content="我来自Fragment_Control";
            this.controlSend2Activity .receiveDataFromControl(content,0) ;//触发
        }
    }
}

Fragment_Oversee:

package com.example.dx.testviewpager;


import android.os.Bundle;
import android.support.v4.app.Fragment;

import android.view.LayoutInflater;

import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;

/**
 * Created by dx on 2018/9/8.
 */
public class Fragment_Oversee  extends Fragment implements View.OnClickListener   {
 private Button see_Send;
    public onSeeSend2Activity seeSend2Activity ;
    public View onCreateView(LayoutInflater inflater , ViewGroup container, Bundle savedInstanceState){
        View view=inflater .inflate(R.layout .activity_see ,container,false) ;
        see_Send =(Button)view.findViewById(R.id.button_see_send ) ;
        see_Send .setOnClickListener(this) ;
        return view;
    }

    //接口
    interface onSeeSend2Activity
    {
        public void receiveDataFromSee(String content,int whichFragment);
    }
    //接口监听
    public void setOnConnectSend2ActivityListener(onSeeSend2Activity on){
        this.seeSend2Activity =on;
    }

    @Override
   public void onClick(View v )
   {
       if(v.getId() ==R.id.button_see_send )
       {
           String content="我来自Fragment_Oversee";
           this.seeSend2Activity .receiveDataFromSee(content,1) ;//触发
       }

   }

}

Fragment_ConnectDevice:

package com.example.dx.testviewpager;


import android.os.Bundle;
import android.support.v4.app.Fragment;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;


/**
 * Created by dx on 2018/9/10.
 */
public class Fragment_ConnectDevice extends Fragment implements View .OnClickListener  {
    private Button connect_send;
public onConnectSend2Activity connectSend2Activity ;
    public View onCreateView(LayoutInflater inflater , ViewGroup container, Bundle savedInstanceState){
        View view=inflater .inflate(R.layout .activity_connect  ,container,false) ;
        connect_send =(Button )view.findViewById(R.id.button_connect_send ) ;
        connect_send .setOnClickListener(this) ;
        return view;
    }

    //接口
    interface onConnectSend2Activity
    {
      public void receiveDataFromConnect(String content,int whichFragment);
    }
    //接口监听
    public void setOnConnectSend2ActivityListener(onConnectSend2Activity on){
        this.connectSend2Activity =on;
    }

    @Override
   public void onClick(View v)
  {
     if(v.getId() ==R.id.button_connect_send )
     {
         String content="我来自Fragment_ConnectDevice";
         this.connectSend2Activity .receiveDataFromConnect(content,2) ;//触发
     }
   }

}

第二步

照常理,应该是在MainActivity中实现三个Fragment的接口,并且给三个Fragment注册监听事件,但问题在于,如何获得当前的Fragment?又如何给它注册监听事件呢?
网上有一种获得当前Fragment的方法,参考。获取到当前Fragment后,给它注册监听。想到了在 onPageSelected(int arg0) 函数中根据选中的Fragment注册相应的监听事件。事实上,我也这样试过了,然后发现程序闪退。
那出现了什么问题呢?后来查阅资料发现,我们获取当前Fragment的setPrimaryItem()函数在onPageSelected()函数之后执行,也就是说在onPageSelected(int arg0) 中找到的Fragment对象是滑动之前的。
那么有什么其他方法可以给Fragment动态注册监听事件呢?下面我提供一种方法:setPrimaryItem()函数是每次切换Fragment都会执行的,因此可以通过回调监听这个函数,并且把当前Fragment参数给传递出去。

package com.example.dx.testviewpager;

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.view.ViewGroup;

import java.util.List;

/**
 * Created by dx on 2018/9/18.
 */
public class TabFragmentPagerAdapter extends FragmentPagerAdapter  {
    private FragmentManager mfragmentManager;
    private List<Fragment> mlist;
    public Fragment currentFragment;
    private OnFragmentChangedListener onFragmentChangedListener ;

    /**
     *  定义回调接口,我们监听setPrimaryItem()中的position,就是切换的fragment
     */
    public interface OnFragmentChangedListener {

        public void onFragmentChanged(int pos);
    }
    /**
    *设置监听函数
     */
    public void setOnFragmentChangedListener (OnFragmentChangedListener onFragmentChangedListener )
    {
        this.onFragmentChangedListener =onFragmentChangedListener ;
    }
    public TabFragmentPagerAdapter(FragmentManager fm, List<Fragment> list) {
        super(fm);
        this.mlist = list;
    }

    @Override
    public void setPrimaryItem(ViewGroup container, int position, Object object) {
        this.currentFragment= (Fragment) object;
        onFragmentChangedListener .onFragmentChanged(position ) ;//触发监听,将position传递出去
        super.setPrimaryItem(container, position, object);
    }


    @Override
    public Fragment getItem(int arg0) {
        return mlist.get(arg0);//显示第几个页面
    }

    @Override
    public int getCount() {
        return mlist.size();//有几个页面
    }
}


第二步

在MainActivity里注册监听,并且重写接口的实现方法。代码很长,但是关键部分都有注释。

package com.example.dx.testviewpager;

import android.graphics.Color;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Gravity;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity implements Fragment_Control .onControlSend2Activity,Fragment_ConnectDevice .onConnectSend2Activity ,Fragment_Oversee .onSeeSend2Activity, TabFragmentPagerAdapter .OnFragmentChangedListener{
    private List<Fragment> list;
    private ViewPager myViewPager;
    private TabFragmentPagerAdapter adapter;

    private TextView  text_Control;
    private TextView  text_Oversee;
    private TextView  text_connectDevice;
    private TextView  topTitle;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }
    private void initView()
    {
        text_Control=(TextView)  findViewById(R.id.textView_control ) ;
        text_Oversee =(TextView)  findViewById(R.id.textView_oversee ) ;
        text_connectDevice =(TextView)  findViewById(R.id.textView_connectDevice  ) ;
        topTitle =(TextView)  findViewById(R.id.textView_topTitle ) ;

        myViewPager = (ViewPager) findViewById(R.id.myViewPager);
        //绑定点击事件
        myViewPager.setOnPageChangeListener(new MyPagerChangeListener()) ;
        //把Fragment添加到List集合里面
        list = new ArrayList<>();
        list.add(new Fragment_Control() );
        list.add(new Fragment_Oversee() );
        list.add(new Fragment_ConnectDevice() );
        adapter = new TabFragmentPagerAdapter(getSupportFragmentManager(), list);
        myViewPager.setAdapter(adapter);
        myViewPager.setCurrentItem(1);  //初始化显示第一个页面
        adapter .setOnFragmentChangedListener(this) ;//给adapter注册监听事件
    }

    /**
     * 设置一个ViewPager的侦听事件,当左右滑动ViewPager时菜单栏被选中状态跟着改变
     *
     */
    public class MyPagerChangeListener implements ViewPager.OnPageChangeListener {

        @Override
        public void onPageScrollStateChanged(int arg0) {
        }

        @Override
        public void onPageScrolled(int arg0, float arg1, int arg2) {
        }


        @Override
        public void onPageSelected(int arg0) {
            switch (arg0) {
                case 0:

                    text_Control  .setTextColor(Color.GREEN  );
                    text_Oversee  .setTextColor(Color.BLACK );
                    text_connectDevice   .setTextColor(Color.BLACK );
                    topTitle .setText("手动控制") ;

                    break;
                case 1:
                    text_Control .setTextColor(Color.BLACK );
                    text_Oversee .setTextColor(Color.GREEN );
                    text_connectDevice  .setTextColor(Color.BLACK );
                    topTitle .setText("数据监控") ;

                    break;
                case 2:
                    text_Control .setTextColor(Color.BLACK );
                    text_Oversee .setTextColor(Color.BLACK  );
                    text_connectDevice  .setTextColor(Color.GREEN );
                    topTitle .setText("连接设备") ;
                    break;
            }

        }

    }
    //监听当前Fragment,并且初始化
    @Override
    public void onFragmentChanged(int pos){
        switch(pos) {
            case 0:

                Fragment_Control fc1 = (Fragment_Control) ((TabFragmentPagerAdapter) myViewPager.getAdapter()).currentFragment;
                if (fc1 == null) {
                    Toast toast1 = Toast.makeText(getApplicationContext(),
                            "未获取到当前的Fragment"+String .valueOf(pos) , Toast.LENGTH_LONG);
                    toast1.setGravity(Gravity.CENTER, 0, 0);
                    toast1.show();
                } else {

                    fc1.setOnControlSend2ActivityListener(this) ;
                }

                break;
            case 1:
                Fragment_Oversee  fc2=(Fragment_Oversee)  ((TabFragmentPagerAdapter )myViewPager .getAdapter() ).currentFragment ;
                if(fc2==null)
                {
                    Toast toast1 = Toast.makeText(getApplicationContext(),
                            "未获取到当前的Fragment"+String .valueOf(pos), Toast.LENGTH_LONG);
                    toast1.setGravity(Gravity.CENTER, 0, 0);
                    toast1.show();
                }else{

                    fc2.setOnSeeSend2ActivityListener(this) ;
                }
                break;
            case 2:

                Fragment_ConnectDevice  fc3=(Fragment_ConnectDevice)  ((TabFragmentPagerAdapter )myViewPager .getAdapter() ).currentFragment ;
                if(fc3==null)
                {
                    Toast toast1 = Toast.makeText(getApplicationContext(),
                            "未获取到当前的Fragment"+String .valueOf(pos), Toast.LENGTH_LONG);
                    toast1.setGravity(Gravity.CENTER, 0, 0);
                    toast1.show();
                }else{

                    fc3.setOnConnectSend2ActivityListener(this) ;
                }
                break;
        }

    }
    //监听来自Fragment_control数据
    @Override
    public void receiveDataFromControl(String content,int whichFragment){
        Toast toast1 = Toast.makeText(getApplicationContext(),
                content, Toast.LENGTH_LONG);
        toast1.setGravity(Gravity.CENTER, 0, 0);
        toast1.show();
    }
    //监听来自Fragment_Oversee数据
    @Override
    public void receiveDataFromSee(String content,int whichFragment){
        Toast toast1 = Toast.makeText(getApplicationContext(),
                content, Toast.LENGTH_LONG);
        toast1.setGravity(Gravity.CENTER, 0, 0);
        toast1.show();
    }
    //监听来自Fragment_ConnectDevice数据
    @Override
    public void receiveDataFromConnect(String content,int whichFragment){
        Toast toast1 = Toast.makeText(getApplicationContext(),
                content, Toast.LENGTH_LONG);
        toast1.setGravity(Gravity.CENTER, 0, 0);
        toast1.show();
    }
}

实现效果:
在这里插入图片描述

2、Activity向多个Fragment传值

方法类似,这里只想提醒一下,在Fragment给MainActivity注册监听时:`

 MainActivity mainActivity =(MainActivity)  getActivity() ;
 mainActivity .setOnSendData2FragmentListener(new receiveData2Activity() ) ;//给MainActivity注册监听

用接口回调的方法传值,了解执行过程以后,其实很简单。

三、源码

源码。 提取码:v01o

猜你喜欢

转载自blog.csdn.net/qq_33198758/article/details/82762655
今日推荐