Here is the custom class of GradientTextView provided by #koush (source is there on (github)
Now I got the class but how to call this class anyone can help since I am new bee on android
As far as I understood it can use custom attribute to but nyways how to call this class from MainActivity to get run. I dont know how to send AttributeSet parameters. it's too confusing
package android.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.LinearGradient;
import android.graphics.Shader.TileMode;
import android.text.BoringLayout;
import android.util.AttributeSet;
import android.widget.TextView;
public class GradientTextView extends TextView {
public GradientTextView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
int mStartColor = 0;
int mEndColor = 0;
float mAngle;
String mText;
BoringLayout mLayout;
public GradientTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
int[] ids = new int[attrs.getAttributeCount()];
for (int i = 0; i < attrs.getAttributeCount(); i++) {
ids[i] = attrs.getAttributeNameResource(i);
}
TypedArray a = context.obtainStyledAttributes(attrs, ids, defStyle, 0);
for (int i = 0; i < attrs.getAttributeCount(); i++) {
String attrName = attrs.getAttributeName(i);
if (attrName == null)
continue;
if (attrName.equals("startColor")) {
mStartColor = a.getColor(i, -1);
}
else if (attrName.equals("endColor")) {
mEndColor = a.getColor(i, -1);
}
else if (attrName.equals("angle")) {
mAngle = a.getFloat(i, 0);
}
}
}
public static void setGradient(TextView tv, float angle, int startColor, int endColor) {
tv.measure(tv.getLayoutParams().width, tv.getLayoutParams().height);
LinearGradient gradient = getGradient(tv.getMeasuredWidth(), tv.getMeasuredHeight(), angle, startColor, endColor);
tv.getPaint().setShader(gradient);
}
static LinearGradient getGradient(int measuredWidth, int measuredHeight, float angle, int startColor, int endColor) {
// calculate a vector for this angle
double rad = Math.toRadians(angle);
double oa = Math.tan(rad);
double x;
double y;
if (oa == Double.POSITIVE_INFINITY) {
y = 1;
x = 0;
}
else if (oa == Double.NEGATIVE_INFINITY) {
y = -1;
x = 0;
}
else {
y = oa;
if (rad > Math.PI)
x = -1;
else
x = 1;
}
// using the vector, calculate the start and end points from the center of the box
int mx = measuredWidth;
int my = measuredHeight;
int cx = mx / 2;
int cy = my / 2;
double n;
if (x == 0) {
n = (double)cy / y;
}
else if (y == 0) {
n = (double)cx / x;
}
else {
n = (double)cy / y;
double n2 = (double)cx / x;
if (Math.abs(n2) < Math.abs(n))
n = n2;
}
int sx = (int)(cx - n * x);
int sy = (int)(cy - n * y);
int ex = (int)(cx + n * x);
int ey = (int)(cy + n * y);
return new LinearGradient(sx, sy, ex, ey, startColor, endColor, TileMode.CLAMP);
}
protected void onDraw(android.graphics.Canvas canvas) {
if (mGradient == null) {
mGradient = getGradient(getMeasuredWidth(), getMeasuredHeight(), mAngle, mStartColor, mEndColor);
getPaint().setShader(mGradient);
}
super.onDraw(canvas);
}
public int getStartColor() {
return mStartColor;
}
public void setStartColor(int startColor) {
mStartColor = startColor;
invalidate();
}
public int getEndColor() {
return mEndColor;
}
public void setEndColor(int endColor) {
mEndColor = endColor;
invalidate();
}
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mGradient = null;
}
LinearGradient mGradient;
}
This custom class are too confusing but they are used for tweaking like outline, gradients, and etc I am very keen to understand the flow
you can use this "View Element" by instanciating/using a view object:
TextView myView = new TextView (this);
myView.setText("Test");
GradientTextView.setGradient(myView, 90, Color.BLACK, Color.WHITE);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,
Layoutparams.WRAP_CONTENT);
myLayout.addView(myView, params);
You can even use this object using it your layouts XML file.
Related
In one of my apps I have created a circular view with multiple colors,In which I want to set click listener on each color arch
Below is the image and code for drawing that view
Custom view class code
public class CircularStatusView extends View {
private static final float DEFAULT_PORTION_WIDTH = 10;
private static final int DEFAULT_PORTION_SPACING = 5;
private static final int DEFAULT_COLOR = Color.parseColor("#D81B60");
private static final float DEFAULT_PORTIONS_COUNT = 1;
private static final float START_DEGREE =-90;
private float radius;
private float portionWidth = DEFAULT_PORTION_WIDTH;
private int portionSpacing = DEFAULT_PORTION_SPACING;
private int portionColor = DEFAULT_COLOR;
private float portionsCount = DEFAULT_PORTIONS_COUNT;
private RectF mBorderRect = new RectF();
private Paint paint;
private SparseIntArray portionToUpdateMap = new SparseIntArray();
private Context context;
public CircularStatusView(Context context) {
super(context);
init(context, null, -1);
}
private void init(Context context, AttributeSet attrs, int defStyle) {
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircularStatusView, defStyle, 0);
if (a != null) {
portionColor = a.getColor(R.styleable.CircularStatusView_portion_color, DEFAULT_COLOR);
portionWidth = a.getDimensionPixelSize(R.styleable.CircularStatusView_portion_width, (int) DEFAULT_PORTION_WIDTH);
portionSpacing = a.getDimensionPixelSize(R.styleable.CircularStatusView_portion_spacing, DEFAULT_PORTION_SPACING);
portionsCount = a.getInteger(R.styleable.CircularStatusView_portions_count, (int) DEFAULT_PORTIONS_COUNT);
a.recycle();
}
paint = getPaint();
}
public CircularStatusView(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
init(context, attrs, -1);
}
public CircularStatusView(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs, defStyleAttr);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mBorderRect.set(calculateBounds());
radius = Math.min((mBorderRect.height() - portionWidth) / 2.0f, (mBorderRect.width() - portionWidth) / 2.0f);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
float radius = this.radius;
float center_x = mBorderRect.centerX();
float center_y = mBorderRect.centerY();
final RectF oval = getOval(radius, center_x, center_y);
float degree = 360 / portionsCount;
float percent = 100 / portionsCount;
for (int i = 0; i < portionsCount; i++) {
paint.setColor(getPaintColorForIndex(i));
float startAngle = START_DEGREE + (degree * i);
canvas.drawArc(oval, (getSpacing() / 2) + startAngle, getProgressAngle(percent) - getSpacing(), false, paint);
}
}
private int getPaintColorForIndex(int i) {
if (portionToUpdateMap.indexOfKey(i) >= 0) { //if key is exists
return portionToUpdateMap.get(i);
} else {
return portionColor;
}
}
#NonNull
private RectF getOval(float radius, float center_x, float center_y) {
final RectF oval = new RectF();
oval.set(center_x - radius,
center_y - radius,
center_x + radius,
center_y + radius);
return oval;
}
#NonNull
private Paint getPaint() {
Paint paint = new Paint();
paint.setColor(portionColor);
paint.setStyle(Paint.Style.STROKE);
paint.setAntiAlias(true);
paint.setStrokeWidth(portionWidth);
paint.setStrokeCap(Paint.Cap.BUTT);
return paint;
}
private int getSpacing() {
return portionsCount == 1 ? 0 : portionSpacing;
}
private RectF calculateBounds() {
int availableWidth = getWidth() - getPaddingLeft() - getPaddingRight();
int availableHeight = getHeight() - getPaddingTop() - getPaddingBottom();
int sideLength = Math.min(availableWidth, availableHeight);
float left = getPaddingLeft() + (availableWidth - sideLength) / 2f;
float top = getPaddingTop() + (availableHeight - sideLength) / 2f;
return new RectF(left, top, left + sideLength, top + sideLength);
}
private float getProgressAngle(float percent) {
return percent / (float) 100 * 360;
}
public void setPortionsCount(int portionsCount) {
this.portionsCount = (float) portionsCount;
}
public void setPortionSpacing(int spacing) {
portionSpacing = spacing;
}
public void setPortionWidth(float portionWidth) {
this.portionWidth = portionWidth;
}
public void setCustomPaint(Paint paint) {
this.paint = paint;
}
public void setPortionsColor(int color) {
this.portionColor = color;
portionToUpdateMap.clear();
invalidate();
}
public void setPortionColorForIndex(int index, int color) {
if (index > portionsCount - 1) {
throw new IllegalArgumentException("Index is Bigger than the count!");
} else {
Log.d("3llomi", "adding index to map " + index);
portionToUpdateMap.put(index, color);
invalidate();
}
}
}
and in my activity class
CircularStatusView circularStatusView = findViewById(R.id.circular_status_view);
circularStatusView.setPortionsCount(6);
for (int i=0; i<AppConstants.outerCircleColors.length; i++){
circularStatusView.setPortionColorForIndex(i,Color.parseColor(AppConstants.outerCircleColors[i]));
How I can set click listener on each color arch in this view? Can someone help me out in this?
You can get the pixel from the CircularStatusView, By using OnTouchListener:
CircularStatusView view = ((CircularStatusView)v);
Bitmap bitmap = ((BitmapDrawable)view.getDrawable()).getBitmap();
int pixel = bitmap.getPixel(x,y);
You can just compare the pixel to a different color. Like...
if(pixel == Color.RED){
//It's Red Color
}
You can create an interface listener for onTouch events. Check the onTouch co-ordinates. Depending on their position you can send back the touched part index to the interface listener.
Dummy code:
public class CircularStatusView extends View {
private StatusViewTouchListener listener;
...
..
.
public void setOnClickListener(StatusViewTouchListener listener) {
this.listener = listener;
}
public interface StatusViewTouchListener {
public void onStatusViewTouch(int index);
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
int indexOfTouchedColor;
// Check the touch points and determine in which color part it exists.
listener.onStatusViewTouch(indexOfTouchedColor);
return true;
}
}
Implement the listener where where you are using the view and set it to the View.
public class yourActivity extends Activity implements StatusViewTouchListener {
...
..
.
CircularStatusView circularStatusView = findViewById(R.id.circular_status_view);
circularStatusView.setPortionsCount(6);
for (int i=0; i<AppConstants.outerCircleColors.length; i++){
circularStatusView.setPortionColorForIndex(i,Color.parseColor(AppConstants.outerCircleColors[i]));
circularStatusView.setOnClickListener(this);
...
..
#Override
public void onStatusViewTouch(int index) {
// Perform your action based on the index of the color
}
}
i have got some problem with my own progressbar.
When i click on dot they catch me.
I try do it something like that:
here is code:
package test.pionas.myapplication;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.os.Build;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
public class PioArcCircle extends View {
private static final String TAG = PioArc.class.getSimpleName();
private static int INVALID_PROGRESS_VALUE = -1;
private float mThickness = 50f; // thickness of line
private int mRotate = 0; // rotate circle in degrees
private Paint mCircleBgPaint;
private int mCircleEndAngle = 270; // end arc
private int mCircleStartAngle = 0; // start arc
private int mCircleSweepAngle = 0; // actualy arc
private RectF mCircleOuterBounds;
private int mCircleBgColor = Color.RED; // color of circle
private Paint mCirclePaint; // progressbar
private int mCircleColor = Color.BLUE; // color of progressbar
private Paint mEraserPaint;
private RectF mCircleInnerBounds;
private int mEraserColor = Color.YELLOW; // background color of circle
private boolean mEraserInnerBackground = false; // eraser background inner circle
private Bitmap mBitmap;
private Canvas mCanvas;
private float mMinValue = 0; // min progressbar value
private float mMaxValue = 100; // max progressbar value
private float mProgressSweep = 0; // start progressbar value
private boolean mEnabled; // draw dot
private float mDotSize; // dot size
private Paint mCircleThumbPaint;
private float mTranslateX; // center circle (axis X)
private float mTranslateY; // center circle (axis Y)
private boolean mTouchInside; // touch inside circle can change position on progress
private float mTouchIgnoreRadius;
private int mArcRadius;
private int mThumbXPos;
private int mThumbYPos;
private OnPioArcCircleChangeListener mOnPioArcCircleChangeListener;
public PioArcCircle(Context context) {
super(context);
initDefaultValue(context, 0, null);
}
public PioArcCircle(Context context, AttributeSet attrs) {
super(context, attrs);
initDefaultValue(context, 0, attrs);
}
public PioArcCircle(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initDefaultValue(context, defStyleAttr, attrs);
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public PioArcCircle(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
initDefaultValue(context, defStyleAttr, attrs);
}
private void initDefaultValue(Context context, int defStyleAttr, AttributeSet attrs) {
if (attrs != null) {
TypedArray typedArray = context.getTheme().obtainStyledAttributes(
attrs,
R.styleable.PioArcCircle,
defStyleAttr, 0);
this.mThickness = typedArray.getFloat(R.styleable.PioArcCircle_thickness1, this.mThickness);
this.mRotate = typedArray.getInt(R.styleable.PioArcCircle_rotate, this.mRotate);
this.mCircleSweepAngle = typedArray.getInt(R.styleable.PioArcCircle_circleSweepAngle, this.mCircleSweepAngle);
this.mCircleEndAngle = typedArray.getInt(R.styleable.PioArcCircle_circleEndAngle, this.mCircleEndAngle);
this.mCircleStartAngle = typedArray.getInt(R.styleable.PioArcCircle_circleStartAngle, this.mCircleStartAngle);
this.mCircleBgColor = typedArray.getInt(R.styleable.PioArcCircle_circleBgColor, this.mCircleBgColor);
this.mEraserColor = typedArray.getInt(R.styleable.PioArcCircle_eraserColor, this.mEraserColor);
this.mEraserInnerBackground = typedArray.getBoolean(R.styleable.PioArcCircle_eraserInnerBackground, this.mEraserInnerBackground);
this.mMinValue = typedArray.getFloat(R.styleable.PioArcCircle_minValue, this.mMinValue);
this.mMaxValue = typedArray.getFloat(R.styleable.PioArcCircle_maxValue, this.mMaxValue);
this.mEnabled = typedArray.getBoolean(R.styleable.PioArcCircle_enable, this.mEnabled);
this.mDotSize = typedArray.getFloat(R.styleable.PioArcCircle_dotSize, this.mDotSize);
this.mTouchInside = typedArray.getBoolean(R.styleable.PioArcCircle_touchInside, this.mTouchInside);
this.mCircleColor = typedArray.getInt(R.styleable.PioArcCircle_circleBgColor, this.mCircleColor);
}
mCircleBgPaint = new Paint();
mCircleBgPaint.setAntiAlias(true);
mCircleBgPaint.setColor(mCircleBgColor);
mCirclePaint = new Paint();
mCirclePaint.setAntiAlias(true);
mCirclePaint.setColor(mCircleColor);
mEraserPaint = new Paint();
mEraserPaint.setAntiAlias(true);
mEraserPaint.setColor(mEraserColor);
if (mEraserInnerBackground) {
mEraserPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
}
mCircleThumbPaint = new Paint();
mCircleThumbPaint.setAntiAlias(true);
mCircleThumbPaint.setColor(Color.CYAN);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
if (w != oldw || h != oldh) {
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mBitmap.eraseColor(Color.TRANSPARENT);
mCanvas = new Canvas(mBitmap);
}
super.onSizeChanged(w, h, oldw, oldh);
updateBounds();
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
int min = Math.min(widthMeasureSpec, heightMeasureSpec);
this.setMeasuredDimension(parentWidth, parentHeight);
this.setTouchInSide(this.mTouchInside);
super.onMeasure(min, min);
}
#Override
protected void onDraw(Canvas canvas) {
mCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
mCanvas.drawArc(mCircleOuterBounds, (mCircleStartAngle + mRotate), (mCircleEndAngle - mCircleStartAngle), true, mCircleBgPaint);
if (mCircleSweepAngle - mRotate > 0f) {
mCanvas.drawArc(mCircleOuterBounds, (mCircleStartAngle + mRotate), (mCircleSweepAngle - mRotate), true, mCirclePaint);
}
mCanvas.drawOval(mCircleInnerBounds, mEraserPaint);
if (mEnabled) {
mThumbXPos = (int) (mTranslateX + (mArcRadius * Math.cos(Math.toRadians((double) this.mCircleSweepAngle))));
mThumbYPos = (int) (mTranslateY + (mArcRadius * Math.sin(Math.toRadians((double) this.mCircleSweepAngle))));
mCanvas.drawCircle(mThumbXPos, mThumbYPos, mThickness, mCircleThumbPaint);
}
canvas.drawBitmap(mBitmap, 0, 0, null);
}
private void updateBounds() {
if (this.getPaddingLeft() < (mThickness / 2)) {
this.setPadding((int) (mThickness / 2), this.getPaddingTop(), this.getPaddingRight(), this.getPaddingBottom());
}
mCircleOuterBounds = new RectF(0 + this.getPaddingLeft(), 0 + this.getPaddingLeft(), getWidth() - this.getPaddingLeft(), getHeight() - this.getPaddingLeft());
mCircleInnerBounds = new RectF(
mCircleOuterBounds.left + mThickness,
mCircleOuterBounds.top + mThickness,
mCircleOuterBounds.right - mThickness,
mCircleOuterBounds.bottom - mThickness);
this.mTranslateX = mCircleOuterBounds.centerX();
this.mTranslateY = mCircleOuterBounds.centerY();
this.mArcRadius = (int) (mTranslateX - this.getPaddingLeft() - (mThickness / 2));
invalidate();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (this.mEnabled) {
this.getParent().requestDisallowInterceptTouchEvent(true);
switch (event.getAction()) {
case 0:
this.onStartTrackingTouch();
this.updateOnTouch(event);
break;
case 1:
this.onStopTrackingTouch();
this.setPressed(false);
this.getParent().requestDisallowInterceptTouchEvent(false);
break;
case 2:
this.updateOnTouch(event);
break;
case 3:
this.onStopTrackingTouch();
this.setPressed(false);
this.getParent().requestDisallowInterceptTouchEvent(false);
}
return true;
} else {
return false;
}
}
public void setTouchInSide(boolean isEnabled) {
int thumbHalfheight = (int) (mThickness / 2);
int thumbHalfWidth = (int) (mThickness / 2);
this.mTouchInside = isEnabled;
if (this.mTouchInside) {
this.mTouchIgnoreRadius = (float) this.mArcRadius / 4.0F;
} else {
this.mTouchIgnoreRadius = (float) (this.mArcRadius - Math.min(thumbHalfWidth, thumbHalfheight));
}
}
private void updateOnTouch(MotionEvent event) {
boolean ignoreTouch = this.ignoreTouch(event.getX(), event.getY());
if (!ignoreTouch) {
this.setPressed(true);
this.mProgressSweep = (float) this.getTouchDegrees(event.getX(), event.getY());
this.updateProgress((int) this.mProgressSweep);
}
}
private double getTouchDegrees(float xPos, float yPos) {
double angle = (int) (Math.atan2(yPos - mTranslateY, xPos - mTranslateX) * 180 / Math.PI);
if (angle < 0) {
angle += 360;
}
float x = xPos - this.mTranslateX;
float y = yPos - this.mTranslateY;
angle = Math.toDegrees(Math.atan2((double) y, (double) x) + 1.5707963267948966D - Math.toRadians((double) this.mRotate));
if (angle < 0.0D) {
angle += 360.0D;
}
angle -= (double) this.mCircleStartAngle;
return angle;
}
private boolean ignoreTouch(float xPos, float yPos) {
boolean ignore = false;
double touchRadius = Math.sqrt(Math.pow(xPos - this.mTranslateX, 2) + Math.pow(yPos - this.mTranslateY, 2));
if (this.mTouchInside && touchRadius > this.mArcRadius) {
ignore = true;
} else {
if ((touchRadius > (this.mArcRadius + (this.mThickness / 2))) ||
(touchRadius < (this.mArcRadius - (this.mThickness / 2)))) {
ignore = true;
}
}
return ignore;
}
private void onStartTrackingTouch() {
if (this.mOnPioArcCircleChangeListener != null) {
this.mOnPioArcCircleChangeListener.onStartTrackingTouch(this);
}
}
private void onStopTrackingTouch() {
if (this.mOnPioArcCircleChangeListener != null) {
this.mOnPioArcCircleChangeListener.onStopTrackingTouch(this);
}
}
private void updateProgress(int progress) {
if (progress != INVALID_PROGRESS_VALUE) {
if (this.mOnPioArcCircleChangeListener != null) {
this.mOnPioArcCircleChangeListener.onProgressChanged(this);
}
mCircleSweepAngle = progress;
this.invalidate();
}
}
public OnPioArcCircleChangeListener getmOnPioArcCircleChangeListener() {
return mOnPioArcCircleChangeListener;
}
public void setmOnPioArcCircleChangeListener(OnPioArcCircleChangeListener mOnPioArcCircleChangeListener) {
this.mOnPioArcCircleChangeListener = mOnPioArcCircleChangeListener;
}
public interface OnPioArcCircleChangeListener {
void onProgressChanged(PioArcCircle var1);
void onStartTrackingTouch(PioArcCircle var1);
void onStopTrackingTouch(PioArcCircle var1);
}
}
activity_main.xml:
<com.test.myapplication.PioArcCircle
android:layout_width="200dp"
android:layout_height="200dp"
android:padding="#dimen/activity_vertical_margin"
android:progressDrawable="#drawable/circular_progress_bar"
pioarccircle:circleColor="#color/colorAccent"
pioarccircle:enable="true"
pioarccircle:minValue="50.0"
pioarccircle:rotate="135"
pioarccircle:thickness1="100" />
First problem:
How i can create a few colors of progress?
Thanks for help.
I am using a custom layout to display a varied number of buttons and intercept their clicks. Here is the source code for the custom layout:
import android.content.Context;
import android.content.res.TypedArray;
import android.database.DataSetObserver;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Adapter;
import android.widget.AdapterView;
public class FlowLayout extends AdapterView<Adapter> {
public static final int HORIZONTAL = 0;
public static final int VERTICAL = 1;
private static final int INVALID_INDEX = -1;
private static final int TOUCH_STATE_RESTING = 0;
private static final int TOUCH_STATE_CLICK = 1;
private int mTouchState = TOUCH_STATE_RESTING;
private Rect mRect;
private Runnable mLongPressRunnable;
private int mTouchStartX;
private int mTouchStartY;
private int horizontalSpacing = 0;
private int verticalSpacing = 0;
private int orientation = 0;
private boolean debugDraw = false;
private Adapter mAdapter;
private final AdapterObserver mObserver = new AdapterObserver();
public FlowLayout(Context context) {
super(context);
this.readStyleParameters(context, null);
}
public FlowLayout(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
this.readStyleParameters(context, attributeSet);
}
public FlowLayout(Context context, AttributeSet attributeSet, int defStyle) {
super(context, attributeSet, defStyle);
this.readStyleParameters(context, attributeSet);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int sizeWidth = MeasureSpec.getSize(widthMeasureSpec) - this.getPaddingRight() - this.getPaddingLeft();
int sizeHeight = MeasureSpec.getSize(heightMeasureSpec) - this.getPaddingRight() - this.getPaddingLeft();
int modeWidth = MeasureSpec.getMode(widthMeasureSpec);
int modeHeight = MeasureSpec.getMode(heightMeasureSpec);
int size;
int mode;
if (orientation == HORIZONTAL) {
size = sizeWidth;
mode = modeWidth;
} else {
size = sizeHeight;
mode = modeHeight;
}
int lineThicknessWithSpacing = 0;
int lineThickness = 0;
int lineLengthWithSpacing = 0;
int lineLength;
int prevLinePosition = 0;
int controlMaxLength = 0;
int controlMaxThickness = 0;
final int count = getChildCount();
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child.getVisibility() == GONE) {
continue;
}
child.measure(
MeasureSpec.makeMeasureSpec(sizeWidth, modeWidth == MeasureSpec.EXACTLY ? MeasureSpec.AT_MOST : modeWidth),
MeasureSpec.makeMeasureSpec(sizeHeight, modeHeight == MeasureSpec.EXACTLY ? MeasureSpec.AT_MOST : modeHeight)
);
LayoutParams lp = (LayoutParams) child.getLayoutParams();
int hSpacing = this.getHorizontalSpacing(lp);
int vSpacing = this.getVerticalSpacing(lp);
int childWidth = child.getMeasuredWidth();
int childHeight = child.getMeasuredHeight();
int childLength;
int childThickness;
int spacingLength;
int spacingThickness;
if (orientation == HORIZONTAL) {
childLength = childWidth;
childThickness = childHeight;
spacingLength = hSpacing;
spacingThickness = vSpacing;
} else {
childLength = childHeight;
childThickness = childWidth;
spacingLength = vSpacing;
spacingThickness = hSpacing;
}
lineLength = lineLengthWithSpacing + childLength;
lineLengthWithSpacing = lineLength + spacingLength;
boolean newLine = lp.newLine || (mode != MeasureSpec.UNSPECIFIED && lineLength > size);
if (newLine) {
prevLinePosition = prevLinePosition + lineThicknessWithSpacing;
lineThickness = childThickness;
lineLength = childLength;
lineThicknessWithSpacing = childThickness + spacingThickness;
lineLengthWithSpacing = lineLength + spacingLength;
}
lineThicknessWithSpacing = Math.max(lineThicknessWithSpacing, childThickness + spacingThickness);
lineThickness = Math.max(lineThickness, childThickness);
int posX;
int posY;
if (orientation == HORIZONTAL) {
posX = getPaddingLeft() + lineLength - childLength;
posY = getPaddingTop() + prevLinePosition;
} else {
posX = getPaddingLeft() + prevLinePosition;
posY = getPaddingTop() + lineLength - childHeight;
}
lp.setPosition(posX, posY);
controlMaxLength = Math.max(controlMaxLength, lineLength);
controlMaxThickness = prevLinePosition + lineThickness;
}
if (orientation == HORIZONTAL) {
this.setMeasuredDimension(resolveSize(controlMaxLength, widthMeasureSpec), resolveSize(controlMaxThickness, heightMeasureSpec));
} else {
this.setMeasuredDimension(resolveSize(controlMaxThickness, widthMeasureSpec), resolveSize(controlMaxLength, heightMeasureSpec));
}
}
private int getVerticalSpacing(LayoutParams lp) {
int vSpacing;
if (lp.verticalSpacingSpecified()) {
vSpacing = lp.verticalSpacing;
} else {
vSpacing = this.verticalSpacing;
}
return vSpacing;
}
private int getHorizontalSpacing(LayoutParams lp) {
int hSpacing;
if (lp.horizontalSpacingSpecified()) {
hSpacing = lp.horizontalSpacing;
} else {
hSpacing = this.horizontalSpacing;
}
return hSpacing;
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
final int count = getChildCount();
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
LayoutParams lp = (LayoutParams) child.getLayoutParams();
child.layout(lp.x, lp.y, lp.x + child.getMeasuredWidth(), lp.y + child.getMeasuredHeight());
}
}
#Override
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
boolean more = super.drawChild(canvas, child, drawingTime);
this.drawDebugInfo(canvas, child);
return more;
}
#Override
protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
return p instanceof LayoutParams;
}
#Override
protected LayoutParams generateDefaultLayoutParams() {
return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
}
#Override
public LayoutParams generateLayoutParams(AttributeSet attributeSet) {
return new LayoutParams(getContext(), attributeSet);
}
#Override
protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
return new LayoutParams(p);
}
private void readStyleParameters(Context context, AttributeSet attributeSet) {
TypedArray a = context.obtainStyledAttributes(attributeSet, R.styleable.FlowLayout);
try {
horizontalSpacing = a.getDimensionPixelSize(R.styleable.FlowLayout_horizontalSpacing, 0);
verticalSpacing = a.getDimensionPixelSize(R.styleable.FlowLayout_verticalSpacing, 0);
orientation = a.getInteger(R.styleable.FlowLayout_orientation, HORIZONTAL);
debugDraw = a.getBoolean(R.styleable.FlowLayout_debugDraw, false);
} finally {
a.recycle();
}
}
private void drawDebugInfo(Canvas canvas, View child) {
if (!debugDraw) {
return;
}
Paint childPaint = this.createPaint(0xffffff00);
Paint layoutPaint = this.createPaint(0xff00ff00);
Paint newLinePaint = this.createPaint(0xffff0000);
LayoutParams lp = (LayoutParams) child.getLayoutParams();
if (lp.horizontalSpacing > 0) {
float x = child.getRight();
float y = child.getTop() + child.getHeight() / 2.0f;
canvas.drawLine(x, y, x + lp.horizontalSpacing, y, childPaint);
canvas.drawLine(x + lp.horizontalSpacing - 4.0f, y - 4.0f, x + lp.horizontalSpacing, y, childPaint);
canvas.drawLine(x + lp.horizontalSpacing - 4.0f, y + 4.0f, x + lp.horizontalSpacing, y, childPaint);
} else if (this.horizontalSpacing > 0) {
float x = child.getRight();
float y = child.getTop() + child.getHeight() / 2.0f;
canvas.drawLine(x, y, x + this.horizontalSpacing, y, layoutPaint);
canvas.drawLine(x + this.horizontalSpacing - 4.0f, y - 4.0f, x + this.horizontalSpacing, y, layoutPaint);
canvas.drawLine(x + this.horizontalSpacing - 4.0f, y + 4.0f, x + this.horizontalSpacing, y, layoutPaint);
}
if (lp.verticalSpacing > 0) {
float x = child.getLeft() + child.getWidth() / 2.0f;
float y = child.getBottom();
canvas.drawLine(x, y, x, y + lp.verticalSpacing, childPaint);
canvas.drawLine(x - 4.0f, y + lp.verticalSpacing - 4.0f, x, y + lp.verticalSpacing, childPaint);
canvas.drawLine(x + 4.0f, y + lp.verticalSpacing - 4.0f, x, y + lp.verticalSpacing, childPaint);
} else if (this.verticalSpacing > 0) {
float x = child.getLeft() + child.getWidth() / 2.0f;
float y = child.getBottom();
canvas.drawLine(x, y, x, y + this.verticalSpacing, layoutPaint);
canvas.drawLine(x - 4.0f, y + this.verticalSpacing - 4.0f, x, y + this.verticalSpacing, layoutPaint);
canvas.drawLine(x + 4.0f, y + this.verticalSpacing - 4.0f, x, y + this.verticalSpacing, layoutPaint);
}
if (lp.newLine) {
if (orientation == HORIZONTAL) {
float x = child.getLeft();
float y = child.getTop() + child.getHeight() / 2.0f;
canvas.drawLine(x, y - 6.0f, x, y + 6.0f, newLinePaint);
} else {
float x = child.getLeft() + child.getWidth() / 2.0f;
float y = child.getTop();
canvas.drawLine(x - 6.0f, y, x + 6.0f, y, newLinePaint);
}
}
}
private Paint createPaint(int color) {
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(color);
paint.setStrokeWidth(2.0f);
return paint;
}
public static class LayoutParams extends ViewGroup.LayoutParams {
private static int NO_SPACING = -1;
private int x;
private int y;
private int horizontalSpacing = NO_SPACING;
private int verticalSpacing = NO_SPACING;
private boolean newLine = false;
public LayoutParams(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
this.readStyleParameters(context, attributeSet);
}
public LayoutParams(int width, int height) {
super(width, height);
}
public LayoutParams(ViewGroup.LayoutParams layoutParams) {
super(layoutParams);
}
public boolean horizontalSpacingSpecified() {
return horizontalSpacing != NO_SPACING;
}
public boolean verticalSpacingSpecified() {
return verticalSpacing != NO_SPACING;
}
public void setHorizontalSpacing(int hs) {
horizontalSpacing = hs;
}
public void setVerticalSpacing(int vs) {
verticalSpacing = vs;
}
public void setPosition(int x, int y) {
this.x = x;
this.y = y;
}
private void readStyleParameters(Context context, AttributeSet attributeSet) {
TypedArray a = context.obtainStyledAttributes(attributeSet, R.styleable.FlowLayout_LayoutParams);
try {
horizontalSpacing = a.getDimensionPixelSize(R.styleable.FlowLayout_LayoutParams_layout_horizontalSpacing, NO_SPACING);
verticalSpacing = a.getDimensionPixelSize(R.styleable.FlowLayout_LayoutParams_layout_verticalSpacing, NO_SPACING);
newLine = a.getBoolean(R.styleable.FlowLayout_LayoutParams_layout_newLine, false);
} finally {
a.recycle();
}
}
}
#Override
public Adapter getAdapter() {
return mAdapter;
}
#Override
public View getSelectedView() {
throw new UnsupportedOperationException("Not supported");
}
#Override
public void setAdapter(Adapter adapter) {
if (mAdapter != null) {
mAdapter.unregisterDataSetObserver(mObserver);
}
mAdapter = adapter;
mAdapter.registerDataSetObserver(mObserver);
refresh();
}
public void refresh() {
removeAllViewsInLayout();
for (int i = 0; i < mAdapter.getCount(); i++) {
final View view = mAdapter.getView(i, null, this);
ViewGroup.LayoutParams params = view.getLayoutParams();
if (params == null) {
params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
}
addViewInLayout(view, i, params, true);
}
postInvalidate();
requestLayout();
}
public class AdapterObserver extends DataSetObserver {
#Override
public void onChanged() {
refresh();
}
#Override
public void onInvalidated() {
}
}
#Override
public void setSelection(int position) {
throw new UnsupportedOperationException("Not supported");
}
// Touch detection
#Override
public boolean onTouchEvent(MotionEvent event) {
if (getChildCount() == 0) {
return false;
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
startTouch(event);
break;
case MotionEvent.ACTION_UP:
if (mTouchState == TOUCH_STATE_CLICK) {
clickChildAt((int)event.getX(), (int)event.getY());
}
endTouch();
break;
default:
endTouch();
break;
}
return true;
}
/**
* Sets and initializes all things that need to when we start a touch
* gesture.
*
* #param event The down event
*/
private void startTouch(final MotionEvent event) {
mTouchStartX = (int)event.getX();
mTouchStartY = (int)event.getY();
startLongPressCheck();
mTouchState = TOUCH_STATE_CLICK;
}
private void startLongPressCheck() {
if (mLongPressRunnable == null) {
mLongPressRunnable = new Runnable() {
public void run() {
if (mTouchState == TOUCH_STATE_CLICK) {
final int index = getContainingChildIndex(mTouchStartX, mTouchStartY);
if (index != INVALID_INDEX) { longClickChild(index); mTouchState = TOUCH_STATE_RESTING; }
}
}
};
}
postDelayed(mLongPressRunnable, 300); //ViewConfiguration.getLongPressTimeout()
}
private void longClickChild(final int index) {
final View itemView = getChildAt(index);
final int position = index;
final long id = mAdapter.getItemId(position);
final OnItemLongClickListener listener = getOnItemLongClickListener();
if (listener != null) { listener.onItemLongClick(this, itemView, position, id); }
}
private int getContainingChildIndex(final int x, final int y) {
if (mRect == null) { mRect = new Rect(); }
for (int index = 0; index < getChildCount(); index++) {
getChildAt(index).getHitRect(mRect);
if (mRect.contains(x, y)) { return index; }
}
return INVALID_INDEX;
}
private void endTouch() {
removeCallbacks(mLongPressRunnable);
mTouchState = TOUCH_STATE_RESTING;
}
private void clickChildAt(final int x, final int y) {
final int index = getContainingChildIndex(x, y);
if (index != INVALID_INDEX) {
final View itemView = getChildAt(index);
final int position = index;
final long id = mAdapter.getItemId(position);
performItemClick(itemView, position, id);
}
}
}
This code works on my test device which is a Google Nexus S with Android 4.1.2, meaning that the buttons are clickable. Yet I got reports that the buttons are unresponsive on other devices such as Android Casio C771 with Android version 2.3.3 and Verizon LG VS840 with Android 4.0.4.
Can you please tell me what could cause this discrepancy and how can I fix it?
Thank you
Things to look out for:
It is essential that the Views created for the adapter are enabled for click and touch action. After they are created:
View.setEnabled(true);
When you create the AdapterView and the BaseApapter, remember to both setOnItemClickListener and setOnItemLongClickListener if you want to handle long clicks, which it seems you do.
In the endTouch routine, you need to set mLongPressRunnable to null, so it will be created for the next touch (or lose the null check in startLongPressCheck and handle concurency issues another way).
The runnable created in startLongPressCheck needs to call endTouch when complete to reset everything to the right, nothing pending, state after the long press time period.
In the onTouchEvent switch statement, it is important to not call your endTouch routine, because this means that movement events may stop the click.
There is a suggestion (see Android onClick method doesn't work on a custom view) that if you don't call super.onTouchEvent(event) in your onTouchEvent it can cause problems. This would look something like:
#Override
public boolean onTouchEvent(MotionEvent event) {
if (getChildCount() == 0) {
return super.onTouchEvent(event);
}
boolean handled = false;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
startTouch(event);
handled = true;
break;
case MotionEvent.ACTION_UP:
if (mTouchState == TOUCH_STATE_CLICK) {
clickChildAt((int)event.getX(), (int)event.getY());
handled = true;
}
endTouch();
break;
default:
// Do not do anything dramatic here because the system
// may send different (eg. motion) information here which
// may lead to you losing valid clicks if you simply cancel
// the click in process.
break;
}
if (handled == false) handled = super.onTouchEvent(event);
return handled;
}
I wrote a Compass example that came out of an Android application tutorial book and wrote the custom view, methods, and such, but nothing is being drawn on the screen when the app runs.
Here is the class:
package com.example.compass;
import android.view.View;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.accessibility.AccessibilityEvent;
public class CompassView extends View {
private float bearing;
private Paint markerPaint;
private Paint textPaint;
private Paint circlePaint;
private String northString;
private String eastString;
private String southString;
private String westString;
private int textHeight;
public CompassView(Context context) {
super(context);
initCompassView();
}
public CompassView(Context context, AttributeSet attrs) {
super(context, attrs);
initCompassView();
}
public CompassView(Context context, AttributeSet ats, int defaultStyle) {
super(context, ats, defaultStyle);
initCompassView();
}
protected void initCompassView() {
setFocusable(true);
Resources r = this.getResources();
circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
circlePaint.setColor(r.getColor(R.color.background_color));
circlePaint.setStrokeWidth(1);
circlePaint.setStyle(Paint.Style.FILL_AND_STROKE);
northString = r.getString(R.string.cardinal_north);
eastString = r.getString(R.string.cardinal_east);
southString = r.getString(R.string.cardinal_south);
westString = r.getString(R.string.cardinal_west);
textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
textPaint.setColor(r.getColor(R.color.text_color));
textHeight = (int)textPaint.measureText("yY");
markerPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
markerPaint.setColor(r.getColor(R.color.marker_color));
}
#Override
protected void onDraw(Canvas canvas) {
int mMeasuredWidth = getMeasuredWidth();
int mMeasuredHeight = getMeasuredHeight();
int px = mMeasuredWidth/2;
int py = mMeasuredHeight/2;
int radius = Math.min(px, py);
canvas.drawCircle(px, py, radius, circlePaint);
canvas.save();
canvas.rotate(-bearing, px, py);
int textWidth = (int) textPaint.measureText("W");
int cardinalX = px-textWidth/2;
int cardinalY = py-radius+textHeight;
for (int i = 0; i < 24; i++) {
canvas.drawLine(px, py-radius, px, py-radius+10, markerPaint);
canvas.save();
canvas.translate(0, textWidth);
if (i%6 == 0) {
String dirString = "";
switch (i) {
case(0):{
dirString = northString;
int arrowY = 2*textHeight;
canvas.drawLine(px, arrowY, px-5, 3*textHeight, markerPaint);
canvas.drawLine(px, arrowY, px+5, 3*textHeight, markerPaint);
break;
}
case(6): dirString = eastString; break;
case(12): dirString = southString; break;
case(18): dirString = westString; break;
}
canvas.drawText(dirString, cardinalX, cardinalY, textPaint);
}
else if (i%3==0) {
String angle = String.valueOf(i*15);
float angleTextWidth = textPaint.measureText(angle);
int angleTextX = (int)(px-angleTextWidth/2);
int angleTextY = py-radius+textHeight;
canvas.drawText(angle, angleTextX, angleTextY, textPaint);
}
canvas.restore();
canvas.rotate(15, px, py);
}
canvas.restore();
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int measuredWidth = measure(widthMeasureSpec);
int measuredHeight = measure(heightMeasureSpec);
int d = Math.min(measuredWidth, measuredHeight);
setMeasuredDimension(d, d);
}
private int measure(int measureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getMode(measureSpec);
if (specMode == MeasureSpec.UNSPECIFIED) {
result = 200;
}
else {
result = specSize;
}
return result;
}
public void setBearing(float _bearing) {
bearing = _bearing;
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED);
}
public float getBearing() {
return bearing;
}
#SuppressWarnings("deprecation")
#Override
public boolean dispatchPopulateAccessibilityEvent(final AccessibilityEvent event) {
super.dispatchPopulateAccessibilityEvent(event);
if (isShown()) {
String bearingStr = String.valueOf(bearing);
if (bearingStr.length() > AccessibilityEvent.MAX_TEXT_LENGTH)
bearingStr = bearingStr.substring(0, AccessibilityEvent.MAX_TEXT_LENGTH);
event.getText().add(bearingStr);
return true;
}
else
return false;
}
}
I don't get any logcat errors; it does however display this (which might be relevant):
04-01 18:41:57.163: D/gralloc_goldfish(583): Emulator without GPU emulation detected.
However, after seeing this I added GPU emulation hardware to my emulator and selected the "Yes" option, but this message keeps showing up.
What could be the cause of nothing displaying on the screen? I can also post xml files if needed.
Figured out the cause: called getMode a second time instead of getSize... I feel dumb now.
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 11 years ago.
I have used to draw pie chart using canvas..
There are approximately 10 arcs in pie chart..i want to perform click event on each arc.
Is there any way to do this? or any other way?
This is my pie chart view..
MyView.java
package android.piechart;
import java.util.ArrayList;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
public class MyView extends View {
private Paint p;
private int startX;
private int startY;
private int radius;
private ArrayList<Integer> colors;
private ArrayList<Integer> values;
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
p = new Paint();
p.setColor(Color.BLUE);
p.setAntiAlias(true);
colors = new ArrayList<Integer>();
values = new ArrayList<Integer>();
startX = 320 / 4;
startY = 480 / 8;
radius = 320 / 2;
colors.add(Color.GREEN);
colors.add(Color.CYAN);
colors.add(Color.MAGENTA);
colors.add(Color.BLUE);
colors.add(Color.RED);
values.add(0);
values.add(1);
values.add(3);
values.add(0);
values.add(2);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.e("", "onDraw() is called...");
float offset = 0;
float sum = 0;
for (int a = 0; a < values.size(); a++) {
sum += values.get(a);
}
float angle = (float) (360 / sum);
Log.e("angle", "" + angle);
RectF rectF = new RectF();
rectF.set(getStartX(), getStartY(), getStartX() + getRadius(),
getStartY() + getRadius());
for (int i = 0; i < values.size(); i++) {
p.setColor(colors.get(i));
if (i == 0) {
canvas.drawArc(rectF, 0, values.get(i) * angle, true, p);
} else {
canvas.drawArc(rectF, offset, values.get(i) * angle, true, p);
}
offset += (values.get(i) * angle);
}
canvas.save();
}
public int getStartX() {
return startX;
}
public void setStartX(int startX) {
this.startX = startX;
}
public int getStartY() {
return startY;
}
public void setStartY(int startY) {
this.startY = startY;
}
public int getRadius() {
return radius;
}
public void setRadius(int radius) {
this.radius = radius;
}
public ArrayList<Integer> getColors() {
return colors;
}
public void setColors(ArrayList<Integer> colors) {
this.colors = colors;
}
public ArrayList<Integer> getValues() {
return values;
}
public void setValues(ArrayList<Integer> values) {
this.values = values;
}
}
Thanks in advance..
I solved my question myself...
MyView.java
public class MyView extends View {
private Paint p;
private int startX;
private int startY;
private int radius;
private ArrayList<Integer> colors;
private ArrayList<Float> values;
Bitmap bitmap;
Context mContext;
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
p = new Paint();
p.setAntiAlias(true);
colors = new ArrayList<Integer>();
values = new ArrayList<Float>();
startX = 320 / 4;
startY = 480 / 8;
radius = 320 / 2;
colors.add(Color.GREEN);
colors.add(Color.CYAN);
colors.add(Color.MAGENTA);
colors.add(Color.BLUE);
colors.add(Color.RED);
values.add(5f);
values.add(1f);
values.add(3f);
values.add(5f);
values.add(2f);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
bitmap = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(),
Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(bitmap);
Log.e("", "onDraw() is called...");
float offset = 0;
float sum = 0;
for (int a = 0; a < values.size(); a++) {
sum += values.get(a);
}
float angle = (float) (360 / sum);
Log.e("angle", "" + angle);
RectF rectF = new RectF();
rectF.set(getStartX(), getStartY(), getStartX() + getRadius(),
getStartY() + getRadius());
for (int i = 0; i < values.size(); i++) {
p.setColor(colors.get(i));
if (i == 0) {
canvas.drawArc(rectF, 0, values.get(i) * angle, true, p);
c.drawArc(rectF, 0, values.get(i) * angle, true, p);
} else {
canvas.drawArc(rectF, offset, values.get(i) * angle, true, p);
c.drawArc(rectF, offset, values.get(i) * angle, true, p);
}
offset += (values.get(i) * angle);
}
canvas.save();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
int color = bitmap.getPixel((int) event.getX(), (int) event.getY());
Log.e("", "" + color);
if (colors.contains(color)) {
Log.e("", "is matching");
if (color == Color.RED) {
Toast.makeText(mContext, "Is Red", Toast.LENGTH_SHORT).show();
}
if (color == Color.CYAN) {
Toast.makeText(mContext, "Is Cyan", Toast.LENGTH_SHORT).show();
}
if (color == Color.MAGENTA) {
Toast.makeText(mContext, "Is MAGENTA", Toast.LENGTH_SHORT)
.show();
}
if (color == Color.BLUE) {
Toast.makeText(mContext, "Is BLUE", Toast.LENGTH_SHORT).show();
}
if (color == Color.GREEN) {
Toast.makeText(mContext, "Is GREEN", Toast.LENGTH_SHORT).show();
}
}
return super.onTouchEvent(event);
}
public int getStartX() {
return startX;
}
public void setStartX(int startX) {
this.startX = startX;
}
public int getStartY() {
return startY;
}
public void setStartY(int startY) {
this.startY = startY;
}
public int getRadius() {
return radius;
}
public void setRadius(int radius) {
this.radius = radius;
}
public ArrayList<Integer> getColors() {
return colors;
}
public void setColors(ArrayList<Integer> colors) {
this.colors = colors;
}
public ArrayList<Float> getValues() {
return values;
}
public void setValues(ArrayList<Float> values) {
this.values = values;
}
}
I hope it's useful to others...
piechart
If you've used a Canvas, you probably have a reference to its underlying Bitmap. You could use Bitmap.getPixel(int x, int y) and test the color it returns to decide which section the click was in.
Otherwise, you have to do the calculation manually to figure out which wedge contains the x,y coordinates of your click.