简体   繁体   中英

pass data to another fragment by swipe view with tab android studio,not button

Is it possible to pass a data from fragment to fragment by swipe?

There are many articles teaching us how to pass the data from fragment to fragment, but most of the article or questions had implemented OnClickListener in their first fragment, which used to pass value to another fragment.

But my case is pass the data from two fragments without any button click and finally save them in different tables by clicking button in the last fragment. What can I do to achieve this??

The flow is Information >> WorkForce >> WorkDetailsTable and save them to different table by one button click.

I have tried to work it out but I get NULL value in SQLite. I think I have miss out a lot but have no idea. PLEASE help me...I've been stuck at here for more than two days...Thanks

Tab.java

public class Tab extends ActionBarActivity implements ActionBar.TabListener {
    ViewPager Tab;
    TabPagerAdapter TabAdapter;
    ActionBar actionBar;
    public static String name = null;
    public static String subContractors = null;

// will be used for data communication 

    public static Force force_bean;;
    public static Info info_bean;


    public static Force getForce(){

        return force_bean;
    }
    public static void setForce(Force force){

        force_bean=force;
    }
    public static Info getInfo(){

        return info_bean;
    }
    public static void setInfo(Info info){

        info_bean=info;
    }



    final Activity mActivity = (Activity) this;

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


        info_bean = new Info();
        force_bean = new Force();


        TabAdapter = new TabPagerAdapter(getSupportFragmentManager());


        Tab = (ViewPager) findViewById(R.id.pager);

        Tab.setOnPageChangeListener(
                new ViewPager.SimpleOnPageChangeListener() {
                    @Override
                    public void onPageSelected(int position) {

                        actionBar = ((AppCompatActivity) mActivity).getSupportActionBar();
                        actionBar.setSelectedNavigationItem(position);
                    }
                });

        Tab.setAdapter(TabAdapter);

        actionBar = ((AppCompatActivity) mActivity).getSupportActionBar();

//Enable Tabs on Action Bar 
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);


//Add New Tabs 
        actionBar.addTab(actionBar.newTab().setText("Information").setTabListener(this));
        actionBar.addTab(actionBar.newTab().setText("Work Force").setTabListener(this));
        actionBar.addTab(actionBar.newTab().setText("Work Details").setTabListener(this));

    }


    @Override
    public void onTabSelected(ActionBar.Tab tab, android.support.v4.app.FragmentTransaction ft) {

    }

    @Override
    public void onTabUnselected(ActionBar.Tab tab, android.support.v4.app.FragmentTransaction ft) {

    }

    @Override
    public void onTabReselected(ActionBar.Tab tab, android.support.v4.app.FragmentTransaction ft) {

    }
}

TabPagerAdapter.java

public class TabPagerAdapter extends FragmentStatePagerAdapter {
        public TabPagerAdapter(FragmentManager fm) {
            super(fm);
        }
       @Override
        public Fragment getItem(int i) {
            switch (i) {
                case 0:
                    return  Information.newInstance("name");
                case 1:
                    return WorkForce.newInstance("SubCon");
                case 2:
                    return WorkDetailsTable.newInstance();
            }
            return null ;
        }
        @Override
        public int getCount() {
            return 3; //No of Tabs you can give your number of tabs
        }

Informmation.java

public class Information extends Fragment implements View.OnClickListener {
        private Spinner spinner, spinner2, spinner3;

        private static String a;
         public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            View info = inflater.inflate(R.layout.information, container, false);
            dialog = new DateDialog();
            spinner = (Spinner)info.findViewById(R.id.spinner);
            addItemsOnSpinner();
            a= spinner.getSelectedItem().toString();
            return info;
        }

     public static Information newInstance(String a)
        {
           Information fragment=new Information();
            Bundle bundle=new Bundle();
            bundle.putString("a",a);
            fragment.setArguments(bundle);
            return fragment;
        }

     public void addItemsOnSpinner() {
            List<String> list = new ArrayList<String>();
            list.add("1 ");
            list.add("2");
            ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_spinner_dropdown_item, list);
            adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
            spinner.setAdapter(adapter);



        }

WorkForce.java

public class WorkForce extends Fragment {
        private static EditText txt1;
        private static String subCon;
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            View work = inflater.inflate(R.layout.workforce, container, false);
            txt1 = (EditText) work.findViewById(R.id.editText);
            subCon = txt1.getText().toString();
            return work;
        }

        public static WorkForce newInstance(String subCon) {

            WorkForce f = new WorkForce();
            Bundle bundle = new Bundle();
            bundle.putString("subCon", subCon);
            f.setArguments(bundle);
            return f;
        }
    }

