Замена фрагмента внутри ViewPager из фрагмента Адаптер RecycerView Вернуться Пустой экран? - PullRequest
0 голосов
/ 18 декабря 2018

Я пытаюсь заменить текущий активный фрагмент внутри ViewPager при нажатии на элемент внутри recycelerview фрагмента.До сих пор мне удается вывести тост за второй фрагмент, когда щелкает элемент первого фрагмента, но весь вид второго фрагмента пуст.

Вот мой код:

MainActivity.class

public class MainActivity extends AppCompatActivity {
    
    private ViewPager viewPager;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);
        toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        viewPager = findViewById(R.id.view_pager);
        FragmentAdapter adapter = new FragmentAdapter(getSupportFragmentManager());
        
        viewPager.setAdapter(adapter);
        viewPager.setOffscreenPageLimit(adapter.getCount() - 1);
    
    }
    
    // ..........
    
    private static class FragmentAdapter extends FragmentStatePagerAdapter {

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

        @Override
        public Fragment getItem(int position) {
            switch (position) {
                case 0:
                    return AllGenreFragment.newInstance();
                case 1:
                    return DashboardFragment.newInstance();
                case 2:
                    return NotificationFragment.newInstance();
            }
            return null;
        }

        @Override
        public int getCount() {
            return 3;
        }
        
    }
    
    // ..........
    
}

AllGenreFragment.class

public class AllGenreFragment extends Fragment {

    RecyclerView genreRV;
    private AllGenreAdapter allGenreAdapter;
    private List<Genre> genreList;
    
    public static AllGenreFragment newInstance() {
        return new AllGenreFragment();
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        setHasOptionsMenu(true);
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        View v = inflater.inflate(R.layout.fragment_genre, container, false);

        genreRV = v.findViewById(R.id.rv);
        genreRV.setHasFixedSize(true);
        GridLayoutManager layoutManager = new GridLayoutManager(getContext(), 2);
        genreRV.setLayoutManager(layoutManager);
        genreList = new ArrayList<>();
        allGenreAdapter = new AllGenreAdapter(genreList, getContext());
        genreRV.setAdapter(allGenreAdapter);

        return v;
    }

}

AllGenreAdapter.class

public class AllGenreAdapter extends RecyclerView.Adapter<AllGenreAdapter.ViewHolder> {

    // .......
    
    class ViewHolder extends android.support.v7.widget.RecyclerView.ViewHolder {

        public ViewHolder(final View itemView) {
            super(itemView);

            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                
                    Toast.makeText(context, "Genre: " + genre_title.getText().toString(), Toast.LENGTH_SHORT).show();

                    AppCompatActivity activity = (AppCompatActivity) itemView.getContext();

                    FragmentManager fragmentManager = activity.getSupportFragmentManager();
                    FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

                    Fragment allAnimeFragment = new AllAnimeFragment();

                    Bundle bundle = new Bundle();
                    bundle.putString("genreid", genre_id.getText().toString().trim());
                    allAnimeFragment.setArguments(bundle);

                    fragmentTransaction.replace(R.id.view_pager, allAnimeFragment);
                    fragmentTransaction.addToBackStack(null);
                    fragmentTransaction.commit();

                }
            });

        }

    }

    // .......

}

AllAnimeFragment.class

public class AllAnimeFragment extends Fragment {

    RecyclerView animeRV;
    private AllAnimeAdapter allAnimeAdapter;
    private List<Anime> animeList;
    String genreid;

    public static AllAnimeFragment newInstance() {
        return new AllAnimeFragment();
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        setHasOptionsMenu(true);
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        View v = inflater.inflate(R.layout.fragment_anime, container, false);

        Bundle arguments = getArguments();
        genreid = arguments.getString("genreid");
        
        Toast.makeText(getContext(), genreid, Toast.LENGTH_SHORT).show();
        
        // .....

        return v;
    }
}

Ответы [ 2 ]

0 голосов
/ 18 декабря 2018

Ваш подход не очень хорош, попробуйте следующий способ:

  • Создайте фрагмент контейнера с именем ContainerFragment, например, вы будете использовать этот фрагмент для вашего ViewPager.

  • ContainerFragment должен содержать представление контейнера и добавить AllGenreFragment в первом из них, которое оно вызывается.

  • В AllGenreFragment создайте обратный вызов, при нажатии на элемент в RecyclerView, затем в ContainerFragment заменит (или добавит) текущий фрагмент (AllGenreFragment)AllAnimeFragment

