如何在viewpager中的片段之间传递数据?

时间:2016-06-07 16:19:52

标签: android xamarin xamarin.android

有一个tabLayout和ViewPager。 所以我想将数据从fragment1传递给fragment2。

注意:fragment1 vs fragment2位于VIewPager中。所以我不能按照正常的方式传递数据。

FragmentTransaction fragmentTx=this.FragmentManager.BeginTransaction();
            TracksByGenres fragTrack=new TracksByGenres();
            fragTrack.AddData(items[e.Position]);
            //get our item from listview

            fragmentTx.Replace(Resource.Id.fragmentContainer,fragTrack);    
            fragmentTx.AddToBackStack(null);
            fragmentTx.Commit();

6 个答案:

答案 0 :(得分:3)

使用sharedPreferences

SharedPreferences sharedpreferences;
public static final String MyPREFERENCES = "MyPrefs" ;
sharedpreferences = getSharedPreferences(MyPREFERENCES, Context.MODE_PRIVATE);

保存价值

SharedPreferences.Editor editor = sharedpreferences.edit();
editor.putString("TAG_NAME", "value");
editor.commit();

从首选项中检索数据:在第二个片段中

public static final String MyPREFERENCES = "MyPrefs" ;
SharedPreferences prefs = getSharedPreferences(MyPREFERENCES , MODE_PRIVATE); 
String restoredText = prefs.getString("TAG_NAME", null);

答案 1 :(得分:2)

您可以使用界面。

public interface DataBoy{
    public void bigDog(Data data);
}

内部片段1:

DataBoy dataBoy = (DataBoy)getActivity().getSupportFragmentManager().findFragmentById(R.id.fragment2);

dataBoy.bigDog(data);

在片段2中:

fragment2 implements DataBoy {
...

@Override
public void bigDog(Data data);
doSomethingWith(data);
}

答案 2 :(得分:1)

最好的方法是使用 SharedPreferences

为此,我们需要像这样定义和初始化SharedPreferences

SharedPreferences preferences;
public static final String MY_SHARED_PREFERENCES = "MySharedPrefs" ;
preferences = getSharedPreferences(MY_SHARED_PREFERENCES, Context.MODE_PRIVATE);

为了节省价值,请使用以下代码。

SharedPreferences.Editor editor = preferences.edit();
editor.putString("YOUR_TAG_NAME", "value");
editor.commit();

要从Second片段中的SharedPreferences中检索数据,请使用下面的代码

public static final String MY_SHARED_PREFERENCES = "MySharedPrefs" ;
SharedPreferences myPreferences = getSharedPreferences(MY_SHARED_PREFERENCES , MODE_PRIVATE); 
String restoredText = myPreferences.getString("YOUR_TAG_NAME", null);

您也可以使用以下方式在片段之间传递数据,但是这个方法有点单调乏味,如果您有大量数据要求转移到viewpager中的另一个片段,这将非常有用。

要将数据从1st Fragment()(假设它作为 FirstFragment )传递到Viewpager内的第二个片段(假设它为 SecondFragment ),请按照以下步骤操作。

第1步:使用如下方法签名创建一个界面。

public interface ShareIt {
    public void passIt(String data);
}

第2步: SecondFragment需要实现ShareIt接口,并且应该覆盖passIt方法,并且需要将数据存储在从FirstFragment传递的局部变量中。除此之外,我传递了Viewpager的实例和Fragment的索引。需要Viewpager实例作为findFragmentByTag方法的参数。所以你的SecondFragment会是这样的。

public class SecondFragment extends Fragment implements ShareIt {

private NonSwipeableViewPager pager;
private int index;
private String string;

public static SecondFragment newInstance(int index, NonSwipeableViewPager viewPager) {
    SecondFragment f = new SecondFragment();
    Bundle args = new Bundle();
    args.putSerializable("VP", viewPager);
    args.putInt("index", index);
    f.setArguments(args);
    return f;
}


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

    Bundle bundle = getArguments();
    pager = (NonSwipeableViewPager) bundle.getSerializable("VP");
    index = bundle.getInt("index");



    return rootView;
}

@Override
public void passIt(String data) {
    string = data; // Storing the data which is been passed from FirstFargment in a local variable
    Toast.makeText(getActivity(), "" + data, Toast.LENGTH_SHORT).show();
 }
}

