Android RecyclerView动态更新多个视图类型

Android RecyclerView动态更新多个视图类型,android,android-recyclerview,recyclerview-layout,Android,Android Recyclerview,Recyclerview Layout,我试图弄清楚异构回收视图是如何工作的,并根据我的需要进行调整。我有3个布局。第一个是带有底部条的标题(在本例中不在底部),并且始终显示该标题。其他2个布局将根据单击底部栏中的哪个选项卡进行切换。底部栏中的第一个选项卡将显示网格布局,第二个选项卡应显示列表布局。我已经设法实现了它,但有一个轻微的轻弹和列表的变化是不是真的顺利。此外,单击第二个选项卡时,第一个选项卡仍处于选中状态。第二次单击第二个选项卡时,它将被选中。如何使其更平滑,并在第一次单击时选择特定选项卡 适配器 public cl

我试图弄清楚异构回收视图是如何工作的,并根据我的需要进行调整。我有3个
布局
。第一个是带有
底部条的标题(在本例中不在底部),并且始终显示该标题。其他2个
布局
将根据单击
底部栏
中的哪个选项卡进行切换。
底部栏中的第一个选项卡将显示
网格布局
,第二个选项卡应显示
列表布局
。我已经设法实现了它,但有一个轻微的轻弹和列表的变化是不是真的顺利。此外,单击第二个选项卡时,第一个选项卡仍处于选中状态。第二次单击第二个选项卡时,它将被选中。如何使其更平滑,并在第一次单击时选择特定选项卡

适配器

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

    private final int HEADER_TYPE = 0;
    private final int IMAGE_GRID_TYPE = 1;
    private final int IMAGE_LIST_TYPE = 2;
    private final int cellSize;
    private Context mContext;
    private List<Home> mHomeList;
    private boolean onBind;
    private OnHeaderItemClickedListener mListener;
    int selectedPosition;

    public ProfileAdapter(Context context, List<Home> homeList) {
        this.mContext = context;
        this.mHomeList = homeList;
        this.cellSize = Utils.getScreenWidth(context) / 3;
    }

    public interface OnHeaderItemClickedListener {
        void onTabGridClicked();

        void onTabListClicked();
    }

    @Override
    public void onDetachedFromRecyclerView(RecyclerView recyclerView) {
        super.onDetachedFromRecyclerView(recyclerView);
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        LayoutInflater inflater = LayoutInflater.from(mContext);

        switch (viewType) {
            case HEADER_TYPE:
                View viewHeader = inflater.inflate(R.layout.item_profile_header, parent, false);
                StaggeredGridLayoutManager.LayoutParams lp1 = (StaggeredGridLayoutManager.LayoutParams) viewHeader.getLayoutParams();
                lp1.setFullSpan(true);
                viewHeader.setLayoutParams(lp1);
                return new ProfileAdapter.HeaderHolder(viewHeader);
            case IMAGE_GRID_TYPE:
                View viewGridImage = inflater.inflate(R.layout.item_profile_grid_image, parent, false);
                StaggeredGridLayoutManager.LayoutParams layoutParams = (StaggeredGridLayoutManager.LayoutParams) viewGridImage.getLayoutParams();
                layoutParams.height = cellSize;
                layoutParams.width = cellSize;
                layoutParams.setFullSpan(false);
                viewGridImage.setLayoutParams(layoutParams);
                return new ImageGridHolder(viewGridImage);
            case IMAGE_LIST_TYPE:
                View viewListImage = inflater.inflate(R.layout.item_profile_list_image, parent, false);
                StaggeredGridLayoutManager.LayoutParams lp3 = (StaggeredGridLayoutManager.LayoutParams) viewListImage.getLayoutParams();
                lp3.setFullSpan(true);
                viewListImage.setLayoutParams(lp3);
                return new ImageListHolder(viewListImage);
        }
        return null;
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        switch (holder.getItemViewType()) {
            case HEADER_TYPE:
                onBind = true;
                bindHeader((HeaderHolder) holder, mHomeList.get(position));
                onBind = false;
                break;
            case IMAGE_GRID_TYPE:
                onBind = true;
                bindGridImage((ImageGridHolder) holder, mHomeList.get(position));
                onBind = false;
                break;
            case IMAGE_LIST_TYPE:
                onBind = true;
                bindListImage((ImageListHolder) holder, mHomeList.get(position));
                onBind = false;
                break;
        }
    }

    private void bindHeader(final HeaderHolder holder, Home home) {
        holder.getItemProfileHeaderBinding().setHome(home);
        holder.getItemProfileHeaderBinding().bottomBar.setOnTabSelectListener(new OnTabSelectListener() {
            @Override
            public void onTabSelected(@IdRes int tabId) {
                switch (tabId) {
                    case R.id.tab_grid:
                        if (!onBind) {
                            mListener.onTabGridClicked();
                            selectedPosition = holder.getLayoutPosition();
                            notifyItemChanged(selectedPosition);
                        }
                        break;
                    case R.id.tab_list:
                        if (!onBind) {
                            mListener.onTabListClicked();
                            selectedPosition = holder.getLayoutPosition();
                            notifyItemChanged(selectedPosition);
                        }
                        break;
                }
            }
        });
        adjustTabs(holder);
    }

    private void bindGridImage(ImageGridHolder holder, Home home) {
        holder.getItemProfileGridImageBinding().setHome(home);
        Uri uri = new Uri.Builder()
                .scheme(UriUtil.LOCAL_RESOURCE_SCHEME)
                .path(String.valueOf(R.drawable.ap_android_icon))
                .build();
        holder.getItemProfileGridImageBinding().ivImage.setImageURI(uri);
    }

    private void bindListImage(ImageListHolder holder, Home home) {
        holder.getItemProfileListImageBinding().setHome(home);
    }

    @Override
    public int getItemViewType(int position) {
        if (isPositionHeader(position)) {
            return HEADER_TYPE;
        }
        if (mHomeList.get(position).getGridListType() == 2) {
            return IMAGE_LIST_TYPE;
        } else {
            return IMAGE_GRID_TYPE;
        }
    }

    private boolean isPositionHeader(int position) {
        return position == 0;
    }

    @Override
    public int getItemCount() {
        return mHomeList.size();
    }

    private void adjustTabs(HeaderHolder holder) {
        holder.getItemProfileHeaderBinding().bottomBar.getTabWithId(R.id.tab_grid).setPadding(0, 30, 0, 0);
        holder.getItemProfileHeaderBinding().bottomBar.getTabWithId(R.id.tab_list).setPadding(0, 30, 0, 0);
        holder.getItemProfileHeaderBinding().bottomBar.getTabWithId(R.id.tab_group).setPadding(0, 30, 0, 0);
        holder.getItemProfileHeaderBinding().bottomBar.getTabWithId(R.id.tab_bookmark).setPadding(0, 30, 0, 0);
    }

    private static class HeaderHolder extends RecyclerView.ViewHolder {

        ItemProfileHeaderBinding mItemProfileHeaderBinding;

        HeaderHolder(View itemView) {
            super(itemView);
            mItemProfileHeaderBinding = DataBindingUtil.bind(itemView);
        }

        ItemProfileHeaderBinding getItemProfileHeaderBinding() {
            return mItemProfileHeaderBinding;
        }
    }

    private static class ImageGridHolder extends RecyclerView.ViewHolder {

        ItemProfileGridImageBinding mItemProfileGridImageBinding;

        ImageGridHolder(View itemView) {
            super(itemView);
            mItemProfileGridImageBinding = DataBindingUtil.bind(itemView);
        }

        ItemProfileGridImageBinding getItemProfileGridImageBinding() {
            return mItemProfileGridImageBinding;
        }
    }

    private static class ImageListHolder extends RecyclerView.ViewHolder {

        ItemProfileListImageBinding mItemProfileListImageBinding;

        ImageListHolder(View itemView) {
            super(itemView);
            mItemProfileListImageBinding = DataBindingUtil.bind(itemView);
        }

        ItemProfileListImageBinding getItemProfileListImageBinding() {
            return mItemProfileListImageBinding;
        }
    }

    public void addOnHeaderItemClickListener(OnHeaderItemClickedListener listener) {
        this.mListener = listener;
    }
}
编辑


