Swiping to delete items of recyclerview doesnt work - java

I am trying to add this function to my RecyclerView, that when I swipe one item either to the left or the right it gets deleted.
But when I execute my App I can't even swipe one of the items.
Appreciate any help
new ItemTouchHelper(itemTouchHelperCallback).attachToRecyclerView(mRecyclerView);
ItemTouchHelper.SimpleCallback itemTouchHelperCallback= new ItemTouchHelper.SimpleCallback(0,
ItemTouchHelper.LEFT | 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) {
mExampleList.remove(viewHolder.getAdapterPosition());
mAdapter.notifyDataSetChanged();
saveData();
}
By the way this RecyclerView is not located in my MainActivity but in a Fragment that can be opened from the Drawer menu in the MainActivity, so maybe the problem lies there?

Okay so I have finally found the problem.
I just had to initialize the ItemTouchHelper in the method where the RecyclerViewis built instead of in the onCreate method.
So this is what the code looks like:
private void buildRecyclerView() {
mRecyclerView = view.findViewById(R.id.recyclerview);
mLayoutManager = new LinearLayoutManager(getActivity());
mAdapter = new ExampleAdapter(mExampleList);
mRecyclerView.setLayoutManager(mLayoutManager);
new ItemTouchHelper(itemTochHelperCallback).attachToRecyclerView(mRecyclerView);
mRecyclerView.setAdapter(mAdapter);
}
ItemTouchHelper.SimpleCallback itemTochHelperCallback=new ItemTouchHelper.SimpleCallback(0,ItemTouchHelper.RIGHT | ItemTouchHelper.LEFT) {
#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) {
mExampleList.remove(viewHolder.getAdapterPosition());
mAdapter.notifyDataSetChanged();
}
};

Related

RecyclerView does not return to the same position after switching activity

I have implemented drag item in the recycler view using ItemTouchHelper class and it works well, but when I switch between activities the item position returns back to its default. I want the recycler view item position to remain the same even when activities are switched.
public RecyclerViewItemTouchHelper(Context context, RecyclerView recyclerView) {
super(ItemTouchHelper.UP | ItemTouchHelper.DOWN |
ItemTouchHelper.START | ItemTouchHelper.END, ItemTouchHelper.LEFT);
this.recyclerView = recyclerView;
this.context = context;
}
#Override
public boolean onMove(#NonNull RecyclerView recyclerView, #NonNull RecyclerView.ViewHolder viewHolder, #NonNull RecyclerView.ViewHolder target) {
int fromPosition = viewHolder.getAbsoluteAdapterPosition();
int toPosition = target.getAbsoluteAdapterPosition();
Collections.swap(MainActivity.dataArrayList, fromPosition, toPosition);
recyclerView.getAdapter().notifyItemMoved(fromPosition, toPosition);
return false;
}

Detecting up and down swipes on a Recyclerview in a fragment how can I do that?