WorkDetails.java

 private com.example.project.project.API.InfoAPI ts;
     private com.example.project.project.API.WorkDetailsAPI WD;
     private com.example.project.project.API.WorkForceAPI WF;
     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     View workDetails = inflater.inflate(R.layout.tableworkdetails, container, false);
                getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        spinnerTra = (Spinner) workDetails.findViewById(R.id.spinner6);
        addItemsOnSpinner();
        Button btn1 = (Button)workDetails.findViewById(R.id.button2);
        WD = new com.example.project.project.API.WorkDetailsAPI(getActivity());
        ts = new com.example.project.project.API.InfoAPI(getActivity());
        WF = new com.example.project.project.API.WorkForceAPI(getActivity());
        a1 = spinnerTra.getSelectedItem().toString();
        Bundle bundle = new Bundle();
        final String name = bundle.getString("a");
        final String subContractors = bundle.getString("subCon");
        btn1.setOnClickListener(new View.OnClickListener() {
            public void onClick(View arg0) {



                 add(name, subContractors);
                }
            });

            return workDetails;
        }

     public void  add(String name,String subContractors)
        {
            Toast.makeText(getActivity(),+name+subContractors, Toast.LENGTH_SHORT).show();
ts.insertTimeSheet(name);
WF.insertWorkForce(subContractors);

        }

Note: My case is pass the data from two fragments without any button click and finally save them in different tables by clicking button in the last fragment.

If I understand your problem correctly, you are essentially implementing something a little bit like a "Wizard" where each step passes information to the next step as you swipe between the tabs or select them.

So in reality your problem is how to get the information out of a fragment when it is deselected and into a fragment when selected.

At the simplest level I would suggest your activity holds the "master" copy of all of the information and passes it into/takes it from each fragment in your tab pager adapter.

You would need some kind of "Domain" object to hold all the information you need to collect. Each tab would only update the bits of information it cares about..

public class WorkData {
 string information;
 string subCon;
... etc..
}

You add an instance of this to hold the master copy to your "tab" activity:

public class Tab extends ActionBarActivity implements ActionBar.TabListener {
...
 WorkData workData = new WorkData();
...

I would then suggest a simple interface that each of your "tab" fragments implement; something like:

public interface DataUpdate {
 void setData(WorkData data);
 WorkData getData();
}

Each of your tab fragments would implement this interface, updating the WorkData as required..

public class WorkForce extends Fragment implements DataUpdate {
...
  private WorkData workData; // this fragment's "copy" of the data
...
@Override
public WorkData getData() {
  this.workData.subCon = this.subCon; // Assuming subcon has been updated.. else use txt1.getText();
  return this.workData;
}

@Override
public void setData(WorkData workData) {
 this.workData = workData;
 // Update this page's views with the workData...
 // This assumes the fragment has already been created and txt1 is set to a view
 txt1.setText(workData.subCon);
 this.subCon = workData.subCon; // Actually could just use subCon in workData, but be aware that workData actually points to the Activity's copy (kinda makes getdata redundant.. but I like symmetry and couldn't be bothered making lots of copies of the object).
}

Then you just need to add the code to pass the data backwards and forwards.. in your "Tab" activity which looks like...

@Override
public void onTabSelected(ActionBar.Tab tab, android.support.v4.app.FragmentTransaction ft) {
 int position = tab.getPosition();
 DataUpdate dataUpdate = (DataUpdate) TabAdapter.getItem(position);
 // Pass the master workdata to the selected fragment
 dataUpdate.setData(this.workData);
}

@Override
public void onTabUnselected(ActionBar.Tab tab, android.support.v4.app.FragmentTransaction ft) {
 int position = tab.getPosition();
 DataUpdate dataUpdate = (DataUpdate) TabAdapter.getItem(position);
 // Update the master workdata from the unselected fragment
 this.workData = dataUpdate.getData();
}

@Override
public void onTabReselected(ActionBar.Tab tab, android.support.v4.app.FragmentTransaction ft) {
 // This might be pointless, but we'll do it anyway..
 int position = tab.getPosition();
 DataUpdate dataUpdate = (DataUpdate) TabAdapter.getItem(position);
 // Pass the master workdata to the selected fragment
 dataUpdate.setData(this.workData);
}

An important thing to notice here is that your TabPagerAdapter will create a new fragment every time you call getItem().. that will mean that we will never get any updates because each time we try to get the fragment it returns a new, empty fragment. We need to change this so that the fragments are still created when first asked for, but only created once so that we don't keep throwing away our work.

public class TabPagerAdapter extends FragmentStatePagerAdapter {
 private static final int NUMBER_OF_TABS = 3;
 private Fragment[] tabList = new Fragment[NUMBER_OF_TABS];

        public TabPagerAdapter(FragmentManager fm) {
            super(fm);
        }
       @Override
        public Fragment getItem(int i) {
            if (tabList[i] != null) {
              // Return a tab we created earlier..
              return tabList[i];
            } else {
              switch (i) {
                  case 0:
                      tabList[0] = Information.newInstance("name");
                      return  tabList[0];
                  case 1:
                      tabList[1] = WorkForce.newInstance("SubCon");
                      return tabList[1];
                  case 2:
                      tabList[2] = WorkDetailsTable.newInstance();
                      return tabList[2];
              }
            }
            return null ;
        }
        @Override
        public int getCount() {
            return NUMBER_OF_TABS;
        }

Hope this helps. Good luck :-)

Although C James provides good tips to solve your problems, I would like to introduce another way without using implementing of interfaces. Please check below link out. If you use an event bus library such a http://square.github.io/otto/ , you can easily pass data you want to share among fragments and even activities. Additionally, you can reduce a lot of code line since it only requires Sender(PUBLISHING), Receiver(Subscriber) while implementation of interfaces requires additional lines of code. Here is a tutorial of Otto libarary. http://www.vogella.com/tutorials/JavaLibrary-EventBusOtto/article.html

Hope it helps :)

I would more go the Observer Pattern way. Each Fragments changes an POJO with is rendered in your Fragments in some way. You simply have to Observe the pojo in your Fragments. Changing Fragments will notify interested observers without knowing them.

I believe that's a much cleaner way to implement this.

Fragment A -> PojoInstance.setXY("foo"); Fragment A -> informs the Observers which eb Informs Fragment B:

Fragment B will see the change tru the Observer.

Because ViewPagers or other Components will cache Fragments thats a way to get information in already created Fragments, even when their are not seen.

You could also try to use an EventBus where you pass the POJO around.

To transfer data from one fragment to another fragment when swipe is performed ,firstly you should get the view of the each fragment.here is the sample code that can help you out a bit. write this code in Activity:

 mviewpager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
    mviewpager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            adapter = ((SOFragmentPagerAdapter) mviewpager.getAdapter());

//getting the view of fragments at positions              


 if(position==0)
            {
                View v = null;
             Fragment1=(Fragment1)adapter.getFragment(position);
                v=fragment1.getMyView();//this is how you get the view
                ListView lv=(ListView)v.findViewById(R.id.lv_services);
                ArrayAdapter<String> arrayAdapter=new ArrayAdapter<String>(SOListItemSelectedActivity.this,android.R.layout.simple_list_item_1,soRequestFragment.al_list_of_services);
                lv.setAdapter(arrayAdapter);
            }

            if(position==1)
            {


            }
        }

        @Override
        public void onPageSelected(int position) {
            if(position==0)
            {
                View v = null;
                soRequestFragment=(SORequestFragment)adapter.getFragment(position);
                v=soRequestFragment.getMyView();
            }
            if(position==1)
            {


            }
        }

        @Override
        public void onPageScrollStateChanged(int state) {

        }
    });
    tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
        @Override
        public void onTabSelected(TabLayout.Tab tab) {
            mviewpager.setCurrentItem(tab.getPosition());
        }

        @Override
        public void onTabUnselected(TabLayout.Tab tab) {

        }

        @Override
        public void onTabReselected(TabLayout.Tab tab) {

        }
    });

and create a FragmentPagerAdapter as:

public class SOFragmentPagerAdapter extends FragmentPagerAdapter {
HashMap<Integer,Fragment> mPageReferenceMap;
int mNumOfTabs;
public SOFragmentPagerAdapter(FragmentManager fm,int mNumOfTabs) {
    super(fm);
    this.mNumOfTabs=mNumOfTabs;
    mPageReferenceMap=new HashMap<Integer,Fragment>();
}

@Override
public Fragment getItem(int position) {
      switch (position)
      {
          case 0:
              Fragment1 fragment1=new tFragment1();
              mPageReferenceMap.put(position,fragment1);
              return fragment1;

          case 1:
              Fragment2 fragment2=new Fragment2();
              mPageReferenceMap.put(position,fragment2);
              return fragment2;

          default:
              return null;
      }

}
public Fragment getFragment(int key) {
    return mPageReferenceMap.get(key);
}
@Override
public int getCount() {
    return 2;
}}

In Fragments add the getmyview() which will return the view of that fragment as:

public void getmyview()

{ return myview;//myview is fragment view which you will return in oncreateview method }

Note: Viewpager execute onpagescroll first and get the position 0,1 and when you scroll ,views at position 1,2 will execute and page selected 0 will execute. For tabselections: Tabunselected,Tabselected Tab reselected is the sequence of execution. so write accordingly in the respective positions of fragments. Hope this helps you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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