1. 程式人生 > >RecyclerView詳細介紹-----解決點選事件,重新整理錯誤(二)

RecyclerView詳細介紹-----解決點選事件,重新整理錯誤(二)

1. 前言

RecyclerView 沒有提供類似ListView的setOnItemClickListener方法,所以只有我們自己為RecyclerView新增點選事件, 本篇文章主要介紹如何新增點選事件,進行Item增加和刪除,並且解決RecycleView Adapter使用notifyItemRemoved和notifyItemInserted造成Position混亂的問題。

2.新增點選事件

1)在Adapter中建立一個實現點選介面:

public interface OnItemClickLitener {
        void onItemClick(View view, int
position); }

2)在Adapter中新增介面設定方法:

private OnItemClickLitener mOnItemClickListener = null;

    public void setOnItemClickListener(OnItemClickLitener listener) {
        this.mOnItemClickListener = listener;
    }

3)觸發itemClick回撥程式碼:

@Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        holder.mTextView
.setText(data.get(position)); holder.mTextView.setTag(holder.getLayoutPosition()); holder.mTextView.setOnClickListener(this); }
@Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.item_text:
                mOnItemClickListener.onItemClick(v, (int
) v.getTag()); break; } }

4)activity中註冊介面到Adapter中:

public class ItemClickListViewActivity extends AppCompatActivity {

    /**
     * view
     */
    private RecyclerView recyclerView;

    /**
     * 用來確定每一個item如何進行排列擺放,何時展示和隱藏
     */
    private LinearLayoutManager layoutManager;

    /**
     * 介面卡
     */
    private MyItemClickAdapter mAdapter;

    private ArrayList<String> data = new ArrayList<String>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initView();
        initData();
    }

    /**
     * 初始化佈局元件
     */
    private void initView() {
        recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
        //建立預設的線性LayoutManager
        layoutManager = new LinearLayoutManager(this);
//        layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
        recyclerView.setLayoutManager(layoutManager);
        //如果可以確定每個item的高度是固定的,設定這個選項可以提高效能
        recyclerView.setHasFixedSize(true);
    }

    /**
     * 初始化資料
     */
    private void initData() {
        for (int i = 0; i < 100; i++) {
            data.add(i + "--->click");
        }
        //建立並設定Adapter
        mAdapter = new MyItemClickAdapter(data);
        recyclerView.setAdapter(mAdapter);
        recyclerView.setItemAnimator(new DefaultItemAnimator());
        mAdapter.setOnItemClickListener(new MyItemClickAdapter.OnItemClickLitener() {
            @Override
            public void onItemClick(View view, int position) {
                if(position ==2){
                    mAdapter.addItem("add click", 4);
                    Toast.makeText(ItemClickListViewActivity.this, "增加資料" + position, Toast.LENGTH_SHORT).show();
                }else if(position ==3) {
                    mAdapter.removeItem(2);
                    Toast.makeText(ItemClickListViewActivity.this, "刪除資料" + position, Toast.LENGTH_SHORT).show();
                }else{

                    Toast.makeText(ItemClickListViewActivity.this, "選中" + position, Toast.LENGTH_SHORT).show();
                }
            }
        });
    }
}

以上程式碼就可以為RecyclerView新增item點選事件了。

3.Item增加和刪除

在adpater中增加如下兩個方法:
1)新增資料:

public void addItem(String content, int position) {
        data.add(position, content);
        notifyItemInserted(position);
    }

2)刪除資料:

public void removeItem(int position) {
        data.remove(position);
        notifyItemRemoved(position);
    }

activity中呼叫上面兩個方法,實現增加跟刪除item

mAdapter.setOnItemClickListener(new MyItemClickAdapter.OnItemClickLitener() {
            @Override
            public void onItemClick(View view, int position) {
                if(position ==2){
                    mAdapter.addItem("add click", 4);
                    Toast.makeText(ItemClickListViewActivity.this, "增加資料" + position, Toast.LENGTH_SHORT).show();
                }else if(position ==3) {
                    mAdapter.removeItem(2);
                    Toast.makeText(ItemClickListViewActivity.this, "刪除資料" + position, Toast.LENGTH_SHORT).show();
                }else{

                    Toast.makeText(ItemClickListViewActivity.this, "選中" + position, Toast.LENGTH_SHORT).show();
                }
            }
        });

