SwipeMenuListView類
涉及到的一些知識點桑寨,在onInterceptTouchEvent方法的down事件中的三個方法:
pointToPosition
getChildAt
inRangeOfView
SwipeMenuLayout類
涉及知識點:
GestureDetectorCompat手勢類
以及
手勢類的監(jiān)聽器OnGestureListener
平滑滑動的類ScrollerCompat
詳細解釋
1冬三、pointToPosition
AbsListView類中的方法
/**
* Maps a point to a position in the list.
*
* @param x X in local coordinate
* @param y Y in local coordinate
* @return The position of the item which contains the specified point, or
* {@link #INVALID_POSITION} if the point does not intersect an item.
*/
public int pointToPosition(int x, int y) {
}
解釋是:返回觸摸到的點的position
listview.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
int position = listview.pointToPosition((int)event.getX(), (int)event.getY());
return false;
}
});
可以打印下position的值敦腔,它不存在什么復用不復用的問題己英,實際得到的position值就是item的位置。
2捂龄、getChildAt
/**
* Returns the view at the specified position in the group.
*
* @param index the position at which to get the view from
* @return the view at the specified position or null if the position
* does not exist within the group
*/
public View getChildAt(int index) {
if (index < 0 || index >= mChildrenCount) {
return null;
}
return mChildren[index];
}
由于我們在使用listview的時候漆诽,都存在復用問題,所以在用getChildAt方法得到view時扮休,得到的都是復用的那個view,所以需要用得到的position減去getFirstVisiblePosition
View view = getChildAt(position- getFirstVisiblePosition());
3漩绵、inRangeOfView
這個就是判斷事件是否在某個view內(nèi)部
這個是SwipMenuListView類中自己實現(xiàn)的方法,不是系統(tǒng)方法
/**
* 判斷點擊事件是否在某個view內(nèi)
*
* @param view
* @param ev
* @return
*/
public static boolean inRangeOfView(View view, MotionEvent ev) {
int[] location = new int[2];
view.getLocationOnScreen(location);
int x = location[0];
int y = location[1];
if (ev.getRawX() < x || ev.getRawX() > (x + view.getWidth()) || ev.getRawY() < y || ev.getRawY() > (y + view.getHeight())) {
return false;
}
return true;
}
4、GestureDetectorCompat
private GestureDetectorCompat mGestureDetector;
private OnGestureListener mGestureListener;
mGestureDetector = new GestureDetectorCompat(getContext(),
mGestureListener);
mGestureListener = new SimpleOnGestureListener() {
@Override
public boolean onDown(MotionEvent e) {
return true;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2,
float velocityX, float velocityY) {
return super.onFling(e1, e2, velocityX, velocityY);
}
};
其實在這個接口中有很多關(guān)于手勢的回調(diào)方法:
/**
* A convenience class to extend when you only want to listen for a subset
* of all the gestures. This implements all methods in the
* {@link OnGestureListener} and {@link OnDoubleTapListener} but does
* nothing and return {@code false} for all applicable methods.
*/
public static class SimpleOnGestureListener implements OnGestureListener, OnDoubleTapListener {
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
public void onLongPress(MotionEvent e) {
}
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
return false;
}
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
return false;
}
public void onShowPress(MotionEvent e) {
}
public boolean onDown(MotionEvent e) {
return false;
}
public boolean onDoubleTap(MotionEvent e) {
return false;
}
public boolean onDoubleTapEvent(MotionEvent e) {
return false;
}
public boolean onSingleTapConfirmed(MotionEvent e) {
return false;
}
}
5肛炮、ScrollerCompat
跟Scroller一樣止吐,一般想要實現(xiàn)平滑過渡,可以使用
public static ScrollerCompat create(Context context, Interpolator interpolator) {
return new ScrollerCompat(context, interpolator);
}
這是個靜態(tài)方法侨糟,直接用類可以調(diào)用碍扔,并且可以傳入一個差值器,很有用的秕重。
調(diào)用startScroll方法進行滑動
public void startScroll(int startX, int startY, int dx, int dy, int duration) {
mImpl.startScroll(mScroller, startX, startY, dx, dy, duration);
}
最后需要覆寫computeScroll方法完成
@Override
public void computeScroll() {
// ......
postInvalidate();
// ......
}
postInvalidate會調(diào)用view的draw方法不同,draw方法內(nèi)部會調(diào)用computeScroll(源碼中能找到),循環(huán)調(diào)用完成動畫,computeScroll方法中需要有動畫結(jié)束邏輯二拐。