標籤:android style blog http color os io 使用 java
1、設計思路
在Scroller的應用--滑屏實現中使用Scroller實現滑屏效果,這裡使用Scroller與ListView實作類別似QQ滑動,然後點擊刪除功能,設計思路是Item使用Scroller實現滑動,ListView根據觸摸判斷是橫向滑動還是豎直滑動,關於點擊事件處理思路:對於View的onClick事件跟平常一樣,裡面針對OnItemClick做了處理,判斷觸摸距離來判斷,如果小於5的話,在Item的onTouchEvent方法中的MotionEvent.ACTION_UP裡面返回false,這樣ListView裡面的dispatchTouchEvent的super.dispatchTouchEvent(event)就會返回false,根據x,y擷取當前position以及點擊的view,調用super.performItemClick(view, position, view.getId());來告訴ListView出發onItemClick事件。
2、Item的代碼
package com.jwzhangjie.scrollview;import android.content.Context;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.view.View;import android.widget.LinearLayout;import android.widget.Scroller;public class ListItemDelete extends LinearLayout {private Scroller mScroller;// 滑動控制private float mLastMotionX;// 記住上次觸控螢幕的位置private int deltaX;private int back_width;private float downX;public ListItemDelete(Context context) {this(context, null);}public ListItemDelete(Context context, AttributeSet attrs) {super(context, attrs);init(context);}private void init(Context context) {mScroller = new Scroller(context);}@Overridepublic void computeScroll() {if (mScroller.computeScrollOffset()) {// 會更新Scroller中的當前x,y位置scrollTo(mScroller.getCurrX(), mScroller.getCurrY());postInvalidate();}}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);int count = getChildCount();for (int i = 0; i < count; i++) {measureChild(getChildAt(i), widthMeasureSpec, heightMeasureSpec);if (i == 1) {back_width = getChildAt(i).getMeasuredWidth();}}}@Overridepublic boolean onTouchEvent(MotionEvent event) {int action = event.getAction();float x = event.getX();switch (action) {case MotionEvent.ACTION_DOWN:Log.e("test", "item ACTION_DOWN");mLastMotionX = x;downX = x;break;case MotionEvent.ACTION_MOVE:Log.e("test", back_width + " item ACTION_MOVE " + getScrollX());deltaX = (int) (mLastMotionX - x);mLastMotionX = x;int scrollx = getScrollX() + deltaX;if (scrollx > 0 && scrollx < back_width) {scrollBy(deltaX, 0);} else if (scrollx > back_width) {scrollTo(back_width, 0);} else if (scrollx < 0) {scrollTo(0, 0);}break;case MotionEvent.ACTION_UP:Log.e("test", "item ACTION_UP");int scroll = getScrollX();if (scroll > back_width / 2) {scrollTo(back_width, 0);} else {scrollTo(0, 0);}if (Math.abs(x - downX) < 5) {// 這雷根據點擊距離來判斷是否是itemClickreturn false;}break;case MotionEvent.ACTION_CANCEL:scrollTo(0, 0);break;}return true;}@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {int margeLeft = 0;int size = getChildCount();for (int i = 0; i < size; i++) {View view = getChildAt(i);if (view.getVisibility() != View.GONE) {int childWidth = view.getMeasuredWidth();// 將內部子孩子橫排排列view.layout(margeLeft, 0, margeLeft + childWidth,view.getMeasuredHeight());margeLeft += childWidth;}}}}
3、ListView的代碼
package com.jwzhangjie.scrollview;import android.content.Context;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.view.View;import android.widget.ListView;public class ScrollListviewDelete extends ListView {private float minDis = 10;private float mLastMotionX;// 記住上次X觸控螢幕的位置private float mLastMotionY;// 記住上次Y觸控螢幕的位置private boolean isLock = false;public ScrollListviewDelete(Context context, AttributeSet attrs) {super(context, attrs);}/** * 如果一個ViewGroup的onInterceptTouchEvent()方法返回true,說明Touch事件被截獲, * 子View不再接收到Touch事件,而是轉向本ViewGroup的 * onTouchEvent()方法處理。從Down開始,之後的Move,Up都會直接在onTouchEvent()方法中處理。 * 先前還在處理touch event的child view將會接收到一個 ACTION_CANCEL。 * 如果onInterceptTouchEvent()返回false,則事件會交給child view處理。 */@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {if (!isIntercept(ev)) {return false;}return super.onInterceptTouchEvent(ev);}@Overridepublic boolean dispatchTouchEvent(MotionEvent event) {boolean dte = super.dispatchTouchEvent(event);if (MotionEvent.ACTION_UP == event.getAction() && !dte) {//onItemClickint position = pointToPosition((int)event.getX(), (int)event.getY());View view = getChildAt(position);super.performItemClick(view, position, view.getId());}return dte;}@Override// 處理點擊事件,如果是手勢的事件則不作點擊事件 普通Viewpublic boolean performClick() {return super.performClick();}@Override// 處理點擊事件,如果是手勢的事件則不作點擊事件 ListViewpublic boolean performItemClick(View view, int position, long id) {return super.performItemClick(view, position, id);}/** * 檢測是ListView滑動還是item滑動 isLock 一旦判讀是item滑動,則在up之前都是返回false */private boolean isIntercept(MotionEvent ev) {float x = ev.getX();float y = ev.getY();int action = ev.getAction();switch (action) {case MotionEvent.ACTION_DOWN:Log.e("test", "isIntercept ACTION_DOWN "+isLock);mLastMotionX = x;mLastMotionY = y;break;case MotionEvent.ACTION_MOVE:Log.e("test", "isIntercept ACTION_MOVE "+isLock);if (!isLock) {float deltaX = Math.abs(mLastMotionX - x);float deltay = Math.abs(mLastMotionY - y);mLastMotionX = x;mLastMotionY = y;if (deltaX > deltay && deltaX > minDis) {isLock = true;return false;}} else {return false;}break;case MotionEvent.ACTION_UP:Log.e("test", "isIntercept ACTION_UP "+isLock);isLock = false;break;case MotionEvent.ACTION_CANCEL:Log.e("test", "isIntercept ACTION_CANCEL "+isLock);isLock = false;break;}return true;}}
4、Activity代碼
package com.jwzhangjie.scrollview;import android.content.Context;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.view.View;import android.widget.ListView;public class ScrollListviewDelete extends ListView {private float minDis = 10;private float mLastMotionX;// 記住上次X觸控螢幕的位置private float mLastMotionY;// 記住上次Y觸控螢幕的位置private boolean isLock = false;public ScrollListviewDelete(Context context, AttributeSet attrs) {super(context, attrs);}/** * 如果一個ViewGroup的onInterceptTouchEvent()方法返回true,說明Touch事件被截獲, * 子View不再接收到Touch事件,而是轉向本ViewGroup的 * onTouchEvent()方法處理。從Down開始,之後的Move,Up都會直接在onTouchEvent()方法中處理。 * 先前還在處理touch event的child view將會接收到一個 ACTION_CANCEL。 * 如果onInterceptTouchEvent()返回false,則事件會交給child view處理。 */@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {if (!isIntercept(ev)) {return false;}return super.onInterceptTouchEvent(ev);}@Overridepublic boolean dispatchTouchEvent(MotionEvent event) {boolean dte = super.dispatchTouchEvent(event);if (MotionEvent.ACTION_UP == event.getAction() && !dte) {//onItemClickint position = pointToPosition((int)event.getX(), (int)event.getY());View view = getChildAt(position);super.performItemClick(view, position, view.getId());}return dte;}@Override// 處理點擊事件,如果是手勢的事件則不作點擊事件 普通Viewpublic boolean performClick() {return super.performClick();}@Override// 處理點擊事件,如果是手勢的事件則不作點擊事件 ListViewpublic boolean performItemClick(View view, int position, long id) {return super.performItemClick(view, position, id);}/** * 檢測是ListView滑動還是item滑動 isLock 一旦判讀是item滑動,則在up之前都是返回false */private boolean isIntercept(MotionEvent ev) {float x = ev.getX();float y = ev.getY();int action = ev.getAction();switch (action) {case MotionEvent.ACTION_DOWN:Log.e("test", "isIntercept ACTION_DOWN "+isLock);mLastMotionX = x;mLastMotionY = y;break;case MotionEvent.ACTION_MOVE:Log.e("test", "isIntercept ACTION_MOVE "+isLock);if (!isLock) {float deltaX = Math.abs(mLastMotionX - x);float deltay = Math.abs(mLastMotionY - y);mLastMotionX = x;mLastMotionY = y;if (deltaX > deltay && deltaX > minDis) {isLock = true;return false;}} else {return false;}break;case MotionEvent.ACTION_UP:Log.e("test", "isIntercept ACTION_UP "+isLock);isLock = false;break;case MotionEvent.ACTION_CANCEL:Log.e("test", "isIntercept ACTION_CANCEL "+isLock);isLock = false;break;}return true;}}
5、XML代碼
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <com.jwzhangjie.scrollview.ScrollListviewDelete android:id="@android:id/list" android:layout_width="match_parent" android:layout_height="match_parent" /></LinearLayout>
<?xml version="1.0" encoding="utf-8"?><com.jwzhangjie.scrollview.ListItemDelete xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <LinearLayout android:id="@+id/front" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/bg_item_list_8" android:gravity="center" android:orientation="horizontal" > <TextView android:id="@+id/itemData" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="測試資料" /> </LinearLayout> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:orientation="horizontal" > <Button android:id="@+id/btnNao" android:layout_width="wrap_content" android:layout_height="match_parent" android:background="@drawable/bg_item_list_4" android:text="鬧鈴" /> <Button android:id="@+id/btnDelete" android:layout_width="wrap_content" android:layout_height="match_parent" android:background="@drawable/bg_item_list_5" android:text="刪除" /> </LinearLayout></com.jwzhangjie.scrollview.ListItemDelete>
6、介面效果
代碼地址:https://github.com/jwzhangjie/-ScrollerDelete
Scroller應用:ListView滑動刪除