Skip to content
This repository has been archived by the owner on Jun 9, 2020. It is now read-only.

Commit

Permalink
fix #15, on click is supported on pinned section view
Browse files Browse the repository at this point in the history
  • Loading branch information
beworker committed Nov 1, 2013
1 parent 2b5e973 commit 67b322c
Showing 1 changed file with 90 additions and 53 deletions.
143 changes: 90 additions & 53 deletions library/src/com/hb/views/PinnedSectionListView.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@
import android.content.Context;
import android.database.DataSetObserver;
import android.graphics.Canvas;
import android.graphics.PointF;
import android.graphics.Rect;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.SoundEffectConstants;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.accessibility.AccessibilityEvent;
import android.widget.AbsListView;
import android.widget.ListAdapter;
Expand Down Expand Up @@ -66,9 +68,12 @@ static class PinnedViewShadow {
}
};

// fields used in onTouchEvent handler
// fields used for handling touch events
private final Rect mTouchRect = new Rect();
private final PointF mTouchPoint = new PointF();
private final int mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
private View mTouchTarget;
private MotionEvent mDownEvent;

/** Delegating listener, can be null. */
OnScrollListener mDelegateOnScrollListener;
Expand Down Expand Up @@ -273,61 +278,11 @@ public void setOnScrollListener(OnScrollListener listener) {
}
}

private boolean isPinnedViewTouched(View view, int x, int y) {
private boolean isPinnedViewTouched(View view, float x, float y) {
view.getHitRect(mTouchRect);
mTouchRect.top += mTranslateY;
mTouchRect.bottom += mTranslateY;
return mTouchRect.contains(x, y);
}

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {

int x = (int) ev.getX();
int y = (int) ev.getY();

// TODO cancel old target if UP event

// create new touch target, if needed
if (mTouchTarget == null
&& mPinnedShadow != null
&& isPinnedViewTouched(mPinnedShadow.view, x, y)) {
mTouchTarget = mPinnedShadow.view;
}

// dispatch event to the new touch target, if such
if (mTouchTarget != null) {
if (isPinnedViewTouched(mTouchTarget, x, y)) {
mTouchTarget.dispatchTouchEvent(ev);
}

// complete touch sequence properly
if (ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_CANCEL) {
mTouchTarget = null;
super.dispatchTouchEvent(ev);
performPinnedItemClick();
}
return true;
}

// call super if this was not our pinned view
return super.dispatchTouchEvent(ev);
}

protected boolean performPinnedItemClick() {
if (mPinnedShadow == null) return false;

OnItemClickListener listener = getOnItemClickListener();
if (listener != null) {
View view = mPinnedShadow.view;
playSoundEffect(SoundEffectConstants.CLICK);
if (view != null) {
view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
}
listener.onItemClick(this, view, mPinnedShadow.position, mPinnedShadow.id);
return true;
}
return false;
return mTouchRect.contains((int)x, (int)y);
}

@Override
Expand Down Expand Up @@ -399,4 +354,86 @@ protected void dispatchDraw(Canvas canvas) {
canvas.restore();
}
}

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {

final float x = ev.getX();
final float y = ev.getY();
final int action = ev.getAction();

if (action == MotionEvent.ACTION_DOWN
&& mTouchTarget == null
&& mPinnedShadow != null
&& isPinnedViewTouched(mPinnedShadow.view, x, y)) {

// user touched pinned view
mTouchTarget = mPinnedShadow.view;
mTouchPoint.x = x;
mTouchPoint.y = y;

mDownEvent = MotionEvent.obtain(ev);
}

if (mTouchTarget != null) {
if (isPinnedViewTouched(mTouchTarget, x, y)) { // forward event to pinned view
mTouchTarget.dispatchTouchEvent(ev);
}

if (action == MotionEvent.ACTION_UP) { // perform onClick on pinned view
super.dispatchTouchEvent(ev);
performPinnedItemClick();
clearTouchTarget();

} else if (action == MotionEvent.ACTION_CANCEL) { // cancel
clearTouchTarget();

} else if (action == MotionEvent.ACTION_MOVE) {
if (Math.abs(y - mTouchPoint.y) > mTouchSlop) {

// cancel sequence on touch target
MotionEvent event = MotionEvent.obtain(ev);
event.setAction(MotionEvent.ACTION_CANCEL);
mTouchTarget.dispatchTouchEvent(event);
event.recycle();

// provide correct sequence to super class for further handling
super.dispatchTouchEvent(mDownEvent);
super.dispatchTouchEvent(ev);
clearTouchTarget();

}
}

return true;
}

// call super if this was not our pinned view
return super.dispatchTouchEvent(ev);
}

private void clearTouchTarget() {
mTouchTarget = null;
if (mDownEvent != null) {
mDownEvent.recycle();
mDownEvent = null;
}
}

private boolean performPinnedItemClick() {
if (mPinnedShadow == null) return false;

OnItemClickListener listener = getOnItemClickListener();
if (listener != null) {
View view = mPinnedShadow.view;
playSoundEffect(SoundEffectConstants.CLICK);
if (view != null) {
view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
}
listener.onItemClick(this, view, mPinnedShadow.position, mPinnedShadow.id);
return true;
}
return false;
}

}

0 comments on commit 67b322c

Please sign in to comment.