1. 程式人生 > >RecyclerView中item點選事件

RecyclerView中item點選事件

自從Google推出RecyclerView後,它就成為"寵兒",自定義外掛式的元件用起來很爽。但是很遺憾的是,Google並沒有給我們提供item的點選事件函式,但是我們可以類似ListView的item點選事件來構造出我們自己的RecyclerView item的點選事件。首先我們看ListView如何用setOnItemClickListener()方法實現item的點選事件的呢,搞明白這個問題,我們還得去看ListView原始碼,開啟原始碼發現,查詢該方法,竟然查不到,是不是它父類AbsListView中的函式呢,其實也不是的。原來setOnItemClickListener()是AdapterView類中的方法,終於理清楚了關係:

ListView extends AbsListView
     abstract class AbsListView extends AdapterView<ListAdapter> implements XXXXX
              abstract class AdapterView<T extends Adapter> extends ViewGroup
                   abstract class ViewGroup extends View implements ViewParent, ViewManager

上面簡單給出了ListView類"祖宗"幾代的關係圖,原來ListView就是個View,哈哈,廢話不多說了,感興趣的朋友可以自己看原始碼。

那麼我們瞧瞧setOnItemClickListener()是如何實現的呢?

public interface OnItemClickListener {
    /**
     * Callback method to be invoked when an item in this AdapterView has
     * been clicked.
     * <p>
     * Implementers can call getItemAtPosition(position) if they need
     * to access the data associated with the selected item.
     *
     * @param parent The AdapterView where the click happened.
     * @param view The view within the AdapterView that was clicked (this
     *            will be a view provided by the adapter)
     * @param position The position of the view in the adapter.
     * @param id The row id of the item that was clicked.
     */
    void onItemClick(AdapterView<?> parent, View view, int position, long id);
}

/**
 * Register a callback to be invoked when an item in this AdapterView has
 * been clicked.
 *
 * @param listener The callback that will be invoked.
 */
public void setOnItemClickListener(@Nullable OnItemClickListener listener) {
    mOnItemClickListener = listener;
}
從上的原始碼中,可以找到,用到的是介面回撥來完成的。上面的註釋說明的太清楚了,不忍心刪除因為我沒有註釋說的好。
下面給出ListView物件變數如何實現item點選事件的:
 listView.setOnItemClickListener(new OnItemClickListener() {              public void onItemClick(AdapterView<?> arg0,View view,final int index,long arg3){
                    /*
                     *呼叫者具體的實現邏輯
                     */

}

  });
 原來就是這樣實現的啊!現在是不是很明白了呢?
 說了那麼多,接下來我們實戰吧!
 在開始之前,看下最終demo實現的效果:
上面每一個item都是一個卡片狀,而且點選的時候還有水波紋效果,實現上面的效果用到CardView,下面也會簡單的介紹CardView使用。
我們item佈局檔案list_text.xml:(主要就是顯示文字,佈局比較簡單)
<android.support.v7.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto" android:id="@+id/card_view" android:layout_width="match_parent" android:layout_height="match_parent" card_view:cardBackgroundColor="@color/pink" android:layout_marginLeft="@dimen/activity_horizontal_margin" android:layout_marginRight="@dimen/activity_horizontal_margin" android:layout_marginTop="5dp" android:layout_marginBottom="15dp" card_view:cardCornerRadius="10dp" card_view:cardElevation="10dp" android:foreground="@drawable/rippler" xmlns:android="http://schemas.android.com/apk/res/android"> <TextView android:id="@+id/text" android:layout_width="match_parent" android:gravity="center" android:textSize="50sp" android:layout_height="wrap_content" /> </android.support.v7.widget.CardView>

主佈局檔案activity_main.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v7.widget.RecyclerView android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="match_parent"/> </RelativeLayout>

下面就是編寫程式碼了,為了方便,全部放在一個類中了:

public class MainActivity extends Activity { private ArrayList<String> array = new ArrayList<String>(); private RecyclerView recycler; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initdata(); recycler = (RecyclerView)findViewById(R.id.recycler_view); LinearLayoutManager layout = new LinearLayoutManager(this); recycler.setLayoutManager(layout); MyAdapter adapter = new MyAdapter(); recycler.setAdapter(adapter);
<span style="font-size: 11.3pt;">                 </span><span style="font-family: Consolas; font-size: 11.3pt;">adapter.setOnItemClickListener(new onRecyclerViewItemClickListener(){</span>
            @Override    
            public void onItemClick(View view,String data){
                Toast.makeText(MainActivity.this,"你好,我是"+data, Toast.LENGTH_SHORT).show();
            }});
	}
	   
	public void initdata(){
		
		for(char i='a';i<='z';i++){
			array.add(String.valueOf(i));
			System.out.print(i);
		}
	}
	
	public class  MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder>{
         
		private onRecyclerViewItemClickListener itemClickListener = null;
		
		@Override
		public int getItemCount() {
			// TODO 自動生成的方法存根
			return array.size();
		}
		public void onBindViewHolder(ViewHolder viewholder, int position) {  //為item佈局中的控制元件設定數值
			// TODO 自動生成的方法存根
			viewholder.textview.setText(array.get(position));
			viewholder.itemView.setTag(viewholder.textview.getText());
		}

		@Override
		public ViewHolder onCreateViewHolder(ViewGroup viewgroup, int position) {
			// TODO 自動生成的方法存根
			View view = LayoutInflater.from(viewgroup.getContext()).inflate(R.layout.list_text,viewgroup,false); //獲取item的佈局
			view.setOnClickListener(new OnClickListener() {   //為每一個item繫結監聽
				@Override
				public void onClick(View v) {
					// TODO 自動生成的方法存根
					if (itemClickListener != null)<span style="font-family: Consolas; font-size: 11.3pt;">              </span>
                              itemClickListener.onItemClick(v,(String)v.getTag());
			         
			          }
				}
			});
			
			return new ViewHolder(view);    
			
		}
		   
		public  class ViewHolder extends RecyclerView.ViewHolder{  //獲取item中的控制元件
            private   TextView textview;
			public ViewHolder(View itemView) {
				super(itemView);
				// TODO 自動生成的建構函式存根
				textview = (TextView)itemView.findViewById(R.id.text);
			}
			
			
		}
		
		public void setOnItemClickListener(onRecyclerViewItemClickListener listener) {
	         this.itemClickListener = listener;
	    	//  Log.d("ddd", itemClickListener.toString());
	    }
	 
	}

	public  interface onRecyclerViewItemClickListener {

		void onItemClick(View v, String tag);
	}
}

看下上面的效果吧:

有朋友會問,怎麼少了item之間的分隔條啊,對,下面我們就把分隔條畫出來。說到這裡感覺本篇介紹的有點多,不過後面也會陸續介紹。

public class Dividerlios extends RecyclerView.ItemDecoration{
    private final static int ARRAS[] = {android.R.attr.listDivider};//使用系統提供的分隔條   當然也可以自己繪製
    private Drawable drawDivider;
    
	public Dividerlios(Context context){
		TypedArray a = context.obtainStyledAttributes(ARRAS);
		drawDivider = a.getDrawable(0);
		a.recycle();
	}
	
	public void onDrawOver(Canvas canvas,RecyclerView recyclerView){ //在canvas上畫分隔條,要獲得分隔條的座標
		
		int left = recyclerView.getPaddingLeft();  
		int right = recyclerView.getWidth() - recyclerView.getPaddingRight();
		
		int childCount = recyclerView.getChildCount();
		
		for(int i=0;i<childCount;i++){  //繪製全部的分隔條
		   View child = recyclerView.getChildAt(i);
		    RecyclerView.LayoutParams parame = (RecyclerView.LayoutParams)child.getLayoutParams();
		    
		    int top = child.getBottom() + parame.bottomMargin;
		    int bottom = top + drawDivider.getIntrinsicHeight();
		    drawDivider.setBounds(left, top, right, bottom);
		    drawDivider.draw(canvas);
		}
	}
} 

在MainActivity.java中新增:

Dividerlios divider= new Dividerlios(MainActivity.this);
	    recycler.addItemDecoration(divider);

然後上面的分割線效果就出來了。感興趣朋友可以自己繪製分割線。

下面簡單說明下,item裡實現波紋和前景色變化,可以我們自定義drawable資原始檔。

selecter.xml:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true">
        <shape android:shape="rectangle">
            <solid android:color="#18ffc400"/>
        </shape>
    </item>
    <item android:state_focused="true"  
        android:state_enabled="true">
        <shape android:shape="rectangle">
        <solid android:color="#0f000000"/>
        </shape>
    </item>

rippler.xml:

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android" 
        android:color="#20000000"
        android:drawable="@drawable/<span style="font-family: Consolas; font-size: 15.0667px; white-space: pre;">selecter.xml</span>" />

關於上面drawable資源如何使用,後面的文章會說明。這裡不再說明。

很久沒更新部落格,寫部落格主要為了鞏固知識,如果能幫助到需要的朋友,我會非常開心。

更多文章請關注微信公眾號: