android: циклическое наследование для передачи валидации / данных из динамических фрагментов ViewPager в активность - PullRequest
0 голосов
/ 07 февраля 2019

Я столкнулся с проблемой и хотел бы получить представление о том, как я могу решить эту проблему.Вот краткое описание

Описание компонентов:

  1. An Activity с ViewPager и двумя кнопками:
    • Add fragment button => Добавляет новый фрагмент в ViewPager с тем же макетом
    • Continue button => Если пользовательские поля проверены во всех фрагментах, переход к следующему экрану
public class ParentActivity extends AppCompatActivity {
    private InputData mfirstProfileData;
    private ArrayList<InputData> mEditProfilesDataList = new ArrayList<>();
    ...
    private EditProfilePagerAdapter mPagerAdapter;
    private Button AddButton;
    private Button ContinueButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_parent);
        mFirstProfileData = new InputData();        
        ...

        mDotTabLayout.setupWithViewPager(mViewPager, true);
        mPagerAdapter = new EditProfilePagerAdapter(getSupportFragmentManager(),
                mViewPager, mDotTabLayout, mFirstProfileData);
        mViewPager.setAdapter(mPagerAdapter);

        mAddProfileBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v ){ 
                // TODO: validate data and save in List<InputData> 
            addProfile(EditProfileFragment.newInstance(getNextPageNumber(), new InputData());          
            }
        });

        mContinueBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v ){ 
                // TODO: validate data iff one EditProfileFragment and save in List<InputData> 
            sendToServer();          
            }
        });
    }
    ...
    public void addProfile(Fragment fragment) {
        mPagerAdapter.addFragment(fragment);
    }

    public void deleteProfile () {
        mPagerAdapter.deleteFragment();
    }

}

A FragmentPagerAdapter, ответственный за инициализацию фрагментов, заботится о динамическом добавлении / удалении фрагментов
public class EditProfilePagerAdapter extends FragmentPagerAdapter {
    private List<Fragment> fragments = new ArrayList<>();
    private ViewPager mViewPager;
    private TabLayout mDotTabLayout;

    public EditProfilePagerAdapter(FragmentManager fm, ViewPager viewPager, TabLayout tabLayout, InputData firstProfileInputData) {
        super(fm);
        fragments.add(EditProfileFragment.newInstance(0, firstProfileInputData));
        mViewPager = viewPager;
        mDotTabLayout = tabLayout;
    }

    public void addFragment (Fragment fragment) {
        fragments.add(fragment);
        notifyDataSetChanged();
        mDotTabLayout.setupWithViewPager(mViewPager);
        mViewPager.setCurrentItem(fragments.size() - 1);
    }

    public void deleteFragment () {
        if (mViewPager.getCurrentItem() != 0) {
            fragments.remove(mViewPager.getCurrentItem());
        }
        notifyDataSetChanged();
        mDotTabLayout.setupWithViewPager(mViewPager);
        mViewPager.setCurrentItem(fragments.size() - 1);
    }
    ...
}
Профиль Fragment с 5 пользовательскими полями ввода (EditTexts, RadioButtons, Dialogs) и одной кнопкой:
  • Delete => Удаляет текущий фрагмент из ViewPager
public class EditProfileFragment extends Fragment {

    ... // bunch of user input fields
    private InputData mInputData;
    private int mPosition;
    private FloatingActionButton mDeleteBtn;

    public static EditProfileFragment newInstance(int position, InputData inputData) {
        EditProfileFragment fragment = new EditProfileFragment();
        Bundle args = new Bundle();
        args.putInt(KEY_POSITION, position);
        args.putParcelable(KEY_NEW_INPUT_DATA, inputData);
        fragment.setArguments(args);

        return fragment;
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (getArguments() != null) {
            mPosition = getArguments().getInt(KEY_POSITION, -1);
            mInputData = getArguments().getParcelable(KEY_NEW_INPUT_DATA);
        }
        ...
        // Take user input and save as mInputData.setName() etc.
        ...

        mDeleteBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // TODO: send mInputData back to ParentActivity so it can be removed from the List<InputData>
                ((ParentActivity) getActivity()).deleteProfile();
            }
        });


    }
    ...



}

Вариант использования:

  • Пользователь входит в действие с одним фрагментом для начала.
  • Пользователь заполняет поля во фрагменте, некоторые обязательные для заполнения (базовая проверка), он может либо нажать Add в действии, чтобы добавить другой фрагмент профиля с такими же полями ввода.
  • После добавления пользователь также может удалить фрагмент, если он этого хочет, с помощью кнопки удаления, присутствующей в каждом фрагменте.

IMO, идентифицированные мной триггеры для прохожденияданные по активности:

  • Add button Если пользователь заполняет текущий фрагмент и нажимает кнопку добавления, чтобы получить другой фрагмент профиля редактирования, мы можем validate данные, поступающие изтекущий фрагмент в действии и сохраните его в List<InputData>, если проверка прошла успешно, если нет, мы setError() на поле, которое отсутствует в требуемых.

  • Continue button: Если у пользователя есть только 1 профиль (поскольку добавление другого профиля не является обязательным), мы можем проверить его, если пользователь нажимает кнопку, прежде чем перейти к следующему экрану

  • Delete button: Если пользователь удаляет профиль, действие уведомляется, чтобы мы могли удалить эти данные профиля из List<InputData>.remove(mInputData)

Я хочу синхронизировать проверку ввода пользователя и отправку данных пользователясюдаm каждый фрагмент родительского действия

Так что в конце, когда пользователь нажимает Continue, я получаю List<InputData>, по одному на каждый созданный пользователем фрагмент.Точно так же, если пользователь нажимает Delete на любом фрагменте, List<InputData> обновляется, чтобы удалить данные этого фрагмента.

Как мне организовать это?

Я попытался реализовать интерфейс (как в ParentActivity и EditProfileFragment, так и в прослушивании onAddButtonPressed() (кнопка «Добавить в действии») и onDeleteButtonPressed() (кнопка «Удалить в фрагменте»), и в итоге получил циклическое наследование. Любая помощь приветствуется!

...