BamsBamx
BamsBamx

Reputation: 4256

removing RecyclerView items

I have a RecyclerView which is adding items each certain period. When adding objects, if list items are more than (lets say) 500, then the first items will be removed and the new items will be added.

If the RecyclerView cannot scroll down any more !recyclerView.canScrollVertically(1); then, after adding new items the RecyclerView will smoothScroolToPosition() to the last position.

Where is the problem? Okay, if ReyclerView is at the middle (not bottom, not top) when removing old items, it will suddenly jump some positions up. I want the RecyclerView to not jump position and stay where it was when removing items at the top

I tried using layoutManager.setStackFromEnd(true); but no luck

Any suggestions?

Some code (unrelated code is deleted). My problem can be reproduced when the RecyclerView is showing list items from the middle and press VOLUME_UP:

public class ActivityMain extends ActionBarActivity {

    public static final int MAX_LOG_ITEMS = 500;

    private RecyclerView mRecyclerView;
    private AdapterLog mRecyclerAdapter;
    private boolean mAutoScroll = true;

    private DataReceiver mDataReceiver;
    private Handler mLogHandler = new Handler() {
        @Override public void handleMessage(Message msg) {
            switch (msg.what){
                case DataReceiver.CAT_LOGS:
                    List<Log> catLogs = (List<Log>) msg.obj;
                    updateLogs(catLogs);
                    break;
                case DataReceiver .CLEAR_LOGS:
                    if (mRecyclerAdapter.getItemCount() > MAX_LOG_ITEMS)
                        mRecyclerAdapter.removeFirstItems(mRecyclerAdapter.getItemCount() - MAX_LOG_ITEMS);
                    break;
                case Logcat.REMOVE_LOGS:
                    mRecyclerAdapter.clear();
            }
        }

    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        final LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        layoutManager.setStackFromEnd(true);
        mRecyclerAdapter = new AdapterLog();

        mRecyclerView = (RecyclerView) findViewById(R.id.activity_main_recyclerview);
        mRecyclerView.setHasFixedSize(true);        
        mRecyclerView.setLayoutManager(layoutManager);
        mRecyclerView.setAdapter(mRecyclerAdapter);
        mRecyclerView.setOnScrollListener(new UIUtils.ScrollManager(toolbarContainer != null ?
                toolbarContainer : toolbar){
                @Override public void onScrolled(RecyclerView r, int dx, int dy) {
                    super.onScrolled(r, dx, dy);
                    mAutoScroll = !r.canScrollVertically(1);
                    }
                });
    }



    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        switch(keyCode){
            case KeyEvent.KEYCODE_VOLUME_UP:
//                mAutoScroll = false;
//                mRecyclerView.scrollToPosition(0);
//                if (mRecyclerAdapter.getItemCount() > MAX_LOG_ITEMS)
                    mRecyclerAdapter.removeFirstItems(mRecyclerAdapter.getItemCount() - 50);

                return true;
            case KeyEvent.KEYCODE_VOLUME_DOWN:
                mAutoScroll = true;
                mRecyclerView.scrollToPosition(mRecyclerAdapter.getItemCount() -1);
                return true;
        }
        return false;
    }

    private void updateLogs(final List<Log> logList) {
        final boolean scroll = mAutoScroll;
        mRecyclerAdapter.addAll(logList);
        if (scroll) mRecyclerView.smoothScrollToPosition(mRecyclerAdapter.getItemCount() - 1);
    }

}

The RecyclerAdapter:

public class AdapterLog extends RecyclerView.Adapter<AdapterLog.ViewHolder> {

    private final List<Log> mLogList;

    public AdapterLog() {
        this.mLogList = new ArrayList<Log>();
    }

    @Override
    public AdapterLog.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.listitem_log, parent, false);
        return new ViewHolder(v);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        holder.mTextView.setText(getItem(position).getMessage());
        holder.mTextView.setTextColor(getItem(position).getLevel().getColor());
    }

    @Override
    public int getItemCount() {
        return mLogList.size();
    }

    public Log getItem(int position) {
        return mLogList.get(position);
    }

    public void addAll(List<Log> logList) {
        mLogList.addAll(logList);
        notifyDataSetChanged();
    }

    public void removeFirstItems(int count) {
        for (int i=0; i<count; i++) mLogList.remove(0);
        notifyDataSetChanged();
    }

    public void clear() {
        mLogList.clear();
        notifyDataSetChanged();
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {
        public TextView mTextView;
        public ViewHolder(View v) {
            super(v);
            mTextView = (TextView) v.findViewById(R.id.listitem_log_textview);
        }
    }
}

Upvotes: 9

Views: 26367

Answers (3)

Azharul Islam
Azharul Islam

Reputation: 11

 public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

    private McPurchasePricingCellBinding itemBinding;
    private OnProductItemListener listener;


    public ViewHolder(McPurchasePricingCellBinding itemBinding, OnProductItemListener listener) {
        super(itemBinding.getRoot());
        this.itemBinding = itemBinding;
        this.listener = listener;
        itemBinding.removeCartContainer.setOnClickListener(this);


    }


    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.remove_cart_container) {
            if (listener == null) {
                return;
            }
            int position = getAdapterPosition();
            if (position != RecyclerView.NO_POSITION) {
                listener.onRemoveItem(position);
            }
        }
    }
} 


public void removeAt(int position) {
    arrayList.remove(position);
    notifyItemRemoved(position);
}
 public interface OnProductItemListener {
    void onRemoveItem(int position);
}

Upvotes: 0

younes
younes

Reputation: 832

public class viewHolderFav extends RecyclerView.ViewHolder {
    private ImageView image;
    private TextView name;




public viewHolderFav( View itemView ) {
        super( itemView );
        image = ( ImageView ) itemView.findViewById( R.id.txt_image_fav );
        name = ( TextView ) itemView.findViewById( R.id.txt_name_fav );



        edite.setOnClickListener( new View.OnClickListener( ) {
            @Override
            public void onClick( View v ) {

            remove( posts.get( getLayoutPosition() ) );


            }
        } );



    }



public void remove(DataBoj item) {
    int position = posts.indexOf(item);
    posts.remove(position);
    notifyItemRemoved(position);
}

Upvotes: 0

Pedro Oliveira
Pedro Oliveira

Reputation: 20500

You're telling your view that you changed your whole adapter. For additions, deletions and reorders consider using the following methods:

notifyItemRangeChanged
notifyItemRangeInserted
notifyItemRangeRemoved
notifyItemMoved
notifyItemInserted
notifyItemChanged
notifyItemRemoved

So in your case you're removing the top count items so:

notifyItemRangeRemoved(0,count)

should do the work.

Upvotes: 20

Related Questions