Search code examples
androidandroid-recyclerviewandroid-alertdialogitemtouchhelper

How to restore swiped item from RecyclerView after dialog show?


I am using ItemTouchHelper with AlertDialog. The problem is when user swipe the element to the right side. AlertDialog with EditText is show at the screen. Now I want to do something like that:

  • When user press "save" button the element disappears not removed, only "go out" from whole RecyclerView list.

  • When "cancel" button is pressed the element should return to the same place that it was before (It was be pretty that it will be the animation for mAdapter.notifyItemChanged(); or mAdapter.notifyItemInserted();

So I tried two solutions but without success.

itemTouchHelper = new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0,
                ItemTouchHelper.RIGHT) {
            @Override
            public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
                return false;
            }
            @Override
            public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
                    position = viewHolder.getAbsoluteAdapterPosition(); // 2. solution
                    openDialog();
                    vieholder2 = viewHolder; // 1. Solution
            }
        });
        itemTouchHelper.attachToRecyclerView(recyclerView);

First I tried implemented my own interface and after user press "cancel" button interface should be invoke and set code below:
itemTouchHelper.startSwipe(vieholder2);

Second:

After interface is invoked I set mAdapter.notifyItemChanged(position);
Both solutions works good, directly in onSwiped method in ItemTouchHelper, but after method was triggered and Dialog is showing. Solutions aren't working.

So how can I return the invisible item back to the RecyclerView list after "cancel" button on Dialog is clicked?

I am using LiveData if it is helpful.

EDIT
Fragment class.

package com.example.application;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import androidx.activity.result.ActivityResult;
import androidx.activity.result.ActivityResultCallback;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
/**
 * A simple {@link Fragment} subclass.
 * Use the {@link Main_Database_fragment#newInstance} factory method to
 * create an instance of this fragment.
 */
public class Main_Database_fragment extends Fragment implements Dialog_Amount.Dialog_AmountListener {

    private View rootView;
    private RecyclerView recyclerView;
    private Recycler_Adapter mAdapter;
    private RecyclerView.LayoutManager mLayoutManager;
    private Item_get_VIEWMODEL item_get_viewmodel;
    private ActivityResultLauncher<Intent> start_next_activity;
    private Item_get item_get;
    int pospos;
    ItemTouchHelper itemTouchHelper;
    RecyclerView.ViewHolder viewholder;
    int deleted = 0;
    private int id;
    private int type;
    private int package_category;
    Item_get item_get2;
    int positionItem;
    // TODO: Rename parameter arguments, choose names that match
    // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
    private static final String ARG_PARAM1 = "param1";
    private static final String ARG_PARAM2 = "param2";
    // TODO: Rename and change types of parameters
    private String mParam1;
    private String mParam2;

    public Main_Database_fragment() {
        // Required empty public constructor
    }

