Android在片段之间传递数据

时间:2020-02-23 14:29:08  来源:igfitidea点击:

在本教程中,我们将开发一个包含TabLayout,ViewPager和Fragments的应用程序。
我们将实现一项功能,将数据从一个片段传递到另一个片段。

Android在片段之间传递数据

意图仅可用于在活动级别上发送数据。
为了在片段之间传递数据,我们需要创建自己的接口。
下面显示了将String数据从一个Fragment发送到另一个Fragment的流程。

让我们开始执行上述流程。

Android在片段项目结构之间传递数据

MainActivity.java类的xml布局如下。

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="https://schemas.android.com/apk/res/android"
  xmlns:app="https://schemas.android.com/apk/res-auto"
  xmlns:tools="https://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:fitsSystemWindows="true"
  tools:context="com.theitroad.passingdatabetweenfragments.MainActivity">

  <android.support.design.widget.AppBarLayout
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:theme="@style/AppTheme.AppBarOverlay">

      <android.support.v7.widget.Toolbar
          android:id="@+id/toolbar"
          android:layout_width="match_parent"
          android:layout_height="?attr/actionBarSize"
          android:background="?attr/colorPrimary"
          app:popupTheme="@style/AppTheme.PopupOverlay" 

      <android.support.design.widget.TabLayout
          android:id="@+id/tabs"
          style="@style/MyStyle"
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          app:tabGravity="fill"
          app:tabMode="fixed" 

  </android.support.design.widget.AppBarLayout>

  <android.support.v4.view.ViewPager
      android:id="@+id/viewPager"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      app:layout_behavior="@string/appbar_scrolling_view_behavior" 

</android.support.design.widget.CoordinatorLayout>

TabLayout和ToolBar的样式在styles.xml文件中定义,如下所示。

<resources>

  <!-- Base application theme. -->
  <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
      <!-- Customize your theme here. -->
      <item name="colorPrimary">@color/colorPrimary</item>
      <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
      <item name="colorAccent">@color/colorAccent</item>
  </style>

  <style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" 

  <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" 

  <style name="MyStyle" parent="Widget.Design.TabLayout">
      <item name="tabIndicatorColor">#FFFF</item>
      <item name="tabIndicatorHeight">5dp</item>
      <item name="tabPaddingStart">8dp</item>
      <item name="tabPaddingEnd">8dp</item>
  </style>

</resources>

ViewPagerAdapter.java是片段的初始化位置。
代码如下。

public class ViewPagerAdapter extends FragmentPagerAdapter {

  public ViewPagerAdapter(FragmentManager fm) {
      super(fm);
  }

  @Override
  public Fragment getItem(int position) {
      Fragment fragment = null;
      if (position == 0) {
          fragment = new FragmentOne();
      } else if (position == 1) {
          fragment = new FragmentTwo();
      }
      return fragment;
  }

  @Override
  public int getCount() {
      return 2;
  }

  @Override
  public CharSequence getPageTitle(int position) {
      String title = null;
      if (position == 0) {
          title = "Tab-1";
      } else if (position == 1) {
          title = "Tab-2";
      }
      return title;
  }
}

FragmentOne会将在EditText中输入的数据发送到FragmentTwo。

下面给出fragment_one.xml的xml布局。

<?xml version="1.0" encoding="utf-8"?>

<ScrollView xmlns:android="https://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:fillViewport="true">

  <RelativeLayout
      android:layout_width="match_parent"
      android:layout_height="wrap_content">

      <EditText
          android:id="@+id/inMessage"
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:layout_above="@+id/btnPassData"
          android:layout_margin="16dp"
          android:hint="Enter here" 

      <Button
          android:id="@+id/btnPassData"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:layout_centerInParent="true"
          android:text="PASS DATA TO FRAGMENT TWO" 

  </RelativeLayout>
</ScrollView>

以下给出fragment_two.xml的xml布局。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent">

  <TextView
      android:id="@+id/txtData"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:textSize="20sp"
      android:layout_centerInParent="true"
      android:text="No data received" 

</RelativeLayout>

FragmentOne.java类的代码如下。

package com.theitroad.passingdatabetweenfragments;

import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;

public class FragmentOne extends Fragment {

  SendMessage SM;

  @Nullable
  @Override
  public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
      View rootView = inflater.inflate(
              R.layout.fragment_one, container, false);
      return rootView;

  }

  @Override
  public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
      super.onViewCreated(view, savedInstanceState);

      Button btnPassData = (Button) view.findViewById(R.id.btnPassData);
      final EditText inData = (EditText) view.findViewById(R.id.inMessage);
      btnPassData.setOnClickListener(new View.OnClickListener() {
          @Override
          public void onClick(View v) {
              SM.sendData(inData.getText().toString().trim());
          }
      });

  }

  interface SendMessage {
      void sendData(String message);
  }

  @Override
  public void onAttach(Context context) {
      super.onAttach(context);

      try {
          SM = (SendMessage) getActivity();
      } catch (ClassCastException e) {
          throw new ClassCastException("Error in retrieving data. Please try again");
      }
  }
}

自定义接口SendMessage是在上面的onAttach方法中初始化的。
该接口将在我们即将看到的MainActivity.java中实现。

FragmentTwo.java类的代码如下。

package com.theitroad.passingdatabetweenfragments;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class FragmentTwo extends Fragment {

  TextView txtData;

  @Nullable
  @Override
  public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
      View rootView = inflater.inflate(
              R.layout.fragment_two, container, false);
      return rootView;
  }

  @Override
  public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
      super.onViewCreated(view, savedInstanceState);

      txtData = (TextView)view.findViewById(R.id.txtData);
  }

  protected void displayReceivedData(String message)
  {
      txtData.setText("Data received: "+message);
  }
}

如下所示,将从MainActivity.java中自定义接口的方法内部的FragmentTwo.java实例上调用" displayReceivedData()"。

package com.theitroad.passingdatabetweenfragments;

import android.support.design.widget.TabLayout;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;

public class MainActivity extends AppCompatActivity implements FragmentOne.SendMessage{

  TabLayout tabLayout;
  ViewPager viewPager;
  ViewPagerAdapter viewPagerAdapter;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
      setSupportActionBar(toolbar);

      viewPager = (ViewPager) findViewById(R.id.viewPager);
      viewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager());
      viewPager.setAdapter(viewPagerAdapter);
      tabLayout = (TabLayout) findViewById(R.id.tabs);
      tabLayout.setupWithViewPager(viewPager);
  }

  @Override
  public void sendData(String message) {
      String tag = "android:switcher:" + R.id.viewPager + ":" + 1;
      FragmentTwo f = (FragmentTwo) getSupportFragmentManager().findFragmentByTag(tag);
      f.displayReceivedData(message);
  }
}

一旦按下FragmentOne中的Button,就会触发上述代码中的sendData()方法。
我们使用findFragmentByTag方法获取在ViewPagerAdapter中已经初始化的FragmentTwo。