Android:在RecyclerView中添加视图时的怪异反应

约翰·沙丁

我正在使用一个自定义的recyclerView,它可以有一个页脚和一个页眉,应该对动画有影响,这是正在发生的事情的视频:http : //www.videosprout.com/video?id= 00fae6ac-39ff-47b6 -b981-803d2773b67b

为什么每个视图都将一个位置移回原来的位置,而不是不这样做呢?

这是我的适配器:

public class AddEventsAdapter extends HFRecyclerViewAdapter<String, AddEventsAdapter.ViewHolder> {

    public AddEventsAdapter(Context context) {
        super(context);
    }

    @Override
    public void footerOnVisibleItem() {

    }

    @Override
    public void addData(int position, String item) {
        super.addData(position, item);
    }

    @Override
    public ViewHolder onCreateDataItemViewHolder(ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.event_item, parent, false);
        return new ViewHolder(v);
    }

    @Override
    public void onBindDataItemViewHolder(ViewHolder holder, int position) {
        holder.itemTv.setText(getData().get(position));
    }

    class ViewHolder extends RecyclerView.ViewHolder{
        TextView itemTv;
        public ViewHolder(View itemView) {
            super(itemView);
            itemTv = (TextView)itemView.findViewById(R.id.eventName);

        }
    }
}

实现:

    final AddEventsAdapter MyAdapter = new AddEventsAdapter(this);
    AddEventsRecycler.setAdapter(MyAdapter);
    AddEventsRecycler.setLayoutManager(new LinearLayoutManager(this));

    //add footer
    final View footerView = LayoutInflater.from(this).inflate(R.layout.events_footer, AddEventsRecycler, false);
    MyAdapter.setFooterView(footerView);

    footerView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            MyAdapter.addData(0, "Event number" + ++g);
        }
    });

    ArrayList<String> data = new ArrayList<>();
    data.add("Vacation");

    MyAdapter.setData(data);

自定义的RecyclerAdapter:

public abstract class HFRecyclerViewAdapter<T, VH extends RecyclerView.ViewHolder> extends BaseRecyclerViewAdapter<T> {

    public HFRecyclerViewAdapter(Context context) {
        super(context);
    }

    private static final int TYPE_HEADER = Integer.MAX_VALUE;
    private static final int TYPE_FOOTER = Integer.MAX_VALUE - 1;
    private static final int ITEM_MAX_TYPE = Integer.MAX_VALUE - 2;
    private RecyclerView.ViewHolder headerViewHolder;
    private RecyclerView.ViewHolder footerViewHolder;

    class HFViewHolder extends RecyclerView.ViewHolder {
        HFViewHolder(View v) {
            super(v);
        }
    }

    public void setHeaderView(View header){
        if (headerViewHolder == null || header != headerViewHolder.itemView) {
            headerViewHolder = new HFViewHolder(header);
            notifyDataSetChanged();
        }
    }

    public void setFooterView(View foot){
        if (footerViewHolder == null || foot != footerViewHolder.itemView) {
            footerViewHolder = new HFViewHolder(foot);
            notifyDataSetChanged();
        }
    }

    public void removeHeader(){
        if (headerViewHolder != null){
            headerViewHolder = null;
            notifyDataSetChanged();
        }
    }
    public void removeFooter(){
        if (footerViewHolder != null){
            footerViewHolder = null;
            notifyDataSetChanged();
        }
    }

    public boolean isHeader(int position){
        return hasHeader() && position == 0;
    }

    public boolean isFooter(int position){
        return hasFooter() && position == getDataItemCount() + (hasHeader() ? 1 : 0);
    }

    private int itemPositionInData(int rvPosition){
        return rvPosition - (hasHeader() ? 1 : 0);
    }
    private int itemPositionInRV(int dataPosition){
        return dataPosition + (hasHeader() ? 1 : 0);
    }

    @Override
    public void notifyMyItemInserted(int itemPosition) {
        notifyItemInserted(itemPositionInRV(itemPosition));
    }
    @Override
    public void notifyMyItemRemoved(int itemPosition) {
        notifyItemRemoved(itemPositionInRV(itemPosition));
    }

    @Override
    public void notifyMyItemChanged(int itemPosition) {
        notifyItemChanged(itemPositionInRV(itemPosition));
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == TYPE_HEADER) {
            return headerViewHolder;
        } else if (viewType == TYPE_FOOTER) {
            return footerViewHolder;
        }
        return onCreateDataItemViewHolder(parent, viewType);
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        if (!isHeader(position) && !isFooter(position))
            onBindDataItemViewHolder((VH)holder, itemPositionInData(position));

        if (isFooter(position)){
            footerOnVisibleItem();
        }
    }

    public abstract void footerOnVisibleItem();

    @Override
    public int getItemCount() {
        int itemCount = getDataItemCount();
        if (hasHeader()) {
            itemCount += 1;
        }
        if (hasFooter()) {
            itemCount += 1;
        }
        return itemCount;
    }

    @Override
    public int getItemViewType(int position) {
        if (isHeader(position)) {
            return TYPE_HEADER;
        }
        if (isFooter(position)) {
            return TYPE_FOOTER;
        }
        int dataItemType = getDataItemType(itemPositionInData(position));
        if (dataItemType > ITEM_MAX_TYPE) {
            throw new IllegalStateException("getDataItemType() must be less than " + ITEM_MAX_TYPE + ".");
        }
        return dataItemType;
    }

    public int getDataItemCount() {
        return super.getItemCount();
    }

    /**
     * make sure your dataItemType < Integer.MAX_VALUE-1
     *
     * @param position item view position in rv
     * @return item viewType
     */
    public int getDataItemType(int position){
        return 0;
    }


    public boolean hasHeader(){
        return headerViewHolder != null;
    }
    public boolean hasFooter(){
        return footerViewHolder != null;
    }

    public abstract VH onCreateDataItemViewHolder(ViewGroup parent, int viewType);

    public abstract void onBindDataItemViewHolder(VH holder, int position);



}

编辑:删除视图时,会发生同样的情况removeData(getAdapterPosition()

埃里克

为什么

之所以发生这种情况,是因为该元素被添加到数组的开头(索引0)。发生这种情况时,RecyclerView它将如视频中所示进行反应,因为它假装支持数据存储区是一个列表,并且所有元素都移到一个索引上,并且该元素插入到开头...恰好位于顶端。

您会看到,如果在适配器末尾添加元素,它将不会执行此丑陋的行为MyAdapter.addData(MyAdapter.getItemCount() - 1, "Event ");但是当然,这也不是您想要的,因为它是错误的索引...现在看来,现有元素实际上正在GUI和其他事物上跳一个索引...但这是一个有趣的实验,验证理论。

一个解法

仍然使用MyAdapter.addData(MyAdapter.getItemCount() - 1, "Event ");在数组末尾添加元素,但是使LinearLayoutManager显示元素反向!这可以通过以下方式完成:

您可能需要对页眉和页脚位于适配器中的位置进行某些操作,以确保它们始终保留为页眉和页脚RecyclerView.Adapter...但是一旦RecyclerView.LayoutManager显示反向。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何在Android中的RecyclerView的项目之间添加动态视图?

Android:滚动时,Recyclerview中的水平线视图闪烁

在本机反应中添加子视图

在数组中添加新的json对象时,视图不刷新。反应本机

Android Recyclerview添加其他视图

在NestedScrollView中的RecyclerView之后无法添加视图

如何在Android Studio中的Sticky Header RecyclerView上方添加固定视图?

在 Android 中滚动时更改 RecyclerView 中项目的视图位置

使用 Android 从 Firebase 获取数据时,在 recyclerview 中扩充子视图

当我在 android 中的 Recyclerview 上滚动时,项目视图的高度会降低

当视图离开屏幕时,Android动画停止在recyclerview中起作用

更改 recyclerview 视图布局中的约束 - android

Android MotionLayout + Recyclerview,recyclerview 中的视图不可点击

Android:正确删除视图并将其添加到recyclerView

在Android工具栏中添加自定义视图时,会有marginLeft

当我向布局中添加视图时,layout_weight发生更改(Android)

在Android中创建动态创建的视图时如何添加事件处理程序?

在视图组中添加视图时,layout_margin被忽略

在与打字稿本机反应中添加NavigationContainer时出错

在discord.py中添加反应角色时出错

在RecyclerView.Adapter中绑定视图时发生NullPointerException

与Butterknife绑定以在android中动态添加视图

如何在 recyclerview 中添加页脚视图,该视图从 DB 和反向布局中获取数据

在Android中单击RecyclerView时显示错误

在RecyclerView中隐藏视图

RecyclerView中的多个视图

在recyclerview中交换视图

如何在Android RecyclerView中缓存Viewholder视图引用

在recyclerview项目android中更改视图之间的焦点