From 8f604a3325573683f0ca0d2d2fc1de7a2c3ffb50 Mon Sep 17 00:00:00 2001 From: Robert Szabo Date: Thu, 27 Mar 2014 16:48:44 -0500 Subject: [PATCH] Adding click events to the markers --- README.md | 6 +- .../sababado/circularview/CircularView.java | 67 +++++++++-------- .../circularview/CircularViewObject.java | 71 +++++++++++++------ .../com/sababado/circularview/Marker.java | 4 +- .../circularview/sample/MainActivity.java | 27 ++++--- 5 files changed, 107 insertions(+), 68 deletions(-) diff --git a/README.md b/README.md index 9234354..d05c537 100644 --- a/README.md +++ b/README.md @@ -60,11 +60,11 @@ circularView.setAdapter(mAdapter); Click events can be received from the `CircularView`. ####Center Click -The center of the view is the center circle. This can be seen in the blue in the screenshot above. To receive this click event set a `View.OnClickListener` into `circularView.setOnCenterCircleClickListener(l)`. For example: +The center of the view is the center circle. This can be seen in the blue in the screenshot above. To receive this click event set a `CircularView.OnClickListener` into `circularView.setOnCircularViewObjectClickListener(l)`. For example: ```JAVA -circularView.setOnCenterCircleClickListener(new View.OnClickListener() { +circularView.setOnCircularViewObjectClickListener(new CircularView.OnClickListener() { @Override - public void onClick(View v) { + public void onClick(final CircularView view, final CircularViewObject circularViewObject) { // Do something. } }); diff --git a/lib/src/main/java/com/sababado/circularview/CircularView.java b/lib/src/main/java/com/sababado/circularview/CircularView.java index 958c2df..ed6341c 100644 --- a/lib/src/main/java/com/sababado/circularview/CircularView.java +++ b/lib/src/main/java/com/sababado/circularview/CircularView.java @@ -13,7 +13,6 @@ import android.text.TextPaint; import android.util.AttributeSet; import android.util.DisplayMetrics; -import android.util.StateSet; import android.view.MotionEvent; import android.view.View; @@ -41,7 +40,7 @@ public class CircularView extends View { private BaseCircularViewAdapter mAdapter; private final AdapterDataSetObserver mAdapterDataSetObserver = new AdapterDataSetObserver(); - private OnClickListener mOnCenterCircleClickListener; + private OnClickListener mOnCircularViewObjectClickListener; private ArrayList mMarkerList; private CircularViewObject mCircle; @@ -412,38 +411,33 @@ public CircularViewObject getCenterCircle() { @Override public boolean onTouchEvent(MotionEvent event) { boolean handled = false; - final int action = event.getAction(); - - //TODO There is a bug where the state doesn't seem to change on the first click (down/move/up) - final boolean isEventInCenterCircle = - mCircle == null ? false : mCircle.isInCenterCircle(event.getX(), event.getY()); - if (action == MotionEvent.ACTION_DOWN) { - // check if center - if (isEventInCenterCircle) { - setCenterCircleState(PRESSED_STATE_SET); - handled = true; - } - } else if (action == MotionEvent.ACTION_UP) { - if (isEventInCenterCircle) { - setCenterCircleState(StateSet.NOTHING); - if (mOnCenterCircleClickListener != null) { - mOnCenterCircleClickListener.onClick(this); + + // check all markers + if(mMarkerList != null) { + for(final CircularViewObject object : mMarkerList) { + final int status = object.onTouchEvent(event); + if(status >= 0) { + handled = true; + if(status == MotionEvent.ACTION_UP && mOnCircularViewObjectClickListener != null) { + mOnCircularViewObjectClickListener.onClick(this, object); + } + break; } - handled = true; } - } else if (action == MotionEvent.ACTION_MOVE) { - if (!isEventInCenterCircle) { - setCenterCircleState(StateSet.NOTHING); + } + + // check center circle + if(!handled && mCircle != null) { + final int status = mCircle.onTouchEvent(event); + if(status >= 0) { handled = true; + if(status == MotionEvent.ACTION_UP && mOnCircularViewObjectClickListener != null) { + mOnCircularViewObjectClickListener.onClick(this, mCircle); + } } } - return handled || super.onTouchEvent(event); - } - void setCenterCircleState(final int[] stateSet) { - if (mCircle != null) { - mCircle.setState(stateSet); - } + return handled || super.onTouchEvent(event); } /** @@ -451,8 +445,8 @@ void setCenterCircleState(final int[] stateSet) { * * @param l Listener to receive a callback. */ - public void setOnCenterCircleClickListener(OnClickListener l) { - mOnCenterCircleClickListener = l; + public void setOnCircularViewObjectClickListener(OnClickListener l) { + mOnCircularViewObjectClickListener = l; } /** @@ -564,6 +558,18 @@ public void onInvalidated() { } } + /** + * Use this to register for click event callbacks from CircularEventObjects + */ + public interface OnClickListener { + /** + * Called when the circular view object has been clicked. + * @param view The circular view that the object belongs to. + * @param circularViewObject The circular view object that was clicked. + */ + public void onClick(CircularView view, CircularViewObject circularViewObject); + } + /** * This method converts device specific pixels to density independent pixels. * @@ -577,5 +583,4 @@ public static float convertPixelsToDp(float px, Context context) { float dp = px / (metrics.densityDpi / 160f); return dp; } - } \ No newline at end of file diff --git a/lib/src/main/java/com/sababado/circularview/CircularViewObject.java b/lib/src/main/java/com/sababado/circularview/CircularViewObject.java index dd6750a..b8a8aac 100644 --- a/lib/src/main/java/com/sababado/circularview/CircularViewObject.java +++ b/lib/src/main/java/com/sababado/circularview/CircularViewObject.java @@ -7,6 +7,8 @@ import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.util.Log; +import android.util.StateSet; +import android.view.MotionEvent; import android.view.View; import java.util.concurrent.atomic.AtomicInteger; @@ -16,15 +18,15 @@ */ public class CircularViewObject { private static final AtomicInteger sAtomicIdCounter = new AtomicInteger(0); - protected int id; + private int id; protected float radius; protected float radiusPadding; protected float x; protected float y; private Paint paint; - protected Context context; - protected Drawable drawable; - protected CircularView.AdapterDataSetObserver mAdapterDataSetObserver; + private Context context; + private Drawable drawable; + private CircularView.AdapterDataSetObserver mAdapterDataSetObserver; private boolean fitToCircle; /** @@ -146,9 +148,7 @@ public void setSrc(final int resId) { */ public void setSrc(final Drawable drawable) { this.drawable = drawable; - if (mAdapterDataSetObserver != null) { - mAdapterDataSetObserver.onInvalidated(); - } + invalidate(); } void setCallback(final View view) { @@ -201,9 +201,7 @@ public float getY() { */ public void setY(float y) { this.y = y; - if (mAdapterDataSetObserver != null) { - mAdapterDataSetObserver.onInvalidated(); - } + invalidate(); } /** @@ -222,9 +220,7 @@ public float getX() { */ public void setX(float x) { this.x = x; - if (mAdapterDataSetObserver != null) { - mAdapterDataSetObserver.onInvalidated(); - } + invalidate(); } /** @@ -243,9 +239,7 @@ public float getRadius() { */ public void setRadius(float radius) { this.radius = radius; - if (mAdapterDataSetObserver != null) { - mAdapterDataSetObserver.onInvalidated(); - } + invalidate(); } /** @@ -264,9 +258,7 @@ public float getRadiusPadding() { */ public void setRadiusPadding(float radiusPadding) { this.radiusPadding = radiusPadding; - if (mAdapterDataSetObserver != null) { - mAdapterDataSetObserver.onInvalidated(); - } + invalidate(); } /** @@ -285,9 +277,7 @@ public int getCenterBackgroundColor() { */ public void setCenterBackgroundColor(int centerBackgroundColor) { paint.setColor(centerBackgroundColor); - if (mAdapterDataSetObserver != null) { - mAdapterDataSetObserver.onInvalidated(); - } + invalidate(); } CircularView.AdapterDataSetObserver getAdapterDataSetObserver() { @@ -312,6 +302,43 @@ public boolean isFitToCircle() { */ public void setFitToCircle(boolean fitToCircle) { this.fitToCircle = fitToCircle; + invalidate(); + } + + /** + * Act on a touch event. Returns a status based on what action was taken. + * @param event The motion event that was just received. + * @return Return a negative number if the event wasn't handled. Return a MotionEvent action code if it was handled. + */ + public int onTouchEvent(final MotionEvent event) { + int status = -2; + final int action = event.getAction(); + + final boolean isEventInCenterCircle = isInCenterCircle(event.getX(), event.getY()); + if (action == MotionEvent.ACTION_DOWN) { + // check if center + if (isEventInCenterCircle) { + setState(CircularView.PRESSED_STATE_SET); + status = MotionEvent.ACTION_DOWN; + } + } else if (action == MotionEvent.ACTION_UP) { + if (isEventInCenterCircle) { + setState(StateSet.NOTHING); + status = MotionEvent.ACTION_UP; + } + } else if (action == MotionEvent.ACTION_MOVE) { + if (!isEventInCenterCircle) { + setState(StateSet.NOTHING); + status = MotionEvent.ACTION_MOVE; + } + } + return status; + } + + /** + * Schedule the object's parent to redraw again. + */ + protected void invalidate() { if(mAdapterDataSetObserver != null) { mAdapterDataSetObserver.onInvalidated(); } diff --git a/lib/src/main/java/com/sababado/circularview/Marker.java b/lib/src/main/java/com/sababado/circularview/Marker.java index 3b23ee6..1604cd1 100644 --- a/lib/src/main/java/com/sababado/circularview/Marker.java +++ b/lib/src/main/java/com/sababado/circularview/Marker.java @@ -105,7 +105,7 @@ public boolean isHighlighted() { */ public void setHighlighted(boolean highlighted) { this.isHighlighted = highlighted; - mAdapterDataSetObserver.onInvalidated(); + invalidate(); } boolean isShouldAnimateWhenHighlighted() { @@ -114,7 +114,7 @@ boolean isShouldAnimateWhenHighlighted() { void setShouldAnimateWhenHighlighted(boolean shouldAnimateWhenHighlighted) { this.shouldAnimateWhenHighlighted = shouldAnimateWhenHighlighted; - mAdapterDataSetObserver.onInvalidated(); + invalidate(); } /** diff --git a/sample/src/main/java/com/sababado/circularview/sample/MainActivity.java b/sample/src/main/java/com/sababado/circularview/sample/MainActivity.java index d2e52ad..21087de 100644 --- a/sample/src/main/java/com/sababado/circularview/sample/MainActivity.java +++ b/sample/src/main/java/com/sababado/circularview/sample/MainActivity.java @@ -3,8 +3,10 @@ import android.app.Activity; import android.os.Bundle; import android.view.View; +import android.widget.Toast; import com.sababado.circularview.CircularView; +import com.sababado.circularview.CircularViewObject; import com.sababado.circularview.SimpleCircularViewAdapter; import com.sababado.circularview.Marker; @@ -29,16 +31,21 @@ protected void onCreate(Bundle savedInstanceState) { // Combine the above line with the following so that the marker at it's position will animate at the start. circularView.setHighlightedDegree(circularView.BOTTOM); - circularView.setOnCenterCircleClickListener(new View.OnClickListener() { + circularView.setOnCircularViewObjectClickListener(new CircularView.OnClickListener() { @Override - public void onClick(View v) { - // Start animation from the bottom of the circle, going clockwise. - final float start = CircularView.BOTTOM; - final float end = start + 360f + (float) (Math.random() * 720f); - // animate the highlighted degree value but also make sure it isn't so fast that it's skipping marker animations. - final long duration = (long) (Marker.ANIMATION_DURATION * 2L * end / (270L - mAdapter.getCount())); - - circularView.animateHighlightedDegree(start, end, duration); + public void onClick(final CircularView view, final CircularViewObject circularViewObject) { + Toast.makeText(MainActivity.this, "Clicked "+circularViewObject.getId(), Toast.LENGTH_SHORT).show(); + + // Only animate the highlighted degree if the center circle is clicked. + if(circularView.getCenterCircle().getId() == circularViewObject.getId()) { + // Start animation from the bottom of the circle, going clockwise. + final float start = CircularView.BOTTOM; + final float end = start + 360f + (float) (Math.random() * 720f); + // animate the highlighted degree value but also make sure it isn't so fast that it's skipping marker animations. + final long duration = (long) (Marker.ANIMATION_DURATION * 2L * end / (270L - mAdapter.getCount())); + + circularView.animateHighlightedDegree(start, end, duration); + } } }); } @@ -51,7 +58,7 @@ public int getCount() { @Override public void setupMarker(final int position, final Marker marker) { - marker.setSrc(R.drawable.ic_launcher); + marker.setSrc(R.drawable.center_bg); marker.setFitToCircle(true); marker.setRadius(10 + 2 * position); }