So I have a recyclerview loaded with Firebase Firestore Documents and I want to see if it is beeing swiped up or down. Depending on the direction I want to make the adapter.startListening(); again and stop if he swipes down. I also want to hide a button if the user scrolls down. I just need to figure out how can I see if he does that ?
This piece of code was working with left and right but for some reason won´t with up and down ?
new ItemTouchHelper( new ItemTouchHelper.SimpleCallback(0,
ItemTouchHelper.UP | ItemTouchHelper.DOWN) {
#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) {
if(direction == ItemTouchHelper.UP){
Toast.makeText(getActivity(), "You swiped up", Toast.LENGTH_LONG).show();
}
}
});
Here the complete code if it some reason interfers with smth don´t know
public class HomeFragment extends Fragment {
View myFragment;
private ImageButton postButton;
CollectionReference postsRef;
FirebaseFirestore db;
private PostsAdapter adapter;
FirebaseAuth mAuth;
RecyclerView recyclerView;
public static ProfileFragment getInstance() {
return new ProfileFragment();
}
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
myFragment = inflater.inflate(R.layout.fragment_home, container, false);
postButton = myFragment.findViewById( R.id.postButton);
recyclerView = myFragment.findViewById(R.id.postlist);
mAuth = FirebaseAuth.getInstance();
db = FirebaseFirestore.getInstance();
postsRef = db.collection("posts");
SetupRecyclerView();
postButton.setOnClickListener( new View.OnClickListener() {
#Override
public void onClick(View v) {
SendUserToPostActivity();
}
});
new ItemTouchHelper( new ItemTouchHelper.SimpleCallback(0,
ItemTouchHelper.UP | ItemTouchHelper.DOWN) {
#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) {
if(direction == ItemTouchHelper.UP){
Toast.makeText(getActivity(), "You swiped up", Toast.LENGTH_LONG).show();
}
}
});
adapter.setOnConfirmClickListener( new PostsAdapter.onConfirmClickListener() {
#Override
public void onConfirmClick(DocumentSnapshot documentSnapshot, int position) {
Posts post = documentSnapshot.toObject(Posts.class);
String id = documentSnapshot.getId();
if(post.getUid().equals(mAuth.getCurrentUser().getUid())){
adapter.deleteItem(position);
Toast.makeText(getActivity(), "Post deleted", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getActivity(), "You cannot delete this", Toast.LENGTH_LONG).show();
}
}
});
return myFragment;
}
#Override
public void onStart(){
super.onStart();
adapter.startListening();
}
#Override
public void onStop() {
super.onStop();
adapter.stopListening();
}
private void SetupRecyclerView() {
Query query = postsRef.orderBy("time", Query.Direction.DESCENDING);
FirestoreRecyclerOptions<Posts> options = new FirestoreRecyclerOptions.Builder<Posts>().setQuery(query, Posts.class).build();
adapter = new PostsAdapter(options);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
recyclerView.setAdapter(adapter);
}
private void SendUserToPostActivity() {
Intent postIntent = new Intent(getActivity(), PostActivity.class);
startActivity(postIntent);
}
}
You're using the wrong listener. An ItemTouchHelper applies to the individual items within the recyclerview, rather than the view as whole.
What you're looking for is OnScrollListener:
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrollStateChanged(#NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
#Override
public void onScrolled(#NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
//This is where you can track a scroll change
}
});
dy in the onScrolled method refers to the change in y position on a scroll event, likewise for dx.
In that method, let's say you wanted to check if the recyclerview reached the limit of scrolling either up or down, then within that onScroll method (or wherever you're checking that), you can add a call to recyclerView.canScrollVertically(int). The int will be a value of -1 for UP, 1 for DOWN, and 0 for FALSE, i.e. cannot scroll.
Checking if the recyclerview reached the bottom:
if(!recyclerView.canScrollVertically(1)){
//The recyclerview can no longer scroll downwards, you have reached the bottom
}
Editing to add: Your itemTouchHelper also didn't work correctly because vertical directions are to be specified in the first parameter of the callback, and horizontal directions in the second parameter. You passed 0 for the first parameter, so it sees no vertical direction as an option

Notify the recyclerview item when it is onMoving without interruption

