【问题标题】:RecyclerView onSwiped behaving randomlyRecyclerView onSwiped 随机行为
【发布时间】:2020-06-10 03:21:00
【问题描述】:

我正在尝试开发像 Gmail 这样的功能,您可以在其中滑动删除。 这是我的主要片段,带有回收站视图。

public class MainFragment extends Fragment implements RecyclerItemTouchHelper.RecyclerItemTouchHelperListener {

RecyclerView recyclerView;
CoordinatorLayout coordinatorLayout;
RecyclerViewAdapter recyclerViewAdapter = null;
private View view;
private Context context = null;
ArrayList<Note> notes = new ArrayList<>();
ArrayList<Note> allNotes;
FloatingActionButton fab;
boolean isLoading = false;


private MainViewModel mViewModel;

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
                         @Nullable Bundle savedInstanceState) {
    View root = inflater.inflate(R.layout.main_fragment, container, false);
    view = root;

    recyclerView = view.findViewById(R.id.recyclerView);
    ItemTouchHelper.SimpleCallback itemTouchHelperCallback = new RecyclerItemTouchHelper(0, ItemTouchHelper.LEFT, this);
    new ItemTouchHelper(itemTouchHelperCallback).attachToRecyclerView(recyclerView);

    return root;
}


@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    mViewModel = ViewModelProviders.of(this).get(MainViewModel.class);
    coordinatorLayout = view.findViewById(R.id.mainContent)
    populateNotesView();
}



@Override
public void onResume() {
    super.onResume();
}

public void populateNotesView() {
    MainViewModel obj = new MainViewModel();
    allNotes = obj.getData(getContext());
    notes.clear();
    for (int i = 0; i < 10 && i < allNotes.size(); i++) {
        notes.add(allNotes.get(i));
    }

    initAdapter(notes);
}

private void initAdapter(ArrayList<Note> notes) {
    recyclerViewAdapter = new RecyclerViewAdapter(notes, getFragmentManager());
    recyclerView.setAdapter(recyclerViewAdapter);
    initScrollListener();
}

@Override
public void onDelete(final RecyclerView.ViewHolder viewHolder, int position) {

    if (viewHolder instanceof RecyclerViewAdapter.ItemViewHolder) {
        ArrayList<Note> notesList = allNotes;
        String name = notesList.get(viewHolder.getAdapterPosition()).getText();

        final Note deletedItem = notesList.get(viewHolder.getAdapterPosition());
        final int deletedIndex = viewHolder.getAdapterPosition();
        recyclerViewAdapter = new RecyclerViewAdapter(notesList,  getFragmentManager());
        recyclerViewAdapter.removeItem(viewHolder.getAdapterPosition(), getContext());
        Snackbar snackbar = Snackbar.make(coordinatorLayout, name + " removed from cart!", Snackbar.LENGTH_LONG);
        snackbar.setAction("UNDO", new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                recyclerViewAdapter.restoreItem(deletedItem, deletedIndex, getContext());
                getFragmentManager().beginTransaction()
                .replace(R.id.mainContent, MainFragment.newInstance())
                .commitNow();
            }
        });
        snackbar.setActionTextColor(Color.YELLOW);
        snackbar.show();

        //Reloading fragment
        getFragmentManager().beginTransaction()
                .replace(R.id.mainContent, MainFragment.newInstance())
                .commitNow();
    }


}
}

这是我的 RecyclerItemTouchHelper

public class RecyclerItemTouchHelper extends ItemTouchHelper.SimpleCallback {
    private RecyclerItemTouchHelperListener listener;
    private boolean delete = false;

    public RecyclerItemTouchHelper(int dragDirs, int swipeDirs, RecyclerItemTouchHelperListener listener) {
        super(dragDirs, swipeDirs);
        this.listener = listener;
    }