第3步:现在来自FirstFragment,我们需要在Viewpager中找到SecondFragment,就像这样

Fragment frag = getActivity().getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.pager + ":" + pager.getCurrentItem()); 
// pager.getCurrentItem() will give 0, index 0 will have instance of FirstFragment, but we want instance of SecondFragment, so we need to pass 1 instead of pager.getCurrentItem()
Fragment frag = getActivity().getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.pager + ":" + 1); 

由于我们有了SecondFragment的实例,我们可以调用SecondFragment的passIt方法来传递这样的数据

((SecondFragment)dataBoy).passIt("Hello..!!!!");

所以你的FirstFragment会看起来像这样。

public class FirstFragment extends Fragment {

private Button btnNext;

private NonSwipeableViewPager pager;
private int index;




public static FirstFragment newInstance(int index, NonSwipeableViewPager viewPager) {
    FirstFragment f = new FirstFragment();
    Bundle args = new Bundle();
    args.putSerializable("VP", viewPager);
    args.putInt("index", index);
    f.setArguments(args);
    return f;
}


@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_first, container, false);
    Bundle bundle = getArguments();
    pager = (NonSwipeableViewPager) bundle.getSerializable("VP");
    index = bundle.getInt("index");
    btnNext = findViewById(R.id.btnNext);
    Fragment frag= getActivity().getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.pager + ":" + 1);




    btnNext.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {

            ((SecondFragment)frag).passIt("Hello..!!!!");           

        }
    });


    return rootView;
  }

}

答案 3 :(得分:0)

取决于数据的性质。

理想情况下,数据保存在ActivityViewPager Adapter中 - 因此,当构建每个片段时,它会从Activity等获取其数据。请参阅此question on SO

我认为最好的解决方案是,如果您可以将数据存储在数据库中,每个Fragment通过CotnentProvider将数据存储在数据库中,那么您可以使用Loaders特别是CursorLoader来检索数据 - 这种方法将始终为您提供最新数据,因为Laoder会在更改时得到通知。

请查看此处的官方文档example

我会建议使用上面建议的偏好设置来存储除基元等之外的复杂数据进行设置。

答案 4 :(得分:0)

尝试以下代码在片段之间传递数据

Bundle bundle = new Bundle();
FragmentTransaction fragmentTx=this.FragmentManager.BeginTransaction();
TracksByGenres fragTrack=new TracksByGenres();
bundle.putString(key, value); i.e bundle.putString("myKey",items[e.Position]);
fragTrack.setArguments(bundle);
                //get our item from listview
fragmentTx.Replace(Resource.Id.fragmentContainer,fragTrack);    
fragmentTx.AddToBackStack(null);
fragmentTx.Commit();

通过

从被调用的片段onCreate()中检索数据
Bundle bundle = this.getArguments();
String value= bundle.putString(key, defaultValue); i.e bundle.putString(myKey, "");

答案 5 :(得分:0)

这是一个古老的问题,以上所有答案均有效。这是2019年,自 Android Architecture Components

开始,Android发生了很大变化

enter image description here

如果您使用的是 Android JetPack ,则可以在主机活动类的 Live Data 上添加观察者,并监听Fragment类中的更改

创建一个Singleton存储库以保存实时数据

/**
 * Data Class Live Data
 */
class Repository private constructor() {


    private var currentProgress: MutableLiveData<Float> = MutableLiveData()

    fun getLiveProgress(): MutableLiveData<Float> {
        return currentProgress
    }

    companion object {

        private val mInstance: Repository =
                Repository()

        @Synchronized
        fun getInstance(): Repository {
            return mInstance
        }
    }
}

设置活动数据在Activity或Fragment类中的任何位置

  viewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
            override fun onPageScrollStateChanged(state: Int) {
            }

            override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
                headMotionScene.progress = positionOffset
                Repository.getInstance().getLiveProgress().value = positionOffset
            }

            override fun onPageSelected(position: Int) {
            }

        })

从您的Fragment / Service类中观察数据更改

    Repository.getInstance().getLiveProgress().observe(this, Observer<Float> {
        motionLayout.progress = it
    })