I've expandable row layouts in RecyclerView, normally they're expanded.
Atteched ItemTouchHelper.SimpleCallback to the RecyclerView for moving the rows with onMove(). Everythings is right and moving the rows correctly.
ItemTouchHelper.SimpleCallback:
#Override
public boolean onMove(#NonNull RecyclerView recyclerView, #NonNull RecyclerView.ViewHolder viewHolder, #NonNull RecyclerView.ViewHolder target) {
int fromPosition = viewHolder.getAdapterPosition();
int toPosition = target.getAdapterPosition();
Collections.swap(adapter.getShelves(), fromPosition, toPosition);
adapter.notifyItemMoved(fromPosition, toPosition);
return true;
}
// Minifying the rows before the onMove is started:
#Override
public boolean isLongPressDragEnabled() {
adapter.minifyRow(position);
return true;
}
It should minify the rows when long pressing, before onMoving() is started. Then should start the moving without any interrupting. The problem is starting dragging and minifiying the row when long press but interrupting the dragging at the moment. So it doesn't dragging or moving the row. How to simulate onMove with notify?
In adapter class:
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
boolean rowIsExpanded = rows.get(position).isExpanded();
if(rowIsExpanded){
holder.rowLayout.setVisibility(View.VISIBLE);
} else {
holder.rowLayout.setVisibility(View.GONE);
}
}
public void minifyRow(boolean situation, int adapterPos){
RowModel row = rows.get(adapterPos);
row.setExpanded(situation);
notifyItemChanged(adapterPos);
}
You shouldn't call adapter.minifyRow(position); inside isLongPressDragEnabled it only flags to check your adapter enable long-press or not. You should override onSelectedChanged. Remove method in isLongPressDragEnabled and Try this
#Override
public void onSelectedChanged(#Nullable RecyclerView.ViewHolder viewHolder, int actionState) {
if (viewHolder != null && actionState == ItemTouchHelper.ACTION_STATE_DRAG) {
((YourViewHolder)viewHolder).rowLayout.setVisibility(View.GONE);
}
}

RecyclerView drag and drop not working with several view types

I am trying to use a RecyclerView with a vertical LinearLayoutManager in order to display a list items. This list can contain several different item types (differents layouts), and it can be reordered by the user using drag and drop.
For the item types, as documented in Android documentation, I have overridden the getItemType method in order to handle different types of views in the recycler and handle it in the onCreateViewHolder and onBindViewHolder. This works like a charm.
For the drag and drop reorder, I have used a ItemTouchHelper.Callback (inspired by this sample project). This also works well.
The problem happen when I try to use different items types AND the drag and drop behaviour. As long as the drag occurs between items of the same type, this works well, but when i'm draggin a view of type A over a view of type B, the drag stop and the view returned to it's original position.
Here is my code:
MyFragment.java
public class MyFragment extends Fragment implements MyAdapter.Listener {
private MyViewModel mViewModel;
private RecyclerView mRecyclerView;
private MyAdapter mAdapter;
private ItemTouchHelper mItemTouchHelper;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment, container, false);
mRecyclerView = root.findViewById(R.id.recyclerView);
mAdapter = new MyAdapter(this);
mRecyclerView.setAdapter(mAdapter);
mItemTouchHelper = new ItemTouchHelper(new MyDragHelperCallback(mAdapter));
mItemTouchHelper.attachToRecyclerView(mRecyclerView);
mViewModel = ViewModelProviders.of(getActivity()).get(MyViewModel.class);
mViewModel.addObserver(this, new Observer<List<Item>>() {
#Override
public void onChanged(#Nullable List<Item> items) {
mAdapter.updateList(items);
}
});
mAdapter.updateList(mViewModel.getList());
return root;
}
#Override
public void onStartDragRequest(#NonNull RecyclerView.ViewHolder viewHolder) {
mItemTouchHelper.startDrag(viewHolder);
}
}
MyDragHelperCallback.java
public class MyDragHelperCallback extends ItemTouchHelper.Callback {
private static final int DRAG_MOVEMENT_FLAGS = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
#NonNull
private MyDragListener mListener;
public MyDragHelperCallback(#NonNull MyDragListener listener) {
mListener = listener;
}
#Override
public boolean isLongPressDragEnabled() {
return true;
}
#Override
public boolean isItemViewSwipeEnabled() {
return false;
}
#Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
if (!(recyclerView.getLayoutManager() instanceof LinearLayoutManager)) {
throw new IllegalArgumentException("Should only be used with a LinearLayoutManager");
}
return makeMovementFlags(DRAG_MOVEMENT_FLAGS, 0);
}
#Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
mListener.onItemMoved(viewHolder.getAdapterPosition(), target.getAdapterPosition());
return true;
}
#Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
// Nothing to do
}
}
MyDragListener.java
public interface MyDragListener {
void onItemMoved(int from, int to);
}
MyAdapter.java
public class MyAdapter extends RecyclerView.Adapter<MyHolder> implements MyDragListener {
#Nullable
private List<Item> mList;
public void updateList(#Nullable List<Item> list) {
mList = list;
notifyDataSetChanged();
}
#Override
public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == 0) {
return new MyHolderBis(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_bis, parent, false));
}
return new MyHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false));
}
#Override
public void onBindViewHolder(final MyHolder holder, int position) {
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View view) {
mListener.onStartDragRequest(holder);
return true;
}
});
// bind views to data
}
#Override
public int getItemCount() {
return mList != null ? mList.size() : 0;
}
#Override
public int getItemViewType(int position) {
return mList.get(position).getType();
}
#Override
public void onItemMoved(int from, int to) {
notifyItemMoved(from, to);
}
}
Is there something I missing ?
Or is this simply to possible to achieve ?
Thanks for all your answers !