Сначала создайте ContainerFragment,

public class ContainerFragment extends Fragment implements AllGenreFragment.OnAllGenreFragmentListener {

    @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_container, container, false);
    }

    @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        initialLoad();
    }

    private void initialLoad() {
        getChildFragmentManager()
                .beginTransaction()
                .add(R.id.container, AllGenreFragment.newInstance())
                .commit();
    }

    @Override public void OnItemClick() {
        getChildFragmentManager()
                .beginTransaction()
                .replace(R.id.container, AllAnimeFragment.newInstance())
                .commit();
    }
}

Этот фрагмент должен реализовать обратный вызов из AllGenreFragment для обработки транзакции фрагмента.

также макет xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

На следующем шаге добавьте фрагмент выше в ViewPager, мы используем ContainerFragment вместо AllGenreFragment.

  @Override
            public Fragment getItem(int position) {
                switch (position) {
                    case 0:
                        return ContainerFragment().newInstance();
                    case 1:
                        return DashboardFragment.newInstance();
                    case 2:
                        return NotificationFragment.newInstance();
                }
                return null;
            }

Хорошо, теперь вернемся к AllGenreFragment, мы должны создать CallBack, который мы реализуем в ContainerFragment

public interface AllGenreFragmentListener {
     onItemClicked();
}

, а затем,

private AllGenreFragmentListener  listener;



@Override public void onAttach(Context context) {
        super.onAttach(context);
        if (getParentFragment() instanceof AllGenreFragmentListener) {
            listener = (AllGenreFragmentListener) getParentFragment();
        }
    }

, поэтому мы имеемэкземпляр AllGenreFragmentListener, теперь, всякий раз, когда listener вызывает onItemClicked, будет вызываться метод onItemClicked in ContainerFragment.

Хорошо, давайте сделаем это,

создайте ниже переменную и метод в вашем AllGenreAdapter:

private AllGenreFragmentListener listener;

public void setListener(AllGenreFragmentListener listener) {
   this.listener = listener;
}

и обновите ваш ViewHodler

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

                    Toast.makeText(context, "Genre: " + genre_title.getText().toString(), Toast.LENGTH_SHORT).show();
                   if (listener != null)
                      listener.onItemClicked()
            });

        }

Не забудьте вызвать setListener метод в вашем AllGenreFragment, поэтому, пожалуйста, добавьте

@Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        if (allGenreAdapter != null) allGenreAdapter.setListener(listener);
    }

Вот и все,

Я набираю этот код вручную, а не в моей IDEпоэтому, возможно, он не скомпилируется, поэтому, пожалуйста, исправьте его, если вы столкнулись с какой-либо ошибкой компиляции.

Примечание

Если вы хотите сохранить поведение кнопки BACK,переопределить OnBackPressed в вашем MainActivity

@Override public void onBackPressed() {
        Fragment f = getCurrentFragment();
        if (f != null) {
            if (f.getChildFragmentManager().getBackStackEntryCount() > 1) {
                f.getChildFragmentManager().popBackStack();
            } else {
                super.onBackPressed();
            }

        } else {
            super.onBackPressed();
        }

    }

    public Fragment getCurrentFragment() {
        return (Fragment) viewPager.getAdapter()
                .instantiateItem(viewPager, viewPager.getCurrentItem());
    }

Кроме того, добавляйте фрагмент в backStack всякий раз, когда мы добавляем их в представление контейнера (в вашем ContainerFragment)

private void initialLoad() {
        getChildFragmentManager()
                .beginTransaction()
                .add(R.id.container, AllGenreFragment.newInstance())
                .addToBackStack(null)
                .commit();
    }

    @Override public void OnItemClick() {
        // change `replace` to  `add` and add more `.addToBackStack(null)`
        getChildFragmentManager()
                .beginTransaction()
                .add(R.id.container, AllAnimeFragment.newInstance())
                .addToBackStack(null)
                .commit();
    }
0 голосов
/ 18 декабря 2018

вы должны добавить контекст в конструктор вашего адаптера

public class AllGenreAdapter(Context context) extends RecyclerView.Adapter<AllGenreAdapter.ViewHolder> {
// ....... 
}

, а затем передать свою активность адаптеру, использовать его для замены вашего фрагмента

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...