我添加了
notifyDataSetChanged()而不是
notifyItemChanged(selectedPosition)并且更改是即时的,但是第二个选项卡看起来从未被选中,并且我无法在第一个和第二个选项卡之间切换。我必须点击第三个才能回到第一个。就好像标签的位置被卡住了。

如果使用notifyItemRangeChanged(0,yourList.size()),您将获得更平滑的过渡,而不是闪烁。在使用dynamic RecyclerView时,我在使用notifyDatasetChanged时遇到了一些奇怪的渲染问题,切换到notifyItemRangeChanged修复了这个问题。嗯,我尝试了
notifyItemRangeChanged
,它在选项卡上实现了这一点,但是我的列表和
layoutmanager
被搞砸了
notifyDataSetChanged
起到了作用,只是标签混淆了…@Neil我刚刚尝试了
notifyItemRangeChanged
,它确实更流畅。但是,选项卡不是第一次切换的。。。
    public class ProfileFragment extends BaseFragment implements ProfileAdapter.OnHeaderItemClickedListener {

    private static final String ARG_PARAM1 = "param1";

    FragmentProfileMultipleBinding mBinder;
    FragmentManager mFragmentManager;
    Home mHome;
    ProfileAdapter mAdapter;
    List<Home> mHomeList;
    StaggeredGridLayoutManager mManager;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        mBinder = DataBindingUtil.inflate(inflater, R.layout.fragment_profile_multiple, container, false);
        mFragmentManager = getChildFragmentManager();
        mHome = new Home();
        populateList();
        mManager = new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL);
        mAdapter = new ProfileAdapter(getContext(), mHomeList);
        mBinder.rvGrid.setLayoutManager(mManager);
        mBinder.rvGrid.setAdapter(mAdapter);
        mAdapter.addOnHeaderItemClickListener(this);
        setUIListeners();
        return mBinder.getRoot();
    }

    private void populateList() {
        for (int i = 0; i < 20; i++) {
            mHomeList.add(i, mHome);
        }
    }

    private void populateUpdatedList() {
        for (Home home : mHomeList) {
            home.setGridListType(2);
        }
    }

    private void populateGridList() {
        for (Home home : mHomeList) {
            home.setGridListType(5);
        }
    }

    @Override
    public void onTabGridClicked() {
        populateGridList();
        mManager = new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL);
    }

    @Override
    public void onTabListClicked() {
        populateUpdatedList();
        mManager = new StaggeredGridLayoutManager(1, StaggeredGridLayoutManager.VERTICAL);
    }
}