Элемент повторного просмотра не отображается после отмены - PullRequest
0 голосов
/ 05 октября 2018

Я новичок в программировании Android, в моем приложении я использую recycleview, чтобы показать содержимое базы данных SQLite, я читаю базу данных в Arraylist, который я показываю в recycleview.Я успешно реализовал функцию смахивания влево (удаление элемента) и вправо (изменение элемента).У меня проблема во время левого пролистывания, значит, с помощью функции удаления я реализовал функцию отмены:

    void restoreItem( SequenceItem sequenceItem, int position) {
    sequenceItemList.add(position, sequenceItem);
    notifyItemInserted(position);
    notifyItemRangeChanged(position, getItemCount());
    }

(SequenceItem - мой пользовательский класс элементов, а sequenceItemList - мой массив)

Эта функция хорошо работает, если я удаляю элемент списка между первым или последним элементом и отменяю их.Если я удаляю первый или последний элемент в повторном просмотре после отмены, я вижу пустое место в этой позиции, макет элемента списка абсолютно не виден, он просто белый.Затем я добавил «recycleview.scrollToPosition» после вызова метода восстановления:

    recycleAdapter.restoreItem(deletedItem, deletedIndex);
    recyclerView.scrollToPosition(deletedIndex);

После этого изменения, если я удаляю первый элемент из повторного просмотра, а затем нажимаю «Отменить», ранее удаленный элементвосстановлен правильно, но если я удаляю последний элемент из повторного просмотра и нажимаю кнопку отмены, я все равно вижу пустой (белый) элемент.

Не могли бы вы мне помочь, в чем может быть проблема?Если вам нужна дополнительная информация, я могу опубликовать больше кода или рассказать больше о приложении.

РЕДАКТИРОВАНИЕ 06.10.2018 Я прикрепил класс RecyclerItemTouchHelper, потому что, по моему мнению, это вызывает проблему:

public class RecyclerItemTouchHelper extends ItemTouchHelper.SimpleCallback {
    private RecyclerItemTouchHelperListener listener;
    private Context mContext;

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

    //This is not used
    @Override
    public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder viewHolder1) {
        return false;
    }

    @Override
    public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
        if (listener != null) {
            listener.onSwiped(viewHolder, direction, viewHolder.getAdapterPosition());
        }
    }

    @Override
    public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
        View list_foreground = ((RecycleAdapter.mViewHolder)viewHolder).list_foreground;
        getDefaultUIUtil().clearView(list_foreground);
    }

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

    @Override
    public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
        if (viewHolder != null) {
            View list_foreground = ((RecycleAdapter.mViewHolder)viewHolder).list_foreground;
            getDefaultUIUtil().onSelected(list_foreground);
        }
    }

    @Override
    public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {

        float mdX = dX / 1;

        if(actionState == ItemTouchHelper.ACTION_STATE_SWIPE){

            Bitmap icon;
            Paint p = new Paint();

            Resources resources = mContext.getResources();

            View itemView = viewHolder.itemView;
            float height = (float) itemView.getBottom() - (float) itemView.getTop();
            float width = height / 3;

            if(dX > 0){ //Swipe right
                p.setColor(Color.parseColor("#D32F2F"));
                RectF background = new RectF((float) itemView.getLeft() , (float) itemView.getTop(), mdX, (float) itemView.getBottom());
                c.drawRect(background,p);
                icon = BitmapFactory.decodeResource(resources, R.drawable.ic_delete_white);
                RectF icon_dest = new RectF((float) itemView.getLeft() + width ,(float) itemView.getTop() + width,(float) itemView.getLeft()+ 2*width,(float)itemView.getBottom() - width);
                c.drawBitmap(icon,null,icon_dest,p);
            } else { //Swipe left
                p.setColor(Color.parseColor("#388E3C"));
                RectF background = new RectF((float) itemView.getRight() + mdX, (float) itemView.getTop(), (float) itemView.getRight(), (float) itemView.getBottom());
                c.drawRect(background,p);
                icon = BitmapFactory.decodeResource(resources, R.drawable.ic_edit_white);
                RectF icon_dest = new RectF((float) itemView.getRight() - 2*width ,(float) itemView.getTop() + width,(float) itemView.getRight() - width,(float)itemView.getBottom() - width);
                c.drawBitmap(icon,null,icon_dest,p);
            }
        }
        super.onChildDraw(c, recyclerView, viewHolder, mdX, dY, actionState, isCurrentlyActive);
    }

    @Override
    public void onChildDrawOver(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
        View list_foreground = ((RecycleAdapter.mViewHolder)viewHolder).list_foreground;
        getDefaultUIUtil().onDrawOver(c, recyclerView, list_foreground, dX, dY, actionState, isCurrentlyActive);
    }
}

