Skip to content

Commit

Permalink
Adding click events to the markers
Browse files Browse the repository at this point in the history
  • Loading branch information
Robert Szabo committed Mar 27, 2014
1 parent f63daf4 commit 8f604a3
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 68 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
}
});
Expand Down
67 changes: 36 additions & 31 deletions lib/src/main/java/com/sababado/circularview/CircularView.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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<Marker> mMarkerList;
private CircularViewObject mCircle;
Expand Down Expand Up @@ -412,47 +411,42 @@ 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);
}

/**
* Set the click listener that will receive a callback when the center circle is clicked.
*
* @param l Listener to receive a callback.
*/
public void setOnCenterCircleClickListener(OnClickListener l) {
mOnCenterCircleClickListener = l;
public void setOnCircularViewObjectClickListener(OnClickListener l) {
mOnCircularViewObjectClickListener = l;
}

/**
Expand Down Expand Up @@ -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.
*
Expand All @@ -577,5 +583,4 @@ public static float convertPixelsToDp(float px, Context context) {
float dp = px / (metrics.densityDpi / 160f);
return dp;
}

}
71 changes: 49 additions & 22 deletions lib/src/main/java/com/sababado/circularview/CircularViewObject.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;

/**
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -201,9 +201,7 @@ public float getY() {
*/
public void setY(float y) {
this.y = y;
if (mAdapterDataSetObserver != null) {
mAdapterDataSetObserver.onInvalidated();
}
invalidate();
}

/**
Expand All @@ -222,9 +220,7 @@ public float getX() {
*/
public void setX(float x) {
this.x = x;
if (mAdapterDataSetObserver != null) {
mAdapterDataSetObserver.onInvalidated();
}
invalidate();
}

/**
Expand All @@ -243,9 +239,7 @@ public float getRadius() {
*/
public void setRadius(float radius) {
this.radius = radius;
if (mAdapterDataSetObserver != null) {
mAdapterDataSetObserver.onInvalidated();
}
invalidate();
}

/**
Expand All @@ -264,9 +258,7 @@ public float getRadiusPadding() {
*/
public void setRadiusPadding(float radiusPadding) {
this.radiusPadding = radiusPadding;
if (mAdapterDataSetObserver != null) {
mAdapterDataSetObserver.onInvalidated();
}
invalidate();
}

/**
Expand All @@ -285,9 +277,7 @@ public int getCenterBackgroundColor() {
*/
public void setCenterBackgroundColor(int centerBackgroundColor) {
paint.setColor(centerBackgroundColor);
if (mAdapterDataSetObserver != null) {
mAdapterDataSetObserver.onInvalidated();
}
invalidate();
}

CircularView.AdapterDataSetObserver getAdapterDataSetObserver() {
Expand All @@ -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();
}
Expand Down
4 changes: 2 additions & 2 deletions lib/src/main/java/com/sababado/circularview/Marker.java
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ public boolean isHighlighted() {
*/
public void setHighlighted(boolean highlighted) {
this.isHighlighted = highlighted;
mAdapterDataSetObserver.onInvalidated();
invalidate();
}

boolean isShouldAnimateWhenHighlighted() {
Expand All @@ -114,7 +114,7 @@ boolean isShouldAnimateWhenHighlighted() {

void setShouldAnimateWhenHighlighted(boolean shouldAnimateWhenHighlighted) {
this.shouldAnimateWhenHighlighted = shouldAnimateWhenHighlighted;
mAdapterDataSetObserver.onInvalidated();
invalidate();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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);
}
}
});
}
Expand All @@ -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);
}
Expand Down

0 comments on commit 8f604a3

Please sign in to comment.