    @Override
    public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
        return true;
    }

    @Override
    public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
        if (viewHolder != null) {
            final View foregroundView = ((RecyclerViewAdapter.ItemViewHolder) viewHolder).viewForeground;

            getDefaultUIUtil().onSelected(foregroundView);
        }
    }

    @Override
    public void onChildDrawOver(Canvas c, RecyclerView recyclerView,
                                RecyclerView.ViewHolder viewHolder, float dX, float dY,
                                int actionState, boolean isCurrentlyActive) {
        final View foregroundView = ((RecyclerViewAdapter.ItemViewHolder) viewHolder).viewForeground;
        getDefaultUIUtil().onDrawOver(c, recyclerView, foregroundView, dX, dY,
                actionState, isCurrentlyActive);
    }


    @Override
    public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
        final View foregroundView = ((RecyclerViewAdapter.ItemViewHolder) viewHolder).viewForeground;
        getDefaultUIUtil().clearView(foregroundView);
    }

    @Override
    public void onChildDraw(Canvas c, RecyclerView recyclerView,
                            final RecyclerView.ViewHolder viewHolder, float dX, float dY,
                            int actionState, boolean isCurrentlyActive) {
            final View foregroundView = ((RecyclerViewAdapter.ItemViewHolder) viewHolder).viewForeground;

            getDefaultUIUtil().onDraw(c, recyclerView, foregroundView, dX, dY,
                    actionState, isCurrentlyActive);

    }

    @Override
    public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
        listener.onDelete(viewHolder, viewHolder.getAdapterPosition());
    }

    @Override
    public int convertToAbsoluteDirection(int flags, int layoutDirection) {
        return super.convertToAbsoluteDirection(flags, layoutDirection);
    }

    public interface RecyclerItemTouchHelperListener {
        void onDelete(RecyclerView.ViewHolder viewHolder, int position);
    }
}

现在刷一个 recyclerview 项目,不会每次都调用 onSwiped 方法。我完全刷了这个项目。

编辑:添加的任何新项目都已成功删除,但已添加的项目不会被删除。

编辑 2:适配器

 public void removeItem(int position, Context context) {
        MainViewModel obj = new MainViewModel();
        obj.deleteData(context, mItemList.get(position).getText());
        mItemList.remove(position);
        notifyItemRemoved(position);
        notifyItemRangeChanged(position, mItemList.size());
    }

    public void restoreItem(Note item, int position, Context context) {
        Util.newInstance().save(context, item.getText());
        mItemList.add(position, item);
        notifyItemInserted(position);
        notifyItemRangeChanged(position, mItemList.size());
    }

感谢任何帮助。 提前致谢。

【问题讨论】:

  • 尝试在 onMove 中返回 false。
  • 不,它仍然在随机工作。

标签: java android android-recyclerview


【解决方案1】:

该项目未被删除,因为您通过使用以下代码行使用 onDelete() 中的原始列表:

ArrayList<Note> notesList = allNotes;

这意味着每当你删除一个项目时,你只是回到原来的列表。

第二个问题是当您使用 sanckbar 操作撤消删除时,您可以通过调用此操作来执行相同的操作:

populateNotesView();

要解决这个问题,您需要从您提供给RecyclerView 适配器的原始列表中删除该项目,然后调用notifyItemRemoved() 来获取已删除的位置。

为此,请将onDelete() 更改为:

@Override
public void onDelete(final RecyclerView.ViewHolder viewHolder, int position) {

    if (viewHolder instanceof RecyclerViewAdapter.ItemViewHolder) {

        String name = allNotes.get(viewHolder.getAdapterPosition()).getText();

        final Note deletedItem = allNotes.get(viewHolder.getAdapterPosition());
        final int deletedIndex = viewHolder.getAdapterPosition();
        allNotes.remove(deletedIndex);
        recyclerViewAdapter.notifyItemRemoved(deletedIndex);

       Snackbar snackbar = Snackbar.make(coordinatorLayout, name + " removed from cart!", Snackbar.LENGTH_LONG);
        snackbar.setAction("UNDO", new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                allNotes.add(deletedIndex, deletedItem);
                recyclerViewAdapter.notifyItemInserted(deletedIndex);
            }
        });
    }
}

【讨论】:

  • 我正在通过以下方式更新 adpater 中的注释列表:recyclerViewAdapter.removeItem(viewHolder.getAdapterPosition(), getContext());
  • 你能发布你的适配器吗?
  • 我已经更新了代码并尝试删除 populateNotesView();
  • 您每次调用 removeItem 方法时都会实例化 MainViewModel,因此它会创建一个具有原始大小的全新便笺项目列表。确保您使用的是单个实例MainViewModel 和其中的静态注释列表.. 似乎您正在通过将字符串传递给 obj.deleteData 来删除基于文本的项目,只需传递位置并使用 list.remove() 将其删除 .. 希望这个目标现在
  • 每次我向列表中添加新项目或重新加载片段时,我都可以删除。但只有一项被成功删除。
猜你喜欢
  • 2019-06-15
  • 2017-03-12
  • 1970-01-01
  • 2016-03-18
  • 2015-07-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-10
相关资源
最近更新 更多