4.解決增加或者刪除position混亂的問題:

照Google文件描述在使用了notifyItemInserted時候原來位置的position會加1,但是事實證明資料的position位置毫無變化,暫且認為google工程師的錯誤吧,但是我們還是要繼續使用。一般有兩種解決辦法:
1)保留刪除跟新增動畫效果:notifyItemRemoved(position);notifyItemInserted(position);從原始碼可以看出,他只是重新整理當前插入或者刪除的item,不會觸發onBindViewHolder,所以插入或者刪除的item的下方的item的postion會有混亂。所以我們手動來重新整理,程式碼如下:

public void removeItem(int position) {
        data.remove(position);
        notifyItemRemoved(position);
        // 加入如下程式碼保證position的位置正確性
        if (position != data.size() - 1) {
            notifyItemRangeChanged(position, data.size() - position);
        }
    }

    public void addItem(String content, int position) {
        data.add(position, content);
        notifyItemInserted(position);
        // 加入如下程式碼保證position的位置正確性
        if (position != data.size() - 1) {
            notifyItemRangeChanged(position, data.size() - position);
        }
    }

2)去掉動畫:直接使用notifyDataSetChanged();因為使用notifyDataSetChanged();後,動畫則消失了。

public void removeItem(int position) {
        data.remove(position);
        notifyItemRemoved(position);
        notifyDataSetChanged();
    }

    public void addItem(String content, int position) {
        data.add(position, content);
        notifyItemInserted(position);
        notifyDataSetChanged();
    }

5.完整程式碼

activity程式碼:

package com.test.recyclerview.itemclick;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.Toast;

import com.test.recyclerview.R;

import java.util.ArrayList;

public class ItemClickListViewActivity extends AppCompatActivity {

    /**
     * view
     */
    private RecyclerView recyclerView;

    /**
     * 用來確定每一個item如何進行排列擺放,何時展示和隱藏
     */
    private LinearLayoutManager layoutManager;

    /**
     * 介面卡
     */
    private MyItemClickAdapter mAdapter;

    private ArrayList<String> data = new ArrayList<String>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initView();
        initData();
    }

    /**
     * 初始化佈局元件
     */
    private void initView() {
        recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
        //建立預設的線性LayoutManager
        layoutManager = new LinearLayoutManager(this);
//        layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
        recyclerView.setLayoutManager(layoutManager);
        //如果可以確定每個item的高度是固定的,設定這個選項可以提高效能
        recyclerView.setHasFixedSize(true);
    }

    /**
     * 初始化資料
     */
    private void initData() {
        for (int i = 0; i < 100; i++) {
            data.add(i + "--->click");
        }
        //建立並設定Adapter
        mAdapter = new MyItemClickAdapter(data);
        recyclerView.setAdapter(mAdapter);
        recyclerView.setItemAnimator(new DefaultItemAnimator());
        mAdapter.setOnItemClickListener(new MyItemClickAdapter.OnItemClickLitener() {
            @Override
            public void onItemClick(View view, int position) {
                if(position ==2){
                    mAdapter.addItem("add click", 4);
                    Toast.makeText(ItemClickListViewActivity.this, "增加資料" + position, Toast.LENGTH_SHORT).show();
                }else if(position ==3) {
                    mAdapter.removeItem(2);
                    Toast.makeText(ItemClickListViewActivity.this, "刪除資料" + position, Toast.LENGTH_SHORT).show();
                }else{

                    Toast.makeText(ItemClickListViewActivity.this, "選中" + position, Toast.LENGTH_SHORT).show();
                }
            }
        });
    }
}

adapter程式碼:

package com.test.recyclerview.itemclick;

import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.test.recyclerview.R;

import java.util.ArrayList;