(Android) Create RecyclerView with strings from list

I have a List<String> listOfNames that contains names. How to print them all using RecyclerView?
I was looking for a simple way of doing this and after some time of fiddling around, I think I have found a way.
Here I use an ArrayList of Strings.
Adapter Class
public class TagsAdapter extends RecyclerView.Adapter<TagsAdapter.TagsViewHolder> {
ArrayList<String> arrayList;
public TagsAdapter(ArrayList<String> arrayList) {
this.arrayList = arrayList;
}
#NonNull
#Override
public TagsViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_holder_tags_chips, parent, false);
return new TagsAdapter.TagsViewHolder(layoutView);
}
#Override
public void onBindViewHolder(#NonNull final TagsViewHolder holder, final int position) {
holder.tagText.setText(arrayList.get(position));
}
#Override
public int getItemCount() {
return arrayList.size();
}
public class TagsViewHolder extends RecyclerView.ViewHolder {
public TextView tagText;
public TagsViewHolder(View view) {
super(view);
tagText = view.findViewById(R.id.chipTextView);
}
}
}
Now in the Activity or fragment you want to show the recycler view, initialize your recycler view to the view in the xml
Tags.Java
private RecyclerView recyclerView;
private RecyclerView.LayoutManager layoutManager;
private RecyclerView.Adapter adapter;
In the same place add this method. I am assuming that the array list already has strings in it
private void getTags() {
recyclerView = view.findViewById(R.id.view);
recyclerView.setNestedScrollingEnabled(false);
recyclerView.setHasFixedSize(false);
layoutManager = new LinearLayoutManager(requireActivity(), LinearLayoutManager.HORIZONTAL, false);
//I have made my recycler view horizontal, if you want it vertical, just change the horizontal above to vertical.
recyclerView.setLayoutManager(layoutManager);
adapter = new TagsAdapter(tagsArray);
recyclerView.setAdapter(adapter);
}
I know this is an old question but might help someone who wants a simple and straightforward way of doing this.
Hi Simple example for recycler view.
Follow below steps:
Declare in global this variable
private RecyclerView recyclerview;
Use this where you get response from server and make one model class using GSON plugin just copy and paste your response.After use that.
Gson gson = new Gson();
CreateYourModel createYourModel = gson.fromJson(response_data, YourActivity.class);
RecyclerAdapter mAdapter = new RecyclerAdapter(createYourModel);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getActivity());
recyclerview.setLayoutManager(mLayoutManager);
recyclerview.setItemAnimator(new DefaultItemAnimator());
recyclerview.setAdapter(mAdapter);
recyclerview.setNestedScrollingEnabled(false);
This is your Recycler adapter just use same.
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.MyViewHolder> {
private CreateYourModel mList;
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView tvdate;
public MyViewHolder(View view) {
super(view);
tvdate = (TextView) view.findViewById(R.id.tvdate);
}
}
public RecyclerAdapterCreateYourModel mList) {
this.mList = mList;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.youritemview, parent, false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.tvsummuryloan_repayment_date.setText(setyourdatafromlist);
}
#Override
public int getItemCount() {
return mList.size();
}
}
You can follow any tutorial on google.
Thanks

Categories