简体   繁体   English

将数据从一个设计选项卡传递到另一选项卡

[英]Pass data from one design tab to another tab

I am using material design tabs as follows : 我使用的材料设计选项卡如下:

Following is my MainActivity.class : 以下是我的MainActivity.class:

 public class MainActivity extends AppCompatActivity implements ViewPager.OnPageChangeListener {

    private TabLayout tabLayout;
    private ViewPager viewPager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        tabLayout = (TabLayout) findViewById(R.id.tabs);
        viewPager = (ViewPager) findViewById(R.id.viewpager);
        ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
        viewPager.setAdapter(adapter);
        viewPager.addOnPageChangeListener(this);
        tabLayout.setupWithViewPager(viewPager);

    }

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

    }

    @Override
    public void onPageSelected(int position) {
        System.out.println("onPageSelected Called");
    }

    @Override
    public void onPageScrollStateChanged(int state) {

    }
}

My ViewPagerAdapter is as follows : 我的ViewPagerAdapter如下:

    public class ViewPagerAdapter extends FragmentPagerAdapter {

    private static int count = 2;

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

    @Override
    public Fragment getItem(int position) {

        switch (position) {
            case 0:
                 return new FragmentOne();
            case 1:
                return new FragmentTwo();
        }
        return null;
    }

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

    @Override
    public CharSequence getPageTitle(int position) {
        switch (position)
        {
            case 0 :
                return "Tab One";
            case 1 :
                return "Tab Two";
        }
        return null;
    }
}

and here are my Fragments : 这是我的片段:

This is my first fragment name is FragmentOne : 这是我的第一个片段名称为FragmentOne:

    public class FragmentOne extends Fragment {

    private EditText editText;
    private Button btnSendData;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        System.out.println("IN FRAGMENT ONE");
        View view = inflater.inflate(R.layout.fragment_one,container,false);

        editText = (EditText) view.findViewById(R.id.et_name);
        btnSendData = (Button) view.findViewById(R.id.btn_send);

        btnSendData.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                FragmentTwo fragment = new FragmentTwo();
                Bundle bundle = new Bundle();
                bundle.putString("username",editText.getText().toString());
                fragment.setArguments(bundle);
                getFragmentManager.beginTransaction.replace(R.id.frag_second,fragment).commit();

            }
        });

        return view;
    }
}

and here is another fragment with name FragmentTwo : 这是另一个名为FragmentTwo的片段:

 public class FragmentTwo extends Fragment {

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        System.out.println("IN FRAGMENT TWO");
        View view = inflater.inflate(R.layout.fragment_two,container,false);
        Bundle bundle = getArguments();
        if(bundle!= null)
        {
            String value = getArguments().getString("username");
        }
        return  view;
    }

    @Override
    public void onResume() {
        super.onResume();
        System.out.println("onResume gets called");
    }
}

In the second fragment i am getting data buts its adding another view with previous one. 在第二个片段中,我正在获取数据,但是它与先前的视图一起添加了另一个视图。 see the image : 看到图片:

在此处输入图片说明

so I want to pass data from FragmentOne to FragmentTwo in two scenario : 所以我想在两种情况下将数据从FragmentOne传递给FragmentTwo:
1. I want to pass the data when i click on button and 1.我想在单击按钮和
2. When I swipe to FragmentTwo data should be passed 2.当我滑动到FragmentTwo时,应该传递数据

Also when I try to swipe to FragmentTwo nothing gets called in FragmentTwo ? 另外,当我尝试滑动到FragmentTwo时,在FragmentTwo中没有调用任何东西吗? why is it so ? 为什么会这样呢? Also when I click to second tab nothing gets called . 另外,当我单击第二个选项卡时,什么也不会被调用。 Please help me how should i pass data to FragmentTwo on button click ? 请帮助我,如何在单击按钮时将数据传递给FragmentTwo?

following are layout files: here is fragment_one 以下是布局文件:这是fragment_one

<LinearLayout 
       xmlns:android="http://schemas.android.com/apk/res/android"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:gravity="center"
       android:orientation="vertical">
           <EditText
               android:layout_marginLeft="16dp"
               android:layout_marginRight="16dp"
               android:id="@+id/et_name"
               android:hint="Username"

               android:layout_width="match_parent"
               android:layout_height="wrap_content"/>

           <Button
                android:padding="16dp"
                android:text="Send Data"
                android:layout_marginLeft="16dp"
                android:layout_marginRight="16dp"
                android:id="@+id/btn_send"
                android:layout_height="wrap_content"
                android:layout_width="match_parent"/>

and second fragment , fragment_second.xml : 第二个片段fragment_second.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/second_frag"
android:gravity="center">
<TextView
    android:textSize="24sp"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textAppearance="?android:attr/textAppearanceLarge"
    android:text="Fragment Two"
    android:id="@+id/textView2" />