public class MyItemClickAdapter extends RecyclerView.Adapter<MyItemClickAdapter.ViewHolder> implements View.OnClickListener {
    private OnItemClickLitener mOnItemClickListener = null;

    public void setOnItemClickListener(OnItemClickLitener listener) {
        this.mOnItemClickListener = listener;
    }

    private ArrayList<String> data;

    public MyItemClickAdapter(ArrayList<String> data) {
        this.data = data;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
        View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.activity_item, viewGroup, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        holder.mTextView.setText(data.get(position));
        holder.mTextView.setTag(holder.getLayoutPosition());
        holder.mTextView.setOnClickListener(this);
    }

    @Override
    public int getItemCount() {
        return data == null ? 0 : data.size();
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.item_text:
                mOnItemClickListener.onItemClick(v, (int) v.getTag());
                break;
        }
    }

    //自定義的ViewHolder,持有每個Item的的所有介面元素
    public static class ViewHolder extends RecyclerView.ViewHolder {
        public TextView mTextView;

        public ViewHolder(View view) {
            super(view);
            mTextView = (TextView) view.findViewById(R.id.item_text);
        }
    }

    public void removeItem(int position) {
        data.remove(position);
        notifyItemRemoved(position);
        // 加入如下程式碼保證position的位置正確性
        if (position != data.size() - 1) {
            notifyItemRangeChanged(position, data.size() - position);
        }
    }

    public void addItem(String content, int position) {
        data.add(position, content);
        notifyItemInserted(position);
        // 加入如下程式碼保證position的位置正確性
        if (position != data.size() - 1) {
            notifyItemRangeChanged(position, data.size() - position);
        }
    }

    public interface OnItemClickLitener {
        void onItemClick(View view, int position);
    }
}

6.完整程式碼下載地址如下所示:

歡迎一起交流討論
群號:469890293

相關推薦

RecyclerView詳細介紹-----解決事件重新整理錯誤

1. 前言 RecyclerView 沒有提供類似ListView的setOnItemClickListener方法,所以只有我們自己為RecyclerView新增點選事件, 本篇文章主要介紹如何新增點選事件,進行Item增加和刪除,並且解決Recyc

10.RecyclerView中的item事件如何實現

recyclerview的使用方法和listview大同小異,但是使用的adapter確實非常不一樣: 1.需要在adapter宣告onclickListener()介面, 2.然後建立介面物件, 3.然後實現介面方法, 4.之後在adapte中的vieholder中繫結例

商品詳情介面跳轉到購物車購物車介面

//佈局檔案 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-aut

android recyclerview 上下滑動導致事件和資料錯亂問題解決

今天遇到一個奇怪的Bug  上下滑動Item時候 再往上滑 撥打電話 與剛開始不一致,網上很多人說setTag種種,但並沒有什麼卵用,很鄙視那些複製貼上的 兩種解決方案 getItemViewType(int position){return position} // 這樣多種佈局

recyclerview巢狀GridView去遮蔽後者的事件而是前者響應到事件

無論是標題中的巢狀方式,還是其它列表控制元件之間的巢狀,都適用。 1、在GirdView的所在佈局的根佈局中設定改屬性: android:descendantFocusability="blacksDescendants"  2、動態設定GirdView的如下屬性:   gridvi

解決datetimepicker不能觸發事件日期外掛位置偏移日期範圍限制的問題

最初的問題: 一開始所遇到的問題是相對簡單的,就是今天的日期是3-20,但是卻可以選擇20號之後的日期。 html程式碼: <form action="web?module=stwmgr&action=Dataprocessing&method=g

RecyclerView的Item事件增加刪除Item瀑布流動畫效果長按拖動ItemRecyclerView複雜佈局、實現新聞頻道選擇器

RecyclerView的Item點選事件的實現,增加和刪除Item使用瀑布流動畫效果,長按拖動Item,RecyclerView複雜佈局的實現使用、RecyclerView去實現今日頭條新聞頻道選擇器。 使用ItemTouchHelper實現Item的拖動交換,由於Recy

RecyclerView打造萬能介面卡事件5.0水波紋效果

