I have a strange problem here.
Context:
I'm building an Android TV application which makes use of Android's Leanback Library. When the user navigates to a show, it has a vertical grid view which lists all the episodes of the show.
The list is filled using an ArrayObjectAdapter to which I pass the episodeModel for each episode in the list and then I just set the adapter to the view using setAdapter(adapter) So far so good.
The thing is that when the user scrolls down the list the items that are not visible in the viewport gets updated but with the images and titles of those that were already passed. I mean, They looks like duplicated items but what's really going on is that the last items don't get updated with its own images and titles but with the ones of the first ones.
How do I prevent this to happen?
Here is the CardPresenter
public class CardPresenter extends Presenter {
private static final String TAG = CardPresenter.class.getSimpleName();
private static final int CARD_WIDTH = 420;
private static final int CARD_HEIGHT= 236;
private static int selectedBgColor;
private static int defaultBgColor;
private Drawable defaultCardimage;
private ImageCardView mCardView;
static class ViewHolder extends Presenter.ViewHolder{
ViewHolder(View view) {
super(view);
}
}
private static void updateCardBGColor(ImageCardView view, boolean selected){
int color = selected ? selectedBgColor : defaultBgColor;
view.setBackgroundColor(color);
view.findViewById(R.id.info_field).setBackgroundColor(color);
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent) {
defaultBgColor = ContextCompat.getColor(parent.getContext(), R.color.le_gray);
selectedBgColor = ContextCompat.getColor(parent.getContext(), R.color.le_black);
defaultCardimage = ContextCompat.getDrawable(parent.getContext(), R.drawable.default_bg);
mCardView = new ImageCardView(parent.getContext()) {
#Override
public void setSelected(boolean selected) {
super.setSelected(selected);
updateCardBGColor(this, selected);
}
};
mCardView.setMainImage(defaultCardimage);
mCardView.setFocusable(true);
mCardView.setFocusableInTouchMode(true);
mCardView.setCardType(BaseCardView.CARD_TYPE_INFO_UNDER);
return new ViewHolder(mCardView);
}
#Override
public void onBindViewHolder(Presenter.ViewHolder viewHolder, Object item) {
if(item instanceof ShowModel){
ShowModel showModel = (ShowModel) item;
if(showModel.getThumbnail() != null){
mCardView.setTitleText(showModel.getName());
mCardView.setContentText(showModel.getType());
mCardView.setMainImageDimensions(CARD_WIDTH, CARD_HEIGHT);
Glide.with(viewHolder.view.getContext()).load(showModel.getThumbnail()).error(defaultCardimage).into(mCardView.getMainImageView());
}
}else if(item instanceof EpisodeModel){
EpisodeModel episodeModel = (EpisodeModel) item;
if(episodeModel.getStill() != null){
mCardView.setTitleText(episodeModel.getTitle());
mCardView.setContentText(episodeModel.getDescription());
mCardView.setMainImageDimensions(CARD_WIDTH, CARD_HEIGHT);
Glide.with(viewHolder.view.getContext()).load(episodeModel.getStill()).error(defaultCardimage).into(mCardView.getMainImageView());
}
}
}
#Override
public void onUnbindViewHolder(Presenter.ViewHolder viewHolder) {
mCardView.setBadgeImage(null);
mCardView.setMainImage(null);
}
}
You need to update onBindViewHolder to use the ViewHolder to update the views. Right now you're creating a reference to whichever ImageCardView was most recently created and then updating it. For example, you have
mCardView.setTitleText(showModel.getName());
But the mCardView is not necessarily for the right position. You need to do something like this:
viewHolder.itemView.setTitleText(showModel.getName());
You may need to cast the itemView to an ImageCardView.
Hello I am new to Fresco and I am trying to load all the images in my phone to the app
when I use this URI: /storage/emulated/0/DCIM/Camera/20200206_222309.jpg
with this code:
ControllerListener listener = new BaseControllerListener();
DraweeController controller = Fresco.newDraweeControllerBuilder()
.setUri(xuri)
.setTapToRetryEnabled(true)
.setControllerListener(listener)
.build();
photosFragmentRecycler.setController(controller);
only the photo with the name 20200206_222309.jpg is loaded
how can I load all the images?
thanks in Advance
Your question doesn't depend on the image library used. You basically want to get a list of all camera images.
Something like this should get you the list of all URIs:
fun getMediaStoreUris(context: Context): List<Uri> {
val uris = mutableListOf<Uri>()
context.contentResolver.query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
arrayOf(MediaStore.Images.Media._ID),
null,
null,
null)?.use {
val dataIndex = it.getColumnIndexOrThrow(MediaStore.Images.Media._ID)
while (it.moveToNext()) {
uris.add(
ContentUris.withAppendedId(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
it.getLong(dataIndex)))
}
}
return uris
}
Then, you can just create a simple RecyclerView adapter and ViewHolder and load images with Fresco:
public class SimpleAdapter extends RecyclerView.Adapter<SimpleViewHolder> {
private List<Uri> mUris;
SimpleAdapter(List<Uri> uris) {
mUris = uris;
setHasStableIds(true);
}
#Override
public SimpleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView =
LayoutInflater.from(parent.getContext())
.inflate(R.layout.drawee_recycler_item, parent, false);
return new SimpleViewHolder(itemView);
}
#Override
public void onBindViewHolder(SimpleViewHolder holder, int position) {
holder.mSimpleDraweeView.setImageURI(mUris.get(position));
}
#Override
public int getItemCount() {
return mUris.size();
}
#Override
public long getItemId(int position) {
return mUris.get(position).hashCode();
}
public void setData(List<Uri> uris) {
mUris = uris;
notifyDataSetChanged();
}
}
static class SimpleViewHolder extends RecyclerView.ViewHolder {
private final SimpleDraweeView mSimpleDraweeView;
SimpleViewHolder(View itemView) {
super(itemView);
mSimpleDraweeView = itemView.findViewById(R.id.drawee_view);
}
}
and use the adapter:
final SimpleAdapter adapter = new SimpleAdapter(getMediaStoreUris(context));
recyclerView.setAdapter(adapter);
Fresco has a full sample in their Showcase sample application here: https://github.com/facebook/fresco/blob/9fde53f963d07495118c61ea2d9a3fce575afeb7/samples/showcase/src/main/java/com/facebook/fresco/samples/showcase/drawee/DraweeRecyclerViewFragment.java
This is going to work if you allow permission to access local storage, there's a guide here or to test it, by simply going to "App Info" for your app and manually allowing it.
This is a very simple solution and in practice, you probably want to implement pagination etc. for the media store. But this should guide you in the right direction.
Please have a look at related Question. I got to know some hint from comments and now putting it in a new way.
I am using a RecyclerView with StaggeredGridView adapter to display the data. How do I get to know that how many items needed to be loaded for current devices to fit the whole screen?
process
Determine the screen size
Determine how many items needed to be loaded to fit full screen
Fetch data from Server with number of items
Display them
When user scroll down device fetch same amount of items and so on.
Question
I am not able to understand How to get done with first two points.
Code for Adapter
public class StaggeredGridAdapter extends RecyclerView.Adapter<StaggeredGridAdapter.StaggeredGridView> {
private Context context;
private String INTENT_VALUE = "warehouse";
private List<Warehouse> warehouses = new ArrayList<Warehouse>();
private AppDelegate app;
int size;
public StaggeredGridAdapter(Context context) {
this.context = context;
app = (AppDelegate) context;
}
public void addItems(List<Warehouse> response) {
size = response.size();
warehouses = response;
}
#Override
public StaggeredGridView onCreateViewHolder(ViewGroup parent, int viewType) {
View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.grid_item, parent, false);
StaggeredGridView staggeredGridView = new StaggeredGridView(layoutView);
return staggeredGridView;
}
#Override
public void onBindViewHolder(StaggeredGridView holder, int position) {
holder.textView.setText(warehouses.get(position).getFace());
}
#Override
public int getItemCount() {
return size;
}
class StaggeredGridView extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView textView;
public StaggeredGridView(View itemView) {
super(itemView);
textView = (TextView) itemView.findViewById(R.id.img_name);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
Intent intent = new Intent(context, WareHouseDetailActivity.class);
intent.putExtra(INTENT_VALUE, warehouses.get(getAdapterPosition()));
v.getContext().startActivity(intent);
}
}
}
code for filling data into adapter
mRecyclerView = (RecyclerView) mActivity.findViewById(R.id.staggering_grid);
mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL));
mAdapter = new StaggeredGridAdapter(mContext);
mAdapter.addItems(response);
mRecyclerView.setAdapter(mAdapter);
As to find the Height and Width, you can use the DisplayMetrics.
final DisplayMetrics displayMetrics = this.getApplicationContext().getResources().getDisplayMetrics();
This displayMetrics will give Height, Width and Density. Use the height of the single View (or row) and the total height to calculate the number of items.
Why do you want the Exact number of items, if it's a server call you are making, you could just make a rough estimate on the number of items based on the device size. Also, I think it's better to keep the number of items sent by server a constant and not dependent on the device height. If you received more than the number of items you can fit in the screen, well, the user can scroll to see them anyways.
Rather than trying to work out how much you'll need to load, you could set it up to automatically load more when you're close to the end of the list.
Consider this method:
#Override
public void onBindViewHolder(StaggeredGridView holder, int position) {
holder.textView.setText(warehouses.get(position).getFace());
}
This is called when the item is ready to be displayed on the screen. By doing something like if(position > getItemCount() - 5{ // load more } then you could be automatically loading more as and when they're required.
I have a POJO:
public class RoomData implements Parcelable {
private String objectId, name, building, floor, imageUrl;
private boolean hasPc, hasProjector, hasTelepresence, hasWhiteboard;
private boolean dataReady = false;
private ArrayList<MeetingData> meetingData = new ArrayList<MeetingData>();
private int capacity;
private ArrayList<BeaconData> beacons = new ArrayList<BeaconData>();
private DateTime nextAvailableStart, nextAvailableEnd;
private boolean availableNow = false;
private ArrayList<Interval> meetingDuringIntervals = new ArrayList<Interval>();
}
that is populated into a custom ListView/ListAdapter.
I want to know how I can filter that list by the fields of my POJO. For instance if I construct a RoomFilter object, that states that my capacity integer should be higher than X. How can I implement this? I can only find links to filtering by primitive data types...
Here is my custom Adapter class:
public class BeaconAdapter extends BaseAdapter {
private Context context;
private ArrayList<BLEDeviceAdvertisement> beaconArrayList = new ArrayList<BLEDeviceAdvertisement>();
private static LayoutInflater inflater = null;
//BeaconAdapter for the custom ListView
public BeaconAdapter(Context context, ArrayList<BLEDeviceAdvertisement> beaconArrayList) {
this.beaconArrayList = beaconArrayList;
this.context = context;
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return beaconArrayList.size();
}
#Override
public BLEDeviceAdvertisement getItem(int position) {
return beaconArrayList.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
//Custom getview for the custom layout beacon_row_item.
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View myCustomView = convertView;
if (myCustomView == null)
myCustomView = inflater.inflate(R.layout.beacon_row_item, null);
return myCustomView;
}
}
After OP's request I post my comment as an answer for future reference, giving more details. Here are some possible solutions:
Destructive update: Loop through the list, filtering out what you don't need. Implement adapter based on this list.
Virtual view: Implement logic for a "virtual view" over the original list. Here you keep only the original list, but in all adapter's methods you skip items that don't match the filter. For instance, in getItem(int pos) you loop through the list keeping a counter, but you increment it only if the item matches the filter: when the counter equals pos you return the item. Similar for the other methods.
Concrete View: Use an additional list to keep the "view" over the original list, so to cache the computation done in 2. When the filter is set/updated, a loop through the original list builds the "view" and then you implement the adapter based on the "view". More time efficient, but also more memory consumed.
I have a RecyclerView with an TextView text box and a cross button ImageView. I have a button outside of the recyclerview that makes the cross button ImageView visible / gone.
I'm looking to remove an item from the recylerview, when that items cross button ImageView is pressed.
My adapter:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> implements View.OnClickListener, View.OnLongClickListener {
private ArrayList<String> mDataset;
private static Context sContext;
public MyAdapter(Context context, ArrayList<String> myDataset) {
mDataset = myDataset;
sContext = context;
}
#Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.my_text_view, parent, false);
ViewHolder holder = new ViewHolder(v);
holder.mNameTextView.setOnClickListener(MyAdapter.this);
holder.mNameTextView.setOnLongClickListener(MyAdapter.this);
holder.mNameTextView.setTag(holder);
return holder;
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.mNameTextView.setText(mDataset.get(position));
}
#Override
public int getItemCount() {
return mDataset.size();
}
#Override
public void onClick(View view) {
ViewHolder holder = (ViewHolder) view.getTag();
if (view.getId() == holder.mNameTextView.getId()) {
Toast.makeText(sContext, holder.mNameTextView.getText(), Toast.LENGTH_SHORT).show();
}
}
#Override
public boolean onLongClick(View view) {
ViewHolder holder = (ViewHolder) view.getTag();
if (view.getId() == holder.mNameTextView.getId()) {
mDataset.remove(holder.getPosition());
notifyDataSetChanged();
Toast.makeText(sContext, "Item " + holder.mNameTextView.getText() + " has been removed from list",
Toast.LENGTH_SHORT).show();
}
return false;
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView mNumberRowTextView;
public TextView mNameTextView;
public ViewHolder(View v) {
super(v);
mNameTextView = (TextView) v.findViewById(R.id.nameTextView);
}
}
}
My layout is:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical"
android:id="#+id/layout">
<TextView
android:id="#+id/nameTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"
android:padding="5dp"
android:background="#drawable/greyline"/>
<ImageView
android:id="#+id/crossButton"
android:layout_width="16dp"
android:layout_height="16dp"
android:visibility="gone"
android:layout_marginLeft="50dp"
android:src="#drawable/cross" />
</LinearLayout>
How can I get something like an onClick working for my crossButton ImageView? Is there a better way? Maybe changing the whole item onclick into a remove the item? The recyclerview shows a list of locations that need to be edited. Any technical advice or comments / suggestions on best implementation would be hugely appreciated.
I have done something similar.
In your MyAdapter:
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
public CardView mCardView;
public TextView mTextViewTitle;
public TextView mTextViewContent;
public ImageView mImageViewContentPic;
public ImageView imgViewRemoveIcon;
public ViewHolder(View v) {
super(v);
mCardView = (CardView) v.findViewById(R.id.card_view);
mTextViewTitle = (TextView) v.findViewById(R.id.item_title);
mTextViewContent = (TextView) v.findViewById(R.id.item_content);
mImageViewContentPic = (ImageView) v.findViewById(R.id.item_content_pic);
//......
imgViewRemoveIcon = (ImageView) v.findViewById(R.id.remove_icon);
mTextViewContent.setOnClickListener(this);
imgViewRemoveIcon.setOnClickListener(this);
v.setOnClickListener(this);
mTextViewContent.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View view) {
if (mItemClickListener != null) {
mItemClickListener.onItemClick(view, getPosition());
}
return false;
}
});
}
#Override
public void onClick(View v) {
//Log.d("View: ", v.toString());
//Toast.makeText(v.getContext(), mTextViewTitle.getText() + " position = " + getPosition(), Toast.LENGTH_SHORT).show();
if(v.equals(imgViewRemoveIcon)){
removeAt(getPosition());
}else if (mItemClickListener != null) {
mItemClickListener.onItemClick(v, getPosition());
}
}
}
public void setOnItemClickListener(final OnItemClickListener mItemClickListener) {
this.mItemClickListener = mItemClickListener;
}
public void removeAt(int position) {
mDataset.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, mDataSet.size());
}
Edit:
getPosition() is deprecated now, use getAdapterPosition() instead.
first of all, item should be removed from the list!
mDataSet.remove(getAdapterPosition());
then:
notifyItemRemoved(getAdapterPosition());
notifyItemRangeChanged(getAdapterPosition(), mDataSet.size()-getAdapterPosition());
if still item not removed use this magic method :)
private void deleteItem(int position) {
mDataSet.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, mDataSet.size());
holder.itemView.setVisibility(View.GONE);
}
Kotlin version
private fun deleteItem(position: Int) {
mDataSet.removeAt(position)
notifyItemRemoved(position)
notifyItemRangeChanged(position, mDataSet.size)
holder.itemView.visibility = View.GONE
}
The Problem
RecyclerView was built to display data in an efficient and responsive manner.
Usually you have a dataset which is passed to your adapter and is looped through to display your data.
Here your dataset is:
private ArrayList<String> mDataset;
The point is that RecyclerView is not connected to your dataset, and therefore is unaware of your dataset changes.
It just reads data once and displays it through your ViewHolder, but a change to your dataset will not propagate to your UI.
This means that whenever you make a deletion/addition on your data list, those changes won't be reflected to your RecyclerView directly. (i.e. you remove the item at index 5, but the 6th element remains in your recycler view).
A (old school) solution
RecyclerView exposes some methods for you to communicate your dataset changes, reflecting those changes directly on your list items.
The standard Android APIs allow you to bind the process of data removal (for the purpose of the question) with the process of View removal.
The methods we are talking about are:
notifyItemChanged(index: Int)
notifyItemInserted(index: Int)
notifyItemRemoved(index: Int)
notifyItemRangeChanged(startPosition: Int, itemCount: Int)
notifyItemRangeInserted(startPosition: Int, itemCount: Int)
notifyItemRangeRemoved(startPosition: Int, itemCount: Int)
A Complete (old school) Solution
If you don't properly specify what happens on each addition, change or removal of items, RecyclerView list items are animated unresponsively because of a lack of information about how to move the different views around the list.
The following code will allow RecyclerView to precisely play the animation with regards to the view that is being removed (And as a side note, it fixes any IndexOutOfBoundExceptions, marked by the stacktrace as "data inconsistency").
void remove(position: Int) {
dataset.removeAt(position)
notifyItemChanged(position)
notifyItemRangeRemoved(position, 1)
}
Under the hood, if we look into RecyclerView we can find documentation explaining that the second parameter we pass to notifyItemRangeRemoved is the number of items that are removed from the dataset, not the total number of items (As wrongly reported in some others information sources).
/**
* Notify any registered observers that the <code>itemCount</code> items previously
* located at <code>positionStart</code> have been removed from the data set. The items
* previously located at and after <code>positionStart + itemCount</code> may now be found
* at <code>oldPosition - itemCount</code>.
*
* <p>This is a structural change event. Representations of other existing items in the data
* set are still considered up to date and will not be rebound, though their positions
* may be altered.</p>
*
* #param positionStart Previous position of the first item that was removed
* #param itemCount Number of items removed from the data set
*/
public final void notifyItemRangeRemoved(int positionStart, int itemCount) {
mObservable.notifyItemRangeRemoved(positionStart, itemCount);
}
Open source solutions
You can let a library like FastAdapter, Epoxy or Groupie take care of the business, and even use an observable recycler view with data binding.
New ListAdapter
Google recently introduced a new way of writing the recycler view adapter, which works really well and supports reactive data.
It is a new approach and requires a bit of refactoring, but it is 100% worth switching to it, as it makes everything smoother.
here is the documentation, and here a medium article explaining it
Here are some visual supplemental examples. See my fuller answer for examples of adding and removing a range.
Add single item
Add "Pig" at index 2.
String item = "Pig";
int insertIndex = 2;
data.add(insertIndex, item);
adapter.notifyItemInserted(insertIndex);
Remove single item
Remove "Pig" from the list.
int removeIndex = 2;
data.remove(removeIndex);
adapter.notifyItemRemoved(removeIndex);
Possibly a duplicate answer but quite useful for me. You can implement the method given below in RecyclerView.Adapter<RecyclerView.ViewHolder>
and can use this method as per your requirements, I hope it will work for you
public void removeItem(#NonNull Object object) {
mDataSetList.remove(object);
notifyDataSetChanged();
}
I tried all the above answers, but inserting or removing items to recyclerview causes problem with the position in the dataSet. Ended up using delete(getAdapterPosition()); inside the viewHolder which worked great at finding the position of items.
The problem I had was I was removing an item from the list that was no longer associated with the adapter to make sure you are modifying the correct adapter you can implement a method like this in your adapter:
public void removeItemAtPosition(int position) {
items.remove(position);
}
And call it in your fragment or activity like this:
adapter.removeItemAtPosition(position);
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private Context context;
private List<cardview_widgets> list;
public MyAdapter(Context context, List<cardview_widgets> list) {
this.context = context;
this.list = list;
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(this.context).inflate(R.layout.fragment1_one_item,
viewGroup, false);
return new MyViewHolder(view);
}
public static class MyViewHolder extends RecyclerView.ViewHolder {
TextView txtValue;
TextView txtCategory;
ImageView imgInorEx;
ImageView imgCategory;
TextView txtDate;
public MyViewHolder(#NonNull View itemView) {
super(itemView);
txtValue= itemView.findViewById(R.id.id_values);
txtCategory= itemView.findViewById(R.id.id_category);
imgInorEx= itemView.findViewById(R.id.id_inorex);
imgCategory= itemView.findViewById(R.id.id_imgcategory);
txtDate= itemView.findViewById(R.id.id_date);
}
}
#NonNull
#Override
public void onBindViewHolder(#NonNull final MyViewHolder myViewHolder, int i) {
myViewHolder.txtValue.setText(String.valueOf(list.get(i).getValuee()));
myViewHolder.txtCategory.setText(list.get(i).getCategory());
myViewHolder.imgInorEx.setBackgroundColor(list.get(i).getImg_inorex());
myViewHolder.imgCategory.setImageResource(list.get(i).getImg_category());
myViewHolder.txtDate.setText(list.get(i).getDate());
myViewHolder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
list.remove(myViewHolder.getAdapterPosition());
notifyDataSetChanged();
return false;
}
});
}
#Override
public int getItemCount() {
return list.size();
}}
i hope this help you.
if you want to remove item you should do this:
first remove item:
phones.remove(position);
in next step you should notify your recycler adapter that you remove an item by this code:
notifyItemRemoved(position);
notifyItemRangeChanged(position, phones.size());
but if you change an item do this:
first change a parameter of your object like this:
Service s = services.get(position);
s.done = "Cancel service";
services.set(position,s);
or new it like this :
Service s = new Service();
services.set(position,s);
then notify your recycler adapter that you modify an item by this code:
notifyItemChanged(position);
notifyItemRangeChanged(position, services.size());
hope helps you.
String str = arrayList.get(position);
arrayList.remove(str);
MyAdapter.this.notifyDataSetChanged();
To Method onBindViewHolder Write This Code
holder.remove.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Cursor del=dbAdapter.ExecuteQ("delete from TblItem where Id="+values.get(position).getId());
values.remove(position);
notifyDataSetChanged();
}
});
Incase Anyone wants to implement something like this in Main class instead of Adapter class, you can use:
public void removeAt(int position) {
peopleListUser.remove(position);
friendsListRecycler.getAdapter().notifyItemRemoved(position);
friendsListRecycler.getAdapter().notifyItemRangeChanged(position, peopleListUser.size());
}
where friendsListRecycler is the Adapter name
you must to remove this item from arrayList of data
myDataset.remove(holder.getAdapterPosition());
notifyItemRemoved(holder.getAdapterPosition());
notifyItemRangeChanged(holder.getAdapterPosition(), getItemCount());
//////// set the position
holder.cancel.setTag(position);
///// click to remove an item from recycler view and an array list
holder.cancel.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
int positionToRemove = (int)view.getTag(); //get the position of the view to delete stored in the tag
mDataset.remove(positionToRemove);
notifyDataSetChanged();
}
});
make interface into custom adapter class and handling click event on recycler view..
onItemClickListner onItemClickListner;
public void setOnItemClickListner(CommentsAdapter.onItemClickListner onItemClickListner) {
this.onItemClickListner = onItemClickListner;
}
public interface onItemClickListner {
void onClick(Contact contact);//pass your object types.
}
#Override
public void onBindViewHolder(ItemViewHolder holder, int position) {
// below code handle click event on recycler view item.
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
onItemClickListner.onClick(mContectList.get(position));
}
});
}
after define adapter and bind into recycler view called below code..
adapter.setOnItemClickListner(new CommentsAdapter.onItemClickListner() {
#Override
public void onClick(Contact contact) {
contectList.remove(contectList.get(contectList.indexOf(contact)));
adapter.notifyDataSetChanged();
}
});
}
In case you are wondering like I did where can we get the adapter position in the method getadapterposition(); its in viewholder object.so you have to put your code like this
mdataset.remove(holder.getadapterposition());
In the activity:
mAdapter.updateAt(pos, text, completed);
mAdapter.removeAt(pos);
In the your adapter:
void removeAt(int position) {
list.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, list.size());
}
void updateAt(int position, String text, Boolean completed) {
TodoEntity todoEntity = list.get(position);
todoEntity.setText(text);
todoEntity.setCompleted(completed);
notifyItemChanged(position);
}
in 2022, after trying everything the whole internet given below is the answer
In MyViewHolder class
private myAdapter adapter;
inside MyViewHolder function initalise adapter
adapter = myAdapter.this
inside onclick
int position = getAdapterPosition()
list.remove(position);
adapter.notifyItemRemoved(position);