从片段回收适配器返回空白屏幕中替换ViewPager内部的片段



我正在尝试替换ViewPager内部的当前活动片段时,当figern fragment的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;
        }
        
    }
    
    // ..........
    
}

allgerrefragment.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;
    }
}

您的方法不是很好,请在下面尝试:

  • 创建一个称为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 onItemClicked() {
        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时,ContainerFragment中的方法onItemClicked将被调用。

好吧,让我们做,

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()
            });
        }

不要忘记AllGenreFragment中的setListener方法,所以请添加

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

全部,

我手工键入此代码,而不是在我的IDE中键入该代码,因此也许不会编译,因此,如果您遇到任何编译错误,请修复它。

注意

如果要保留BACK按钮的行为,请在MainActivity中覆盖onBackPressed

@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());
    }

另外,每当我们将片段添加到容器视图(在您的ContainerFragment中)

时,将片段添加到backStack
private void initialLoad() {
        getChildFragmentManager()
                .beginTransaction()
                .add(R.id.container, AllGenreFragment.newInstance())
                .addToBackStack(null)
                .commit();
    }
    @Override public void onItemClicked() {
        // change `replace` to  `add` and add more `.addToBackStack(null)`
        getChildFragmentManager()
                .beginTransaction()
                .add(R.id.container, AllAnimeFragment.newInstance())
                .addToBackStack(null)
                .commit();
    }

您应该在适配器的构造函数中添加上下文

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

然后将您的活动传递给适配器,用它来替换片段

最新更新