一.前言 最近使用到RecyclerView,RecyclerView使用詳解戳這裡,由於使用過張鴻洋大神的ListView萬能Adapter,感覺RecyclerView的Adapter編寫還是太麻煩了,而且沒有點選事件,ok,參考ListView的萬能Ad

Android中Recyclerview使用7----條目中按鈕事件在activity中呼叫(介面回撥)

0引入Recyclerview的支援庫    compile 'com.android.support:recyclerview-v7:23.4.0' 1效果圖: 2程式碼: 2.1MainActivity中: <span style="font-size:18p

RecyclerView 實現瀑布流及事件回撥的介面

RecyclerView 實現瀑布流及點選事件 public class FruitAdapter extends RecyclerView.Adapter<FruitAdapter.ViewHolder> { private List

cocos2d-x中解決事件上層響應下層不響應

解決方案是重寫一個Layer,加在上下層中間,即可只響應上層事件,阻斷了下層的事件,設定優先順序,程式碼如下 #ifndef _TouchBlockLayer_H_ #define _TouchBlockLayer_H_ class TouchBlockLayer:

andorid佈局layout監聽事件佈局內的imageButton無法響應解決方法

今天發現這個問題,使用的是相對佈局,裡面包含一個TextView與ImageButton,相對佈局監聽了onClickListener,本來想整個佈局點選後都能響應一個事件,結果發現ImageButton無法響應。 嘗試了給imagebutton增加 clickable=t

自定義的tabbar在跳轉之後隱藏tabbar後tabbar原來的位置不能響應事件這樣解決

yourInnerViewController.hidesBottomBarWhenPushed = YES; [self.navigationController pushViewControlle

由於某種特殊需求我需要在winform程式中模擬滑鼠事件經過Google終於找到了如下解決方案。

來自:http://outofmemory.cn/code-snippet/1708/how-winform-moni-shubiao-click-event using System; using System.Windows.Forms; using System.Ru

RecyclerView載入不同item並實現其item事件實現新增常用應用的功能

先上效果圖吧 點選加號 勾選需要的應用點選新增 這裡出現了三種item的樣式,一種是加號,一種是應用圖示加文字,最後一種是應用圖示加文字還有個checkBox 這裡RecyclerView是配合CardView使用的。 在AS中使用RecyclerView需要先在buil

jquery定義之後的按鈕事件會產生累計的情況

使用jquery的on()方法為元素綁定了點選事件,點選同時傳送請求。完成後看效果,第一次點選沒有問題。再一次點選後發現傳送了兩次請求,後面再點擊發現請求的數量越來越多。當排查之後,發現只有一個元素綁定了事件,而且只調用了一次之後,得出最有可能的一種情況,就是點選事件被累加綁定了。 $("#ad

可能是最詳細的Android事件處理詳解(三)

前兩篇文章: 可能是最詳細的Android點選事件處理詳解 可能是最詳細的Android點選事件處理詳解(二) 這裡再次延伸一下,在ScrollView和RecyclerView巢狀中touch事件的傳遞過程,以及巢狀滑動衝突的問題。 如上圖,外層是一個Neste

可能是最詳細的Android事件處理詳解()

上一篇我們主要詳細描述了touch事件在各層的傳遞 本篇文章主要是對比touch在不可滾動和可滾動的ViewGroup事件的傳遞過程 如上圖: - 左圖:是ViewGroup巢狀View,不可滑動 - 右圖:也是ViewGroup(RecyclerView)巢

可能是最詳細的Android事件處理詳解

面試的時候,很多時候都會問到Touch事件的傳遞,而且問法角度都有所不同,但是還是會遵循基本的事件傳遞規則的,可能他問的你沒處理過,但是根據基本規則慢慢思考來回答,都不會錯。 一,簡介 首先我們知道touch事件 主要是是在三個方法中傳遞和處理的。分別是:

jquery的事件非動態載入與動態載入

jquery的點選事件,非動態載入點選與動態載入點選寫法不同 1.非動態載入點選 <div id="clickdemo"> <ul> <li>1<li> </ul> </div>點選1觸發 $