Each fragment is associated with the parent activity. 每个片段都与父活动相关联。 so you can't directly communicate from one fragment to another fragment. 因此您不能直接从一个片段与另一个片段进行通信。 You will need to go through Parent Activity using interface. 您将需要使用界面进行“家长活动”。

Check this docs : https://developer.android.com/training/basics/fragments/communicating.html 检查此文档: https : //developer.android.com/training/basics/fragments/communicating.html

On button click pass the value to methods in your custom interface and access those methods in second fragment. 单击按钮后,将值传递到自定义界面中的方法,然后在第二个片段中访问这些方法。

when I try to swipe to FragmentTwo nothing gets called in FragmentTwo 当我尝试滑动到FragmentTwo时,在FragmentTwo中什么都没叫

For this you need to implement fragment life cycle - https://developer.android.com/reference/android/app/Fragment.html 为此,您需要实现片段生命周期-https: //developer.android.com/reference/android/app/Fragment.html

UPDATE UPDATE

Done with some modification in you code, just look at the foll. 在您的代码中进行了一些修改后,只需查看以下内容即可。 code - 代码-

Manifex.xml Manifex.xml

<application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity"
            android:theme="@style/Theme.AppCompat.NoActionBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

MainActivity.java MainActivity.java

package com.app.onkar.tabdemo;

import android.support.v4.app.Fragment;
import android.support.design.widget.TabLayout;

import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;

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

public class MainActivity extends AppCompatActivity implements ViewPager.OnPageChangeListener {

    private Toolbar toolbar;
    private TabLayout tabLayout;
    private ViewPager viewPager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        viewPager = (ViewPager) findViewById(R.id.viewpager);
        tabLayout = (TabLayout) findViewById(R.id.tabs);


        ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());

        adapter.addFragment(new FragmentOne(), "ONE");
        adapter.addFragment(new FragmentTwo(), "TWO");
        viewPager.setAdapter(adapter);

        viewPager.addOnPageChangeListener(this);
        tabLayout.setupWithViewPager(viewPager);
    }

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

    }

    @Override
    public void onPageSelected(int position) {
        System.out.println("onPageSelected Called");
    }

    @Override
    public void onPageScrollStateChanged(int state) {

    }

    public static class ViewPagerAdapter extends FragmentPagerAdapter {
        private final List<Fragment> mFragmentList = new ArrayList<>();
        private final List<String> mFragmentTitleList = new ArrayList<>();
        private static int count = 2;

        public void addFragment(Fragment fragment, String title) {
            mFragmentList.add(fragment);
            mFragmentTitleList.add(title);
        }

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

        @Override
        public Fragment getItem(int position) {

            switch (position) {
                case 0:
                    return new FragmentOne();
                case 1:
                    return new FragmentTwo();
            }
            return null;
        }

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

        @Override
        public CharSequence getPageTitle(int position) {
            switch (position) {
                case 0:
                    return "Tab One";
                case 1:
                    return "Tab Two";
            }
            return null;
        }
    }
}

FragmentOne.java FragmentOne.java

package com.app.onkar.tabdemo;

import android.content.Context;
import android.net.Uri;
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;
import android.widget.EditText;

public class FragmentOne extends Fragment {
    private EditText editText;
    private Button btnSendData;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        System.out.println("IN FRAGMENT ONE");
        View view = inflater.inflate(R.layout.fragment_one,container,false);

        editText = (EditText) view.findViewById(R.id.et_name);
        btnSendData = (Button) view.findViewById(R.id.btn_send);

        btnSendData.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                FragmentTwo fragment = new FragmentTwo();
                Bundle bundle = new Bundle();
                bundle.putString("username",editText.getText().toString());
                fragment.setArguments(bundle);
                getActivity().getSupportFragmentManager().beginTransaction().replace(R.id.second_frag,fragment).commit();
            }
        });

        return view;
    }
}

FragmentTwo.java FragmentTwo.java

package com.app.onkar.tabdemo;


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


public class FragmentTwo extends Fragment {

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        System.out.println("IN FRAGMENT TWO");
        View view = inflater.inflate(R.layout.fragment_two,container,false);
        TextView txt2 = (TextView) view.findViewById(R.id.textView2);
        Bundle bundle = getArguments();
        if(bundle!= null)
        {
            String value = getArguments().getString("username");
            txt2.setText(value);
        }
        return  view;
    }

    @Override
    public void onResume() {
        super.onResume();
        System.out.println("onResume gets called");
    }

}

No change in Layout files. 布局文件没有变化。 Just try above code - it is working exactly as you want. 只需尝试上面的代码-它完全可以按照您的要求工作。 Hope it will help! 希望对您有所帮助!

SCREENS SCREENS 在此处输入图片说明 在此处输入图片说明

ViewPagerAdapter class ViewPagerAdapter类

public class ViewPagerAdapter extends FragmentPagerAdapter {

private static int count = 2;


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

@Override
public Fragment getItem(int position) {

switch (position) {
    case 0:
         Fragment fragmentone = new FragmentOne();
         Bundle args = new Bundle();
         args.putInt("code", 1);
         fragmentone.setArguments(args);
         return fragmentone;
    break;
    case 1:
        Fragment fragmenttwo = new FragmentTwo();
         Bundle args = new Bundle();
         args.putInt("code", 2);
         fragmenttwo.setArguments(args);
         return fragmenttwo ;
      break;
}
return null;
}

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

@Override
public CharSequence getPageTitle(int position) {
switch (position)
{
    case 0 :
        return "Tab One";
    case 1 :
        return "Tab Two";
}
return null;
}
}

args is the bundle object, you can put String int and other values to use these values in fragment use below code in onCreateView method of Fragment. args是bundle对象,您可以将String int和其他值放在fragment中使用这些值,使用Fragment的onCreateView方法中的以下代码。

int codeForthisFragment = getArguments().getInt("code");

for button click: FragmentTransaction ft = getFragmentManager().beginTransaction(); 单击按钮:FragmentTransaction ft = getFragmentManager()。beginTransaction(); Fragment secondFragment = new FragmentTwo(); 片段secondFragment = new FragmentTwo();

                    Bundle args = new Bundle();
                    args.putInt("code", 2);
                    secondFragment.setArguments(args);
                    ft.replace(R.id.content_frame, secondFragment);
                    ft.commit();

In the second fragment i am getting data buts its adding another view with previous one. 在第二个片段中,我正在获取数据,但是它与先前的视图一起添加了另一个视图。 see the image 看图片

With reference to the answer by @Roy Miller( https://stackoverflow.com/users/5255021/roy-miller ), you can solve it by doing the follwing changes: 参考@Roy Miller( https://stackoverflow.com/users/5255021/roy-miller )的回答,您可以通过以下更改来解决:

In MainActivity.java ,replace the follwing switch: MainActivity.java中 ,替换以下开关:

 @Override
    public Fragment getItem(int position) {

        switch (position) {
            case 0:
                return new FragmentOne();
            case 1:
                return new FragmentTwo();
        }
        return null;
    }

With: 附:

@Override
public Fragment getItem(int position) {

    switch (position){
        case 0:
            return mFragmentList.get(0);
        case 1:
            return mFragmentList.get(1);
        case 2:
            return mFragmentList.get(2);
        default:
            return null;
    }

}

And then, in FragmentOne.java 然后,在FragmentOne.java中

Replace this: 替换为:

btnSendData.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            FragmentTwo fragment = new FragmentTwo();
            Bundle bundle = new Bundle();
            bundle.putString("username",editText.getText().toString());
            fragment.setArguments(bundle);
            getActivity().getSupportFragmentManager().beginTransaction().replace(R.id.second_frag,fragment).commit();
        }
    });

With: 附:

btnSendData.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

/*This one FragmentCollection is a Singleton class that contains list of fragments, set it during initialization itself(code is attached below this code)*/
FragmentCollection fragmentCollection=FragmentCollection.getInstance();

            FragmentTwo fragment = (FragmentTwo) FragmentCollection.getmFragmentList().get(2); //getting the second fragment

             fragment.setText(editText.getText().toString());  //add this method in fragment two             

        }
    });

Now inside FragmentTwo.java Add the method: 现在在FragmentTwo.java中添加方法:

public void updateTextView(String data){
    Log.d("TabTwo","Update Text view");
    TextView txt = (TextView)view.findViewById(R.id.textView2);
    txt.setText(data);
}

At last, the singleton class i mentioned above: 最后,我上面提到的单例课程:

public class FragmentCollection {
static FragmentCollection fragmentCollection=new FragmentCollection();
private final List<Fragment> mFragmentList = new ArrayList<>();    
private FragmentCollection(){}
public static FragmentCollection getInstance(){
    if(fragmentCollection!=null) {
        return fragmentCollection;
    }else {
        return new FragmentCollection();
    }
}
public void setmFragmentList(List<Fragment> mFragmentList){
    this.mFragmentList.addAll(mFragmentList);
}
public List<Fragment> getmFragmentList(){
    return mFragmentList;
}
}

The issue of getting older views overlapping is because of initializing the fragment again and again 使旧视图重叠的问题是因为一次又一次地初始化片段

like new FragmentTwo(); 就像新的FragmentTwo(); in more than one place. 在一个以上的地方。

So here we put it in a list and access it so only a single fragment is altered. 因此,这里我们将其放在列表中并进行访问,以便仅更改单个片段。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM