简体   繁体   中英

Save data from fragments when switching tabs

I've written a game where the user inputs the number of player and every player gets an own tab with an empty table.

Therefore I used a PagerAdapterClass (extends FragmentStatePagerAdapter ) and a viewpager . So every player has the same fragmentView .

Now the user can put variables into the table, bu everytime I switch between the tabs, the input gets lost. Well, i 'fixed' that problem by adding this to my pageradapter:

@Override
    public void destroyItem(ViewGroup container, int position, Object object) {

    }

But it's more stopping the viewpager from destroying than actually saving the data.

My main goal is to really save that stuff in that table.

I already tried https://stackoverflow.com/a/17135346/11956040 but i cannot get mContent because i cannot get the reference of the fragment, because all fragments are not created on their own but all at the same time (or something like that).

I also don't know how to set a Tag. This way: https://stackoverflow.com/a/18993042/11956040 doesn't work for me.

MainActivity:

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

        ...

        //numPlayer = num of tabs
        SectionsPagerAdapter adapter = new SectionsPagerAdapter(numPlayer, getSupportFragmentManager());

        ViewPager viewPager = findViewById(R.id.view_pager);
        viewPager.setAdapter(adapter);

        TabLayout tabs = findViewById(R.id.tabs);
        tabs.setupWithViewPager(viewPager);
        if(numPlayer >= 5) {
            tabs.setTabMode(TabLayout.MODE_SCROLLABLE);
        }
    }

PagerAdapter:

public class SectionsPagerAdapter extends FragmentStatePagerAdapter {

    private int tabNum;

    public SectionsPagerAdapter(int tabNum, FragmentManager fm) {
        super(fm);
        this.tabNum = tabNum;
    }

    @Override
    public PlaceholderFragment getItem(int position) {
        return PlaceholderFragment.newInstance(position);
    }

    @Nullable
    @Override
    public CharSequence getPageTitle(int position) {
        int playerNum = position + 1;
        return "Spieler " + playerNum;
    }

    @Override
    public int getCount() {
        // Show 2 total pages.
        return tabNum;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {

    }
}

Fragment:

public static PlaceholderFragment newInstance(int index) {
        PlaceholderFragment fragment = new PlaceholderFragment();
        Bundle bundle = new Bundle();
        bundle.putInt("player", index);
        fragment.setArguments(bundle);
        return fragment;
    }

There must be a solution but I cannot find it or cannot implement it. Pls help.

Solved my problem this way:

  1. define 2 dimensional ArrayList for rows and columns and counter for columns:
    private ArrayList<ArrayList<Integer>> columnArray; 
    private int column;
  1. onCreateView (for fragments) set column = 0 and add one entry with an empty list to columnArray and set the first rowList on column index of columnArray :
pointArray.add(column, new ArrayList<Integer>());
final ArrayList<Integer> rowList = pointArray.get(column);
  1. fill the empty rowList with 0 (maybe it also works in an other way, but I made it this way to have on empty EditTexts a 0 and can easily replace them)

  2. define View.OnFocusChangeListener for all EditTexts like this:

/*I dont know if I could set column final in general, 
but you need to set a final int because you call this value in an inner class*/

final int pos = column 

for (int i = 0; i <= getEditTexts(pos).size() - 1; i++) {
EditText editTexts = getEditTexts(pos).get(i);
final String editTextsTag = editTexts.getTag().toString();

View.OnFocusChangeListener listener = new View.OnFocusChangeListener() {
   @Override
   public void onFocusChange(View view, final boolean b) {
      if (view.getTag().toString().equals(editTextsTag) && !b) {
        //fills rowList
        addEntries(pos, rowList);

        //adds rowList to columnArray
        columnArray.set(pos, rowList);

        //save the columnsArray or use it 
        saveData(columnArray);
      }
   }
};
editTexts.setOnFocusChangeListener(listener);
  1. define method which collects data from each cell, depending on column position (pos), add it to rowList for example:
private void addEntries(int pos, ArrayList<Integer> rowList) {
   for(int i = 0; i <= 16; i++) {
      //this requires EditText_label, i made them dynamically
      String edit_label = "edit_" + pos + i; 
      EditText editText = table.findViewWithTag(edit_label);
      String mEditTextString = editText.getText().toString();

      try {
         int thisValue = Integer.parseInt(mEditString);
         rowList.set(j, thisValue);
      } catch (NumberFormatException e) {
         //maybe you do not need this, but I need it for something else
         int thisValue = 0;
         rowList.set(j, thisValue);
      }
   }
}
  1. define a method for saving the columnArray . I used an interface to give it to parent Activity: Here you can find how I made it Otherwise you can convert the columnArray to a String and save it in a database.

NOTE

I made it with column value set beacuse I increase the value for every column I add during runtime using a method. If you just have one column, you dont need to set it. Just use 0 instead of pos, column

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