简体   繁体   中英

Wrong Position after Filtering and on Click in Recyclerview

I have Implemented SearchView in my App. But the Problem I am facing is the recycler view returns the wrong position after filtering. How can i get the exact position after filtering.

Here is my code of Adapter:-

public class UserListAdapter extends Adapter<UserListAdapter.DataObjectHolder> implements Filterable {
private static MyClickListener myClickListener;
public Activity activity;
Bitmap bitmap;
ImageView imgUserBig;
TextView txtUserName;
RelativeLayout userProfileView;
private ArrayList<DataObject> mArrayList;
private ArrayList<DataObject> mFilteredList;    

public UserListAdapter(Activity a, ArrayList<DataObject> d, ImageView mImgUserBig, RelativeLayout viewLinear, TextView txtUsername) {

    this.activity = a;
    this.mArrayList = d;
    this.mFilteredList = d;
    this.imgUserBig = mImgUserBig;
    this.userProfileView = viewLinear;
    this.txtUserName = txtUsername;
}

public DataObjectHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    return new DataObjectHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.raw_user_list, parent, false));
}

public void onBindViewHolder(final DataObjectHolder holder, final int position) {
    holder.txtName.setText((mFilteredList.get(position)).getmName());
    holder.txtUserName.setText((mFilteredList.get(position)).getmUsername());
    Glide.with(activity.getApplicationContext()).load((mFilteredList.get(position)).getmImage()).into(holder.imgUser);
    Glide.with(activity).load((mFilteredList.get(position)).getmImage()).asBitmap().into(new SimpleTarget<Bitmap>(Integer.MIN_VALUE, Integer.MIN_VALUE) {
        public void onResourceReady(Bitmap resource, GlideAnimation glideAnimation) {
            bitmap = resource;
            (mFilteredList.get(position)).setBitmap(bitmap);
        }
    });
    holder.imgUser.setOnClickListener(new OnClickListener() {
        public void onClick(View view) {
            if ((mFilteredList.get(position)).getBitmap() != null && imgUserBig != null) {
                zoomImageFromThumb(holder.imgUser, (mFilteredList.get(position)).getBitmap(), (mFilteredList.get(position)).getmImage(), (mFilteredList.get(position)).getmUsername());
            }
        }
    });
}

public int getItemCount() {
    return mFilteredList.size();
}

public void setOnItemClickListener(MyClickListener myClickListener) {
    UserListAdapter.myClickListener = myClickListener;
}

@Override
public Filter getFilter() {
    return new Filter() {
        @Override
        protected FilterResults performFiltering(CharSequence charSequence) {
            String charString = charSequence.toString();
            if (charString.isEmpty()) {
                mFilteredList = mArrayList;
            }else {
                ArrayList<DataObject> filteredList = new ArrayList<>();
                for (DataObject userData : mArrayList) {
                    if (userData.getmUsername().toLowerCase().contains(charString) || userData.getmName().toLowerCase().contains(charString)) {
                        filteredList.add(userData);
                    }
                }
                mFilteredList = filteredList;
            }
            FilterResults filterResults = new FilterResults();
            filterResults.values = mFilteredList;
            return filterResults;
        }

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            mFilteredList = (ArrayList<DataObject>) results.values;
            notifyDataSetChanged();
        }
    };
}

public interface MyClickListener {
    void onItemClick(int i, View view);
}

public Object getItem(int position) {
    return mFilteredList.get(position);
}



public class DataObjectHolder extends ViewHolder implements OnClickListener {
    ImageView imgUser;
    TextView txtName;
    TextView txtUserName;

    public DataObjectHolder(View itemView) {
        super(itemView);
        txtName = (TextView) itemView.findViewById(R.id.txtname);
        txtUserName = (TextView) itemView.findViewById(R.id.txtusername);
        imgUser = (ImageView) itemView.findViewById(R.id.img_user);
        itemView.setOnClickListener(this);
    }