    /**
     * Use this factory method to create a new instance of
     * this fragment using the provided parameters.
     *
     * @param param1 Parameter 1.
     * @param param2 Parameter 2.
     * @return A new instance of fragment Main_Database_fragment.
     */
    // TODO: Rename and change types and number of parameters
    public static Main_Database_fragment newInstance(String param1, String param2) {
        Main_Database_fragment fragment = new Main_Database_fragment();
        Bundle args = new Bundle();
        args.putString(ARG_PARAM1, param1);
        args.putString(ARG_PARAM2, param2);
        fragment.setArguments(args);
        return fragment;
    }


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mParam1 = getArguments().getString(ARG_PARAM1);
            mParam2 = getArguments().getString(ARG_PARAM2);
        }

    }

    @Override
    public View onCreateView(final LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        rootView = inflater.inflate(R.layout.fragment_main__database_fragment,container,false);
        return rootView;
    }


    @Override
    public void onViewCreated(@NonNull final View view, @Nullable final Bundle savedInstanceState) {
        build_RecyclerView();
        mAdapter.setOnItemClickListener(new Recycler_Adapters_items() {

            @Override
            public void onEditClick(Item_get item_get) {
                Intent intent = new Intent(getActivity(), Edit_Delete_details.class);
                type = item_get.food.getCode();
                package_category = item_get.package_type.getCode();
                intent.putExtra(Edit_Delete_details.EXTRA_DATA, item_get);
                intent.putExtra(Edit_Delete_details.EXTRA_ID, item_get.getId());
                intent.putExtra(Edit_Delete_details.EXTRA_CATEGORY, type);
                intent.putExtra(Edit_Delete_details.EXTRA_PACKAGE_TYPE,package_category);
                start_next_activity.launch(intent);
            }

            @Override
            public void onDeleteClick(Item_get item_get) {
                item_get_viewmodel.delete(item_get);
            }

            @Override
            public void onItemClick(Item_get item_get) {
                Intent intent = new Intent(getActivity(), Product_specific_detail.class);
                intent.putExtra(Product_specific_detail.EXTRA_ID_2, item_get.getId());
                start_next_activity.launch(intent);

            }
        });
        item_get_viewmodel = new ViewModelProvider(this).get(Item_get_VIEWMODEL.class);
        item_get_viewmodel.getAll_ItemsModel().observe(getViewLifecycleOwner(), new Observer<List<Item_get>>() {
            @Override
            public void onChanged(List<Item_get> item_gets) {
                mAdapter.submitList(item_gets);
                mAdapter.copylist(item_gets);
            }
        });

        itemTouchHelper = new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0,
                ItemTouchHelper.RIGHT) {
            @Override
            public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
                return false;
            }

            @Override
            public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {

                positionItem = viewHolder.getAbsoluteAdapterPosition();
                openDialog();
                item_get2 = mAdapter.getItemAt(viewHolder.getAbsoluteAdapterPosition());
                deleted = viewHolder.getAbsoluteAdapterPosition();
                viewholder = viewHolder;
            }
        });
        itemTouchHelper.attachToRecyclerView(recyclerView);
        super.onViewCreated(view, savedInstanceState);
    }
    public void build_RecyclerView(){
        recyclerView = rootView.findViewById(R.id.recycler_edit_del_product);
        recyclerView.setHasFixedSize(true);
        mLayoutManager = new LinearLayoutManager(getActivity());
        recyclerView.setLayoutManager(mLayoutManager);
        recyclerView.setItemAnimator(new DefaultItemAnimator());
        mAdapter = new Recycler_Adapter();
        recyclerView.setAdapter(mAdapter);
        start_next_activity = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),
                new ActivityResultCallback<ActivityResult>() {
                    @Override
                    public void onActivityResult(ActivityResult result) {
                        if(result.getResultCode() == Activity.RESULT_OK){
                            Intent intent = result.getData();
                            assert intent != null;
                            id = intent.getIntExtra(Edit_Delete_details.EXTRA_ID,-1);
                            if(id == -1){
                                Toast.makeText(getContext(),"Error", Toast.LENGTH_SHORT).show();
                                return;
                            }else if(id == -5){
                                item_get = intent.getParcelableExtra(Edit_Delete_details.EXTRA_DATA);
                                item_get.setId(id);
                                item_get_viewmodel.delete(item_get);
                                Toast.makeText(getContext(),"Delete",Toast.LENGTH_SHORT).show();
                            }else {
                                item_get = intent.getParcelableExtra(Edit_Delete_details.EXTRA_DATA);
                                type = intent.getIntExtra(Edit_Delete_details.EXTRA_CATEGORY, -1);
                                package_category = intent.getIntExtra(Edit_Delete_details.EXTRA_PACKAGE_TYPE, -1);
                                if(type == -1){
                                    Toast.makeText(getContext(),"Category may not be updated", Toast.LENGTH_LONG).show();
                                }else {
                                    set_food_type(type);
                                }
                                if(package_category == -1){
                                    Toast.makeText(getContext(),"Packages may not be updated", Toast.LENGTH_LONG).show();
                                }else {
                                    set_packages_type(package_category);
                                }
                                item_get.setId(id);
                                item_get_viewmodel.update(item_get);
                                Toast.makeText(getContext(),"Update",Toast.LENGTH_SHORT).show();
                            }
                        }
                    }
                }
        );

    }


    //Set our foodType from int to enum and later we pass it to db to update;
    public void set_food_type(int type){
        switch (type){
            case 1:
                item_get.food = Item_get.Food.SWEETS;
                break;
            case 2:
                item_get.food = Item_get.Food.VEGETABLES_FRUITS;
                break;
            case 3:
                item_get.food = Item_get.Food.DRINKS;
                break;
            case 4:
                item_get.food = Item_get.Food.OTHER;
                break;
            default:
                break;
        }
    }
    // Same as it is with food. Difference is Package Category enum not Package Type enum;
    public void set_packages_type(int type){
        switch (type){
            case 1:
                item_get.package_type = Item_get.Package_type.PACKAGE_BOX;
                break;
            case 2:
                item_get.package_type = Item_get.Package_type.PIECE;
                break;
            case 3:
                item_get.package_type = Item_get.Package_type.OTHER_PACK;
                break;
            default:
                break;
        }
    }
    public void openDialog(){
        Dialog_Amount dialog_amount = new Dialog_Amount();
        dialog_amount.setCancelable(false);
        dialog_amount.show(getChildFragmentManager(),"This is dialog");
    }

    @Override
    public void applyText(int text) {
        if(text != -1){
            item_get2.setNameProduct(item_get2.getNameProduct());
            item_get2.setDate_buy(null);
            item_get2.setAmount(0);
            int a = item_get2.food.getCode();
            int b = item_get2.package_type.getCode();
            item_get2.setPrice(0.0);
            item_get2.setValue(0.0);
            item_get2.setTo_shop(1);
            item_get2.setAmount_toShop(text);
            item_get_viewmodel.update(item_get2);

        }else {
            mAdapter.add_SingleItem(positionItem,item_get2);
            mAdapter.notifyItemInserted(positionItem);
        }
    }
}

My Adapter.

package com.example.application;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.DiffUtil;
import androidx.recyclerview.widget.ListAdapter;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;

public class Recycler_Adapter extends ListAdapter<Item_get,Recycler_Adapter.recyclerViewHolder> {

    public Recycler_Adapters_items clickListener;
    private List<Item_get> data_list2;
    private List<Item_get> data_list2_full;
    public Recycler_Adapter() {
        super(DIFF_CALLBACK);

    }
    private static final DiffUtil.ItemCallback<Item_get> DIFF_CALLBACK = new DiffUtil.ItemCallback<Item_get>() {
        @Override
        public boolean areItemsTheSame(@NonNull Item_get oldItem, @NonNull Item_get newItem) {
            return oldItem.getId() == newItem.getId();
        }

        @Override
        public boolean areContentsTheSame(@NonNull Item_get oldItem, @NonNull Item_get newItem) {
            return oldItem.getNameProduct().equals(newItem.getNameProduct()) && oldItem.getAmount() == newItem.getAmount()
                    && oldItem.food.getCode() == newItem.food.getCode() && oldItem.package_type.getCode() == newItem.package_type.getCode();
        }
    };

    public void copylist(List<Item_get> item_gets){
        if (data_list2 != null){
            data_list2.clear();
        }else {
            data_list2 = new ArrayList<>();
        }
        data_list2.addAll(item_gets);
        if(data_list2_full != null){
            data_list2_full.clear();
            data_list2_full.addAll(data_list2);
        }else{
            data_list2_full = new ArrayList<>(data_list2);
        }

    }

   public void add_SingleItem(int position, List<Item_get> item_get){
        item_get.add(position, (Item_get) item_get);
    }

    public void setOnItemClickListener(Recycler_Adapters_items mClickListener) {
        clickListener = mClickListener;
    }


    public  class recyclerViewHolder extends RecyclerView.ViewHolder {
        public ImageView mImageView1;
        public ImageView mImageView2;
        public ImageView mImageView3;
        public TextView mTextView1;
        public TextView mTextView2;
        public TextView mTextView3;
        public TextView mTextView4;

        public recyclerViewHolder(final View itemView, final Recycler_Adapters_items listener) {
            super(itemView);
            mImageView1 = itemView.findViewById(R.id.rec_image);
            mImageView2 = itemView.findViewById(R.id.rec_image_edit);
            mImageView3 = itemView.findViewById(R.id.rec_image_del);
            mTextView1 = itemView.findViewById(R.id.rec_text_1);
            mTextView2 = itemView.findViewById(R.id.rec_text_2);
            mTextView3 = itemView.findViewById(R.id.rec_text_3);
            mTextView4 = itemView.findViewById(R.id.rect_text_4);


            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (listener != null) {
                        int position = getAbsoluteAdapterPosition();
                        if (position != RecyclerView.NO_POSITION) {
                            listener.onItemClick(getItem(position));
                        }
                    }
                }
            });
            mImageView2.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (listener != null) {
                        int position = getAbsoluteAdapterPosition();
                        if (position != RecyclerView.NO_POSITION) {
                            listener.onEditClick(getItem(position));
                        }
                    }
                }
            });
            mImageView3.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (listener != null) {
                        int position = getAbsoluteAdapterPosition();
                        if (position != RecyclerView.NO_POSITION) {
                            listener.onDeleteClick(getItem(position));
                        }
                    }
                }
            });
        }
    }


    @NonNull
    @Override
    public recyclerViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_template, parent, false);
        return new recyclerViewHolder(v,clickListener);

    }

    @Override
    public void onBindViewHolder(@NonNull recyclerViewHolder holder, int position) {
        Item_get currentItem = getItem(position);
        currentItem.setId(currentItem.getId());
        holder.mTextView1.setText(currentItem.getNameProduct());

        if (currentItem.food == Item_get.Food.SWEETS) {
            holder.mTextView2.setText(R.string.sweets);
        }
        if (currentItem.food == Item_get.Food.Vegetables) {
            holder.mTextView2.setText(R.string.vegetables);
        }
        if (currentItem.food == Item_get.Food.drinks) {
            holder.mTextView2.setText(R.string.drinks);
        }
        if (currentItem.food == Item_get.Food.other) {
            holder.mTextView2.setText(R.string.other);
        }


        String amount = String.valueOf(currentItem.getAmount());
        holder.mTextView3.setText(amount);

        if(currentItem.package_type == Item_get.Package_type.PACKAGE_BOX){
            holder.mTextView4.setText(R.string.product_cat_pack_short);
        }else if(currentItem.package_type == Item_get.Package_type.PIECE){
            holder.mTextView4.setText(R.string.product_cat_piece);
        } else if(currentItem.package_type == Item_get.Package_type.OTHER_PACK){
            holder.mTextView4.setText(R.string.product_amount);
        }
        else {
            holder.mTextView4.setText(R.string.product_amount);
        }
    }

    public Item_get getItemAt(int position){
        return getItem(position);
    }
}

Solution

  • You need to do this in your Fragment class

      madapter.notifyItemChanged(viewholder.getAbsoluteAdapterPostion());