А вот активность реализации свайпа:

    @Override
public void onSwiped(final RecyclerView.ViewHolder viewHolder, int direction, final int position) {
    //Swipe LEFT to DELETE
    if (direction == ItemTouchHelper.RIGHT) {
        Snackbar snackbar = Snackbar.make(rootLayout, "Phase " + (position + 1) + " is removed!", Snackbar.LENGTH_LONG);

        //Backup of removed item dor UNDO purpose
        final SequenceItem deletedItem = sequenceItemList.get(viewHolder.getAdapterPosition());
        final int deletedIndex = viewHolder.getAdapterPosition();

        //Remove the item from recyclerview
        recycleAdapter.removeItem(viewHolder.getAdapterPosition());

        snackbar.setAction(R.string.undo, new OnClickListener() {
            @Override
            public void onClick(View v) {
                //Restore deleted item
                recycleAdapter.restoreItem(deletedItem, deletedIndex);
                recyclerView.scrollToPosition(deletedIndex);

            }
        }).addCallback(new Snackbar.Callback() {
            @Override
            public void onDismissed(Snackbar snackbar, int dismissType) {
                super.onDismissed(snackbar, dismissType);

                if (dismissType != DISMISS_EVENT_ACTION) {
                    //Delete the item from the database
                    databaseHelper.removePhase(deletedItem);
                    Toast.makeText(getApplicationContext(), R.string.phase_successfully_deleted, Toast.LENGTH_LONG).show();
                }
            }
        });
        snackbar.setActionTextColor(getResources().getColor(R.color.warningColor));
        snackbar.show();
    }
    //Swipe RIGHT to EDIT
    else {
        Intent intent = new Intent(this, AddPhaseActivity.class);
        intent.putExtra("dbPosition", (long) viewHolder.itemView.getTag());
        intent.putExtra("rvPosition", position);
        recycleAdapter.notifyItemChanged(position);
        this.startActivity(intent);
    }
}

1 Ответ

0 голосов
/ 07 октября 2018

Ваш код в порядке.Единственное возможное место для этого странного исполнения - функция ниже.

@Override public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { View list_foreground = ((RecycleAdapter.mViewHolder)viewHolder).list_foreground; getDefaultUIUtil().clearView(list_foreground); }

Вы ошибаетесь в представлении.Попробуйте очистить корневой вид вашего элемента, например

@Override public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { View itemView= ((RecycleAdapter.mViewHolder)viewHolder).itemView; getDefaultUIUtil().clearView(itemView); }

ИЛИ

изменить свой public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) метод.

положить

View list_foreground = ((RecycleAdapter.mViewHolder)viewHolder).list_foreground; getDefaultUIUtil().onDraw(c, recyclerView, list_foreground, dX, dY, actionState, isCurrentlyActive);

вместо

super.onChildDraw(c, recyclerView, viewHolder, mdX, dY, actionState, isCurrentlyActive);

Это решит вашу проблему.

ОБЪЯСНЕНИЕ:

Источник проблемы в том, что onChildDraw вызывает метод

super.onChildDraw(c, recyclerView, viewHolder, mdX, dY, actionState, isCurrentlyActive);

И он вызывает onDraw(Canvas c, RecyclerView recyclerView, View view, float dX, float dY, int actionState, boolean isCurrentlyActive) функцию внутри передачи viewHolder.itemView в качестве аргумента дляview и реализации перевода в него, как

view.setTranslationX(dX); view.setTranslationY(dY);

Но четкое представление работает как

    @Override
    public void clearView(View view) {
        view.setTranslationX(0f);
        view.setTranslationY(0f);
    }

Так что в вашем случае функции onChildDraw и clearViewработать с разными взглядами.

...