I am using a custom view component to draw a pie ( a simple pie) . Each list Item has a pie with different values.
Now when I use it in a list view the pie values are shuffled and sometimes not updated.
My default pie value is 1.
When I first open my list
the first item shows proper value rest of the list items show only the defalt value 1 regardless of the actual value.
When I scroll the list the pie get value but that are shuffled . The first item has value of 5th , 2nd has value of 3rd and 3rd has value of something else.
Code of custom view:
public class PieRating extends View{
private float Rate;
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 PieRating(Context context, AttributeSet attrs) {
super(context, attrs);
Rate=1;
mContext = context;
p = new Paint();
p.setAntiAlias(true);
colors = new ArrayList<Integer>();
values = new ArrayList<Float>();
startX = 0;
startY = 0;
radius = 20;
colors.add(Color.GRAY);
colors.add(Color.TRANSPARENT);
values.add(Rate);
values.add(5 - Rate);
}
public void setRating(float Rate) {
this.Rate = Rate;
values.clear();
values.add(Rate);
values.add(5 - Rate);
}
public float getRating(){
return Rate;
}
#Override
protected void onDraw(Canvas canvas) {
float offset = 0;
float sum = 0;
for (int a = 0; a < values.size(); a++) {
sum += values.get(a);
}
float angle = (float) (360 / sum);
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, 270, values.get(i) * angle, true, p);
}
else {
canvas.drawArc(rectF, offset, values.get(i) * angle, true, p);
}
offset += (values.get(i) * angle + 270);
}
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<Float> getValues() {
return values;
}
public void setValues(ArrayList<Float> values) {
this.values = values;
}
}
And my list
public View getView(int position, View convertView, ViewGroup parent) {
PieRating pr =((PieRating)findViewById(R.id.score_pie_container));
try
{
float rating = Float.parseFloat(JSONHelper.getString(mRestaurants, "restaurants.restaurant[].opinion.general", new int[] { position }));
pr.setRating(rating);
}
catch (Exception e) {
// TODO: handle exception
}
}
Tried calling pr.invalidate once I set rating but no good.
silly mistake
((PieRating)convertView.findViewById(R.id.score_pie_container))
I missed the convertView part ..
Leaving answer just in case someone runs into similar issue
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 am working on a small simple game in which the hurdles coming out from top and there is an static ball which can only move on x-axis.When the hurdles coming out from top the user have to move the ball to avoid the collision.
I am placing 3 moving hurdles at a time.but my problem is they are coming out together i.e all three hurdles have the same y-axis values.I want it to come out one by one with some specific distance.
How can i achieve this.
Here is my GamePanel Class:
public class GamePanel extends SurfaceView implements Runnable {
private Thread thread = null;
private Ball ball;
private SurfaceHolder surfaceHolder;
private Paint paint;
private Canvas canvas;
volatile boolean playing = true;
private int hurdleCount = 3;
private Hurdles[] hurdles;
private int screenX, screenY;
private Rect ball_detectCollision;
public GamePanel(Context context, final int screenX, final int screenY) {
super(context);
ball = new Ball(context, screenX, screenY);
surfaceHolder = getHolder();
this.screenX = screenX;
this.screenY = screenY;
paint = new Paint();
canvas = new Canvas();
hurdles = new Hurdles[hurdleCount];
for (int i = 0; i < hurdleCount; i++) {
hurdles[i] = new Hurdles(context, screenX, screenY);
}
ball_detectCollision = new Rect(ball.getBall_x(), ball.getBall_y(), ball.getBitmap().getWidth(), ball.getBitmap().getHeight());
surfaceHolder.addCallback(new SurfaceHolder.Callback() {
#Override
public void surfaceCreated(SurfaceHolder holder) {
System.out.println("Surface Created");
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
System.out.println("Surface Changed");
thread = new Thread(GamePanel.this);
thread.start();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
System.out.println("Surface Destroyed");
}
});
}
private void draw() {
canvas = surfaceHolder.lockCanvas();
canvas.drawColor(Color.RED);
canvas.drawBitmap(ball.getBitmap(), updatedValue, ball.getBall_y(), paint);
ball.setBall_x(updatedValue);
ball_detectCollision.left = ball.getBall_x();
ball_detectCollision.top = screenY - ball.getBitmap().getHeight() - 260;
ball_detectCollision.right = ball.getBall_x() + ball.getBitmap().getWidth();
ball_detectCollision.bottom = screenY - ball.getBitmap().getHeight() - 260 + ball.getBitmap().getHeight();
for (int i = 0; i < hurdleCount; i++) {
canvas.drawBitmap(hurdles[i].getBitmap(), hurdles[i].getX(), hurdles[i].getY(), paint);
}
surfaceHolder.unlockCanvasAndPost(canvas);
}
#Override
public void run() {
while (playing) {
update();
draw();
control();
}
}
private void update() {
for (int i = 0; i < hurdleCount; i++) {
hurdles[i].update();
if (Rect.intersects(getBall_detectCollision(), hurdles[i].getDetectCollision())) {
System.out.println("Collision Detected");
playing = false;
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
showGameOverMessage();
}
});
}
}
}
public void pause() {
playing = false;
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
And this is my Hurdle Class
public class Hurdles {
private Bitmap bitmap;
private int x;
private int y;
private int speed = 20;
private int maxX;
private int minX;
private int maxY;
private int minY;
private Rect detectCollision;
public Hurdles(Context context, int screenX, int screenY) {
bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.hurdle);
maxX = screenX - bitmap.getWidth();
maxY = screenY;
minX = 0;
minY = 0;
Random generator = new Random();
detectCollision = new Rect(x, y, bitmap.getWidth(), bitmap.getHeight());
x = generator.nextInt(maxX);
y = minY;
}
public void update() {
y += speed;
if (y > maxY - getBitmap().getHeight()) {
Random generator = new Random();
y = minY;
x = generator.nextInt(maxX);
}
detectCollision.left = x;
detectCollision.right = x + bitmap.getWidth();
detectCollision.top = y;
detectCollision.bottom = y + bitmap.getHeight();
}
If you want to add delay/gap between hurdles, you can do it in your GamePanel constructor like :
public GamePanel(Context context, final int screenX, final int screenY) {
super(context);
int gapBetweenHurdles = 100;
int gap = 0;
for (int i = 0; i < hurdleCount; i++) {
//(screenY - gap) will move your hurdle above the screen
hurdles[i] = new Hurdles(context, screenX, screenY - gap);
//increment the gap
gap += gapBetweenHurdles;
}
......
}
So the gap between the hurdles is 100 pixels as i have written randomly. If you want specific gap, you can set gapBetweenHurdles to some percentage of the screen height.
EDIT:
You have to pass the initial X and Y position to the hurdle constructor and then in update method of the hurdle class increment the Y value and in Hurdle class, getY() should return Y.
Try changing the code like this:
handler.postDelayed(new Runnable() {
#Override
public void run() {
showGameOverMessage();
}
},timeOffsetInMillis);
If the gaps can be the same you can set timeOffsetInMillis = i * gapInMillis
I am using Dave Morrissey's sub sampling scale Image View to display a high resolution map image. I want to add location markers at predefined coordinates on the map such that even when the image is zoomed or panned around, the markers stay put at the specified coordinates. How can I do this?
Extend the SubsamplingScaleImageView and override its onDraw() method
public class MapView extends SubsamplingScaleImageView {
private PointF sPin;
ArrayList<MapPin> mapPins;
ArrayList<DrawnPin> drawnPins;
Context context;
String tag = getClass().getSimpleName();
public MapView(Context context) {
this(context, null);
this.context = context;
}
public MapView(Context context, AttributeSet attr) {
super(context, attr);
this.context = context;
initialise();
}
public void setPins(ArrayList<MapPin> mapPins)
{
this.mapPins = mapPins;
initialise();
invalidate();
}
public PointF getPin() {
return sPin;
}
private void initialise() {
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// Don't draw pin before image is ready so it doesn't move around during setup.
if (!isReady()) {
return;
}
drawnPins = new ArrayList<>();
Paint paint = new Paint();
paint.setAntiAlias(true);
float density = getResources().getDisplayMetrics().densityDpi;
for(int i=0;i<mapPins.size();i++)
{
MapPin mPin = mapPins.get(i);
Bitmap bmpPin = Utils.getBitmapFromAsset(context, mPin.getPinImgSrc());
float w = (density/420f) * bmpPin.getWidth();
float h = (density/420f) * bmpPin.getHeight();
bmpPin = Bitmap.createScaledBitmap(bmpPin, (int)w, (int)h, true);
PointF vPin = sourceToViewCoord(mPin.getPoint());
//in my case value of point are at center point of pin image, so we need to adjust it here
float vX = vPin.x - (bmpPin.getWidth()/2);
float vY = vPin.y - (bmpPin.getHeight()/2);
canvas.drawBitmap(bmpPin, vX, vY, paint);
//add added pin to an Array list to get touched pin
DrawnPin dPin = new DrawnPin();
dPin.setStartX(mPin.getX()-w/2);
dPin.setEndX(mPin.getX()+w/2);
dPin.setStartY(mPin.getY()-h/2);
dPin.setEndY(mPin.getY()+h/2);
dPin.setId(mPin.getId());
drawnPins.add(dPin);
}
}
public int getPinIdByPoint(PointF point)
{
for(int i=drawnPins.size()-1;i>=0;i--)
{
DrawnPin dPin = drawnPins.get(i);
if(point.x >= dPin.getStartX() && point.x<=dPin.getEndX())
{
if(point.y >= dPin.getStartY() && point.y<=dPin.getEndY())
{
return dPin.getId();
}
}
}
return -1; //negative no means no pin selected
}
class DrawnPin
{
float startX,startY,endX,endY;
int id;
public DrawnPin(float startX, float startY, float endX, float endY, int id)
{
this.startX = startX;
this.startY = startY;
this.endX = endX;
this.endY = endY;
this.id = id;
}
public DrawnPin()
{
//empty
}
public float getStartX()
{
return startX;
}
public void setStartX(float startX)
{
this.startX = startX;
}
public float getStartY()
{
return startY;
}
public void setStartY(float startY)
{
this.startY = startY;
}
public float getEndX()
{
return endX;
}
public void setEndX(float endX)
{
this.endX = endX;
}
public float getEndY()
{
return endY;
}
public void setEndY(float endY)
{
this.endY = endY;
}
public int getId()
{
return id;
}
public void setId(int id)
{
this.id = id;
}
}
I have a customview , inside it , i have one view slide up and down , when slide i draw fade background like this :
#Override
protected void dispatchDraw(Canvas canvas) {
canvas.drawARGB(alpha, 0, 0, 0);
super.dispatchDraw(canvas);
}
It work with my device android 4.2.2 but with android 4.4.2 or google nexus one android 2.3.7 ,it so bad.
2 images below show in my device 4.2.2(slide in and slide out):
http://imgur.com/p6i9gw8
http://imgur.com/9Sdzy7v
and 2 images below show in google nexus one android 2.3.7(slide in and slide out):
http://imgur.com/ZGKiRJi
http://imgur.com/Uf3vRdb
As you can see, in 2 image first, fade draw correct , and in other, it look bad.
Complete code for this view is :
public class SlideView extends ViewGroup {
private static final int MAXDURATIONSLIDE = 500;
protected View content;
private int childHeight;
private int childOffset;
private int childWidth;
private int alpha;
private Fillinger fillinger;
public ISlide getSlideChangeListener() {
return slideListener;
}
public void setSlideChangeListener(ISlide slideChangeListener) {
this.slideListener = slideChangeListener;
}
private ISlide slideListener;
public SlideView(Context context) {
super(context);
init(context, null);
}
private void init(Context context, AttributeSet attrs) {
if(attrs!=null){
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SlideView);
try {
int contentLayoutId = a.getResourceId(R.styleable.SlideView_slideView, 0);
DebugLog.d(contentLayoutId);
setContent(contentLayoutId);
} finally {
a.recycle();
}
}
fillinger = new Fillinger(context);
}
public SlideView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context,attrs);
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
final int width = r - l;
final int height = b - t;
DebugLog.d("width "+width+" height "+height);
childOffset = height;
content.layout(0, childOffset, childWidth, childOffset + childHeight);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = getDefaultSize(0, widthMeasureSpec);
int height = getDefaultSize(0, heightMeasureSpec);
measureChild(content, widthMeasureSpec, height);
childHeight = content.getMeasuredHeight();
childWidth = content.getMeasuredWidth();
DebugLog.d("childWidth "+childWidth+" childHeight "+childHeight);
setMeasuredDimension(width, height);
}
public void setContent(int resId) {
View view = LayoutInflater.from(getContext()).inflate(resId, this,false);
setContent(view);
}
public void setContent(View v) {
if (content != null)
removeView(content);
content = v;
addView(content);
}
private void moveViewByY(int diffY) {
childOffset += diffY;
alpha = (int) (Math.abs((getHeight()-childOffset)*255/(childHeight))*0.5f);
content.layout(0, childOffset, childWidth, childOffset + childHeight);
if(slideListener!=null){
slideListener.onSlide(childOffset,childHeight);
}
}
#Override
protected void dispatchDraw(Canvas canvas) {
canvas.drawARGB(alpha, 0, 0, 0);
super.dispatchDraw(canvas);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if(isIn()&&touchOutSide(event)){
toogle();
return true;
}
return false;
}
private boolean touchOutSide(MotionEvent event) {
final float x = event.getX();
final float y = event.getY();
if(x<content.getLeft()||x>content.getRight()||y<content.getTop()||y>content.getBottom()){
return true;
}
return false;
}
public void hide(){
if(isIn()){
fillinger.startScroll(content.getTop(),getHeight(),childHeight,MAXDURATIONSLIDE);
}
}
public void show(){
if(!isIn()){
fillinger.startScroll(content.getTop(),getHeight()-childHeight,childHeight,MAXDURATIONSLIDE);
}
}
public void toogle(){
fillinger.cancleAnimation();
if(isIn()){
hide();
}else{
show();
}
}
public boolean isIn(){
return content.getTop()<getHeight();
}
public class Fillinger implements Runnable {
private static final String tag = "Fillinger";
private Scroller mScroller;
private int lastY;
private boolean more;
private int currentY;
private int diffY;
public Fillinger(Context context) {
mScroller = new Scroller(context);
}
public void startScroll(float startY, float endY, float maxDistance, int maxDurationForFling) {
int duration = (int) Math.min(Math.abs((endY - startY)) / maxDistance * maxDurationForFling, maxDurationForFling);
lastY = (int) startY;
if(slideListener!=null){
slideListener.onStartSlide();
}
mScroller.startScroll(0, (int) startY, 0, -(int) (endY - startY), duration);
setDrawingCacheEnabled(true);
post(this);
}
public void cancleAnimation(){
removeCallbacks(this);
}
#Override
public void run() {
more = mScroller.computeScrollOffset();
currentY = mScroller.getCurrY();
diffY = lastY - currentY;
moveViewByY(diffY);
lastY = currentY;
if (more) {
post(this);
}else{
setDrawingCacheEnabled(false);
if(slideListener!=null){
slideListener.onSlideFinish(isIn());
}
}
}
}
}
What i missing?
Sorry for my bad english.
Thanks all.
Edit: finally , i must call invalidate in moveViewByY method like this
private void moveViewByY(int diffY) {
childOffset += diffY;
alpha = (int) (Math.abs((getHeight()-childOffset)*255/(childHeight))*0.5f);
content.layout(0, childOffset, childWidth, childOffset + childHeight);
invalidate();
if(slideListener!=null){
slideListener.onSlide(childOffset,childHeight);
}
}
I dont know why , may be invalidate , view tree redraw and old canvas cleared.
Expect best solution, thanks .
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.