    public void onClick(View v) {
        UserListAdapter.myClickListener.onItemClick(getPosition(), v);
    }
}}

I am calling getPosition() Method to get the position of the item, but it returns the old position, not the filtered one. Any Help will be Appreciated.

Use this class to implement the scroll listener before recyclerview reaches to its end . It notify when 5 items are left to be scrolled . See Code below.

Just put it in your projectas a separate class

import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;


public abstract class EndlessRecyclerOnScrollListener extends RecyclerView.OnScrollListener
{
    public static String TAG = EndlessRecyclerOnScrollListener.class.getSimpleName();
private int previousTotal = 0; // The total number of items in the dataset after the last load
private boolean loading = true; // True if we are still waiting for the last set of data to load.
private int visibleThreshold = 5; // The minimum amount of items to have below your current scroll position before loading more.
int firstVisibleItem, visibleItemCount, totalItemCount;

private int current_page = 0;

private StaggeredGridLayoutManager mLinearLayoutManager;
private LinearLayoutManager mLinearLayoutManagerG;

public EndlessRecyclerOnScrollListener(StaggeredGridLayoutManager linearLayoutManager)
{
    this.mLinearLayoutManager = linearLayoutManager;
}


public EndlessRecyclerOnScrollListener(LinearLayoutManager linearLayoutManager)
{
    this.mLinearLayoutManagerG = linearLayoutManager;
    mLinearLayoutManager = null;
}


public void reset()
{
    current_page = 0;
    previousTotal = 0;
    loading = true;
}

public void setThresHold(int threshold)
{
    visibleThreshold = threshold;
}

@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy)
{
    super.onScrolled(recyclerView, dx, dy);

    if (mLinearLayoutManager != null)
    {
        visibleItemCount = recyclerView.getChildCount();
        totalItemCount = mLinearLayoutManager.getItemCount();
        firstVisibleItem = mLinearLayoutManager.findFirstVisibleItemPositions(null)[0];

        if (loading)
        {
            if (totalItemCount > previousTotal)
            {
                loading = false;
                previousTotal = totalItemCount;
            }
        }
        if (!loading && (totalItemCount - visibleItemCount) <= (firstVisibleItem + visibleThreshold))
        {
            // End has been reached

            // Do something
            current_page++;

            onLoadMore(current_page);

            loading = true;
        }
    }
    else
    {
        visibleItemCount = recyclerView.getChildCount();
        totalItemCount = mLinearLayoutManagerG.getItemCount();
        firstVisibleItem = mLinearLayoutManagerG.findFirstVisibleItemPosition();

        if (loading)
        {
            if (totalItemCount > previousTotal)
            {
                loading = false;
                previousTotal = totalItemCount;
            }
        }
        if (!loading && (totalItemCount - visibleItemCount) <= (firstVisibleItem + visibleThreshold))
        {
            // End has been reached

            // Do something
            current_page++;

            onLoadMore(current_page);

            loading = true;
        }

    }

    countChange(firstVisibleItem);
}

public abstract void onLoadMore(int current_page);

public abstract void countChange(int currentVisibleCount);
}

Use it like this

endlessRecyclerOnScrollListener = new EndlessRecyclerOnScrollListener(pass your layout manager here)
    {
        @Override
        public void onLoadMore(int current_page) {
            pageNumber++;
            // Hit your api for more records 
        }

        @Override
        public void countChange(int currentVisibleCount) {

        }
    };

    recyclerView.setOnScrollListener(endlessRecyclerOnScrollListener);

There is a variable named current_page , By default it starts from 0 , you can change it according to your api. visibleThreshold says that before how many items your onLoadMore method should be called .

Example: If the visibleThreshold is 5 and total data in the list is 20, then onLoadMore will be called when your recyclerview is scrolled upto 15th position.

Let me know if you have more queries.

Use getAdapterPosition() in your onClick method because then at the time of the click u want to know the position of the item. If u check at the time of the creation it will (most of the times) be inaccurate

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM