標籤:textview intercept zhang 中介 androi 進一步 測試的 one pat
??
Android RecyclerView單擊、長按事件:基於OnItemTouchListener + GestureDetector標準實現
Android RecyclerView雖然擁有ListView絕大多數的功能,但Android RecyclerView卻沒有實現像ListView那樣的點擊事件、長按事件的標準實現方式,我在附錄文章1中介紹的方式,實現了典型的RecyclerView的item點擊事件,大致的思路是通過為RecyclerView的ViewHolder添加View.OnClickListener事件達到點擊事件的監聽,這種實現方式可以正常工作,但不太標準。現在給出一種較為規範的Android官方實現。
翻了Android RecyclerView的官方文檔,這文檔中確實沒有提供像ListView的OnItem點擊事件,但是注意到有一個addOnItemTouchListener,根據官方文檔的描述,addOnItemTouchListener是Android官方文檔中留下的點擊事件的線索入口,文檔中也暗示開發人員應該從這個事件監聽介面中實現所需的邏輯代碼。但是直接new一個對象傳遞過去,則需要自己解析Android Touch Event複雜的處理,所幸Android官方給出了RecyclerView.SimpleOnItemTouchListener,顧名思義,就是一個簡化的OnItemTouchListener。雖然有了SimpleOnItemTouchListener,到此還沒完,因為SimpleOnItemTouchListener只是事件攔截處理的入口,真正要做事情的主角是:GestureDetector。通過GestureDetector裡面的攔截到的所託管的單擊、長按事件,才最終實現了RecyclerView的單擊、長按事件。
完整代碼:
package zhangphil.app;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.support.v7.widget.LinearLayoutManager;import android.support.v7.widget.RecyclerView;import android.view.GestureDetector;import android.view.MotionEvent;import android.view.View;import android.view.ViewGroup;import android.widget.TextView;import android.widget.Toast;public class MainActivity extends AppCompatActivity { private RecyclerView mRecyclerView; private GestureDetector mGestureDetector; //長按事件 private OnItemLongClickListener mOnItemLongClickListener = new OnItemLongClickListener() { @Override public void onItemLongClick(int position, View childView) { Toast.makeText(getApplication(), "長按:" + position, Toast.LENGTH_SHORT).show(); } }; //單擊事件 private OnItemClickListener mOnItemClickListener = new OnItemClickListener() { @Override public void onItemClick(int position, View childView) { Toast.makeText(getApplication(), "單擊:" + position, Toast.LENGTH_SHORT).show(); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //建立一個簡單的用以測試的RecyclerView mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView); LinearLayoutManager layoutManager = new LinearLayoutManager(this); layoutManager.setOrientation(LinearLayoutManager.VERTICAL); mRecyclerView.setLayoutManager(layoutManager); mRecyclerView.setAdapter(new ItemAdapter()); //以下是添加點擊、長按事件的關鍵代碼 mRecyclerView.addOnItemTouchListener(new RecyclerView.SimpleOnItemTouchListener() { @Override public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) { if (mGestureDetector.onTouchEvent(e)) { return true; } return false; } }); mGestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() { //長按事件 @Override public void onLongPress(MotionEvent e) { super.onLongPress(e); if (mOnItemLongClickListener != null) { View childView = mRecyclerView.findChildViewUnder(e.getX(), e.getY()); if (childView != null) { int position = mRecyclerView.getChildLayoutPosition(childView); mOnItemLongClickListener.onItemLongClick(position, childView); } } } //單擊事件 @Override public boolean onSingleTapUp(MotionEvent e) { if (mOnItemClickListener != null) { View childView = mRecyclerView.findChildViewUnder(e.getX(), e.getY()); if (childView != null) { int position = mRecyclerView.getChildLayoutPosition(childView); mOnItemClickListener.onItemClick(position, childView); return true; } } return super.onSingleTapUp(e); } }); } //長按事件介面 public interface OnItemLongClickListener { public void onItemLongClick(int position, View childView); } //單擊事件介面 public interface OnItemClickListener { public void onItemClick(int position, View childView); } private class ItemViewHolder extends RecyclerView.ViewHolder { public TextView text; public ItemViewHolder(View itemView) { super(itemView); text = (TextView) itemView.findViewById(android.R.id.text1); } } private class ItemAdapter extends RecyclerView.Adapter<ItemViewHolder> { @Override public ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = View.inflate(parent.getContext(), android.R.layout.simple_list_item_1, null); ItemViewHolder holder = new ItemViewHolder(view); return holder; } @Override public void onBindViewHolder(ItemViewHolder holder, int position) { holder.text.setText(String.valueOf(position)); } @Override public int getItemCount() { return 99; } }}
因為我是在onInterceptTouchEvent裡面攔截了RecyclerView的觸摸事件,並通過GestureDetector
託管處理,由此可以延伸、進一步封裝出更多更複雜的事件處理介面。
附錄:
1,《RecyclerView點擊事件》連結:http://blog.csdn.net/zhangphil/article/details/46771865
Android RecyclerView單擊、長按事件標準實現:基於OnItemTouchListener + GestureDetector