How to increment arch length in custom view with OnClick? - android

I have a custom view(Circle) which is partly filled with arch(red color). Here is the picture https://gyazo.com/72e19cb97fd9f2adac2259c3855cf136.
I want to divide my custom view into sections, and when the button is clicked I draw an arch. 1 click 1/5 is covered with arch, 2nd click 2/5, etc...till 5.
How do I fill my view with red Arch when i press Increment button?(I don't understand the drawing part)
Here is what I have already tried - My CustomView class:
public class MySimpleView extends View {
private static final int PAINT_FLAGS = Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG;
private static final int STROKE_WIDTH = 40;
private static final int SECTIONS = 5;
private Paint basePaint, degreesPaint, centerPaint, rectPaint;
private RectF rect;
private int centerX, centerY, radius;
private int fullArchSliceLength;
private int colorArchLineLength;
public MySimpleView(Context context) {
super(context);
init();
}
public MySimpleView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public MySimpleView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
rectPaint = new Paint(PAINT_FLAGS);
rectPaint.setColor(ContextCompat.getColor(getContext(), R.color.white));
rectPaint.setStyle(Paint.Style.FILL);
centerPaint = new Paint(PAINT_FLAGS);
centerPaint.setColor(ContextCompat.getColor(getContext(), R.color.white));
centerPaint.setStyle(Paint.Style.FILL);
basePaint = new Paint(PAINT_FLAGS);
basePaint.setStyle(Paint.Style.STROKE);
basePaint.setStrokeWidth(STROKE_WIDTH);
basePaint.setColor(ContextCompat.getColor(getContext(), R.color.darkGrey));
degreesPaint = new Paint(PAINT_FLAGS);
degreesPaint.setStyle(Paint.Style.STROKE);
degreesPaint.setStrokeCap(Paint.Cap.ROUND);
degreesPaint.setStrokeJoin(Paint.Join.ROUND);
degreesPaint.setStrokeWidth(STROKE_WIDTH);
degreesPaint.setColor(Color.RED);
fullArchSliceLength = 360 / SECTIONS;
colorArchLineLength = fullArchSliceLength - 2;
}
public void swapColor() {
degreesPaint.setColor(degreesPaint.getColor() == Color.RED ? Color.GREEN :
Color.RED);
postInvalidate();
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (rect == null) {
centerX = getMeasuredWidth() / 2;
centerY = getMeasuredHeight() / 2;
radius = Math.min(centerX, centerY);
int startTop = STROKE_WIDTH / 2;
int startLeft = STROKE_WIDTH / 2;
int endBottom = 2 * radius - startTop;
int endRight = 2 * radius - startTop;
rect = new RectF(startTop, startLeft, endRight, endBottom);
}
canvas.drawRect(rect, rectPaint);
canvas.drawCircle(centerX, centerY, radius - STROKE_WIDTH / 2, basePaint);
// TODO: 2019-04-26 LOOK HERE
for (int i = 3; i < SECTIONS; i++) {
canvas.drawArc(rect, i * fullArchSliceLength,colorArchLineLength,
false, degreesPaint);
}
// TODO: 2019-04-26 LOOK HERE
// canvas.drawArc(rect, 0F, 90F, false, degreesPaint);
canvas.drawCircle(centerX, centerY, radius - STROKE_WIDTH, centerPaint);
}
}

public class MySimpleView extends View {
private static final int PAINT_FLAGS = Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG;
private static final int STROKE_WIDTH = 40;
private static final int SECTIONS = 5;
private Paint basePaint, degreesPaint, centerPaint, rectPaint;
private RectF rect;
private int centerX, centerY, radius;
private int fullArchSliceLength;
private int colorArchLineLength;
private int currentSections = 1;
public MySimpleView(Context context) {
super(context);
init();
}
public MySimpleView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public MySimpleView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
rectPaint = new Paint(PAINT_FLAGS);
rectPaint.setColor(ContextCompat.getColor(getContext(), R.color.white));
rectPaint.setStyle(Paint.Style.FILL);
centerPaint = new Paint(PAINT_FLAGS);
centerPaint.setColor(ContextCompat.getColor(getContext(), R.color.white));
centerPaint.setStyle(Paint.Style.FILL);
basePaint = new Paint(PAINT_FLAGS);
basePaint.setStyle(Paint.Style.STROKE);
basePaint.setStrokeWidth(STROKE_WIDTH);
basePaint.setColor(ContextCompat.getColor(getContext(), android.R.color.darker_gray));
degreesPaint = new Paint(PAINT_FLAGS);
degreesPaint.setStyle(Paint.Style.STROKE);
degreesPaint.setStrokeCap(Paint.Cap.ROUND);
degreesPaint.setStrokeJoin(Paint.Join.ROUND);
degreesPaint.setStrokeWidth(STROKE_WIDTH);
degreesPaint.setColor(Color.RED);
fullArchSliceLength = 360 / SECTIONS;
colorArchLineLength = fullArchSliceLength - 2;
}
//just a simple increment function
public void increment() {
if (currentSections < SECTIONS) {
currentSections++;
postInvalidate();
}
}
public void swapColor() {
degreesPaint.setColor(degreesPaint.getColor() == Color.RED ? Color.GREEN :
Color.RED);
postInvalidate();
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (rect == null) {
centerX = getMeasuredWidth() / 2;
centerY = getMeasuredHeight() / 2;
radius = Math.min(centerX, centerY);
int startTop = STROKE_WIDTH / 2;
int startLeft = STROKE_WIDTH / 2;
int endBottom = 2 * radius - startTop;
int endRight = 2 * radius - startTop;
rect = new RectF(startTop, startLeft, endRight, endBottom);
}
canvas.drawRect(rect, rectPaint);
canvas.drawCircle(centerX, centerY, radius - STROKE_WIDTH / 2, basePaint);
/*
startAngle is set to 270 so it will start at the top.
0 is right
90 bottom
180 left
270 top
*/
canvas.drawArc(rect, 270, currentSections * colorArchLineLength, false, degreesPaint);
canvas.drawCircle(centerX, centerY, radius - STROKE_WIDTH, centerPaint);
}
}
Basically your logic was a bit wrong. When calling drawArc the first parameter will be the startAngle of your line (meaning does the line start on top, left, right, bottom of the circle). I have written in comments what each degree corresponds to. The sweepAngle is how many degrees you are drawing (which you had already calculated correctly). Hope it works as you would expect it!

Related

how is possible to set imageview or icon in the canvas circle?

how is possible to set an image or icon in the canvas Circle? i have a custom canvas view that by move the camera on map, resize method will be activate and change the shape of the view and by stop the moving of map it will be like factory setting...happy english :-))))
public class CancvasCircle extends androidx.appcompat.widget.AppCompatImageView {
///main circle resize fields
public static final int MAIN_CIRCLE_PRE_RADIUS = 40;
public static final int MAIN_CIRCLE_POST_RADIUS = 43;
public static final String MAIN_CIRCLE_PRE_STROKE_COLOR = "#69DAE2";
//4CEAE3
public static final String MAIN_CIRCLE_POST_STROKE_COLOR = "#FBCC38";
///// line resize fields
public static final int LINE_HIEGHT_STOP = 45;
public static final int LINE_HIEGHT_START_PRE = 0;
public static final int LINE_HIEGHT_START_POST = 23;
public static final int SHADOW_CIRCLE_PRE_RADIUS = 15;
//circle paint fields
Paint strokeCircle;
Paint fillCircle;
Paint shadowCircle;
Paint line;
Paint dot;
//center
float centerX;
float centerY;
//main circle fields
private int radiusMain = MAIN_CIRCLE_PRE_RADIUS;
private String colorMain = MAIN_CIRCLE_PRE_STROKE_COLOR;
//line fields
private float lineStartY;
private float lineStopY;
//shadow circle fields
private int shadowRadius = SHADOW_CIRCLE_PRE_RADIUS;
public CancvasCircle(Context context) {
super(context);
init();
}
public CancvasCircle(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public CancvasCircle(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public void init() {
strokeCircle = new Paint();
strokeCircle.setAntiAlias(true);
strokeCircle.setAntiAlias(true);
strokeCircle.setStrokeWidth(10);
strokeCircle.setStyle(Paint.Style.STROKE);
fillCircle = new Paint();
fillCircle.setAntiAlias(true);
fillCircle.setColor(Color.parseColor("#BEC6CC"));
fillCircle.setStyle(Paint.Style.FILL);
shadowCircle = new Paint();
shadowCircle.setAntiAlias(true);
shadowCircle.setColor(Color.parseColor("#1f000000"));
shadowCircle.setStyle(Paint.Style.FILL);
line = new Paint();
line.setAntiAlias(true);
line.setColor(Color.parseColor("#000000"));
line.setStrokeWidth(4);
line.setStyle(Paint.Style.FILL);
dot = new Paint();
dot.setAntiAlias(true);
dot.setColor(Color.parseColor("#000000"));
dot.setStrokeWidth(4);
dot.setStyle(Paint.Style.FILL);
}
public void resizeStrokeCircleParams(Boolean resize) {
if (resize) {
this.radiusMain = MAIN_CIRCLE_POST_RADIUS;
this.colorMain = MAIN_CIRCLE_POST_STROKE_COLOR;
this.lineStartY = centerY - LINE_HIEGHT_START_POST;
this.lineStopY = LINE_HIEGHT_STOP + LINE_HIEGHT_START_POST - 10;
this.shadowRadius = LINE_HIEGHT_START_POST;
} else {
this.radiusMain = MAIN_CIRCLE_PRE_RADIUS;
this.colorMain = MAIN_CIRCLE_PRE_STROKE_COLOR;
this.lineStartY = centerY - LINE_HIEGHT_START_PRE;
this.lineStopY = LINE_HIEGHT_STOP;
this.shadowRadius = SHADOW_CIRCLE_PRE_RADIUS;
}
invalidate();
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
centerX = getWidth() / 2f;
centerY = getHeight() / 2f;
int radius = radiusMain;
float lineStopY = this.lineStopY;
float lineStartY = this.lineStartY;
int shadowRadius = this.shadowRadius;
strokeCircle.setColor(Color.parseColor(colorMain));
canvas.drawCircle(centerX, centerY - lineStopY - radius, radius, strokeCircle);
canvas.drawCircle(centerX, centerY - lineStopY - radius, radius, fillCircle);
canvas.drawCircle(centerX, centerY, shadowRadius, shadowCircle);
canvas.drawLine(centerX, lineStartY, centerX, centerY - lineStopY, line);
canvas.drawPoint(centerX,centerY,dot);
}
}
is it possible to flip two images like coin in it????
See example as custom View.
public class ViewCircle extends View{
final Bitmap bms; //source
final Bitmap bmm; //mask
final Paint paint;
public ViewCircle( Context context ){
super( context );
bms = BitmapFactory.decodeResource( getResources(), R.drawable.pr_0000 );
bmm = Bitmap.createBitmap( bms.getWidth(), bms.getHeight(), Bitmap.Config.ARGB_8888 );
Canvas canvas = new Canvas( bmm );
paint = new Paint( Paint.ANTI_ALIAS_FLAG );
canvas.drawCircle( bmm.getWidth()/2, bmm.getHeight()/2, Math.min(bmm.getWidth()/2,bmm.getHeight()/2), paint );
paint.setXfermode( new PorterDuffXfermode( PorterDuff.Mode.SRC_IN ) );
canvas.drawBitmap( bms, 0, 0, paint );
}
#Override
protected void onDraw( Canvas canvas ){
super.onDraw( canvas );
canvas.drawBitmap( bms, 0,0, null );
canvas.drawBitmap( bmm, bms.getWidth(),0, null );
}
}
i used this method to create a bitmap from XML layout and set it in my codes...
public Bitmap getMarkerBitmapFromView(#DrawableRes int resIdMain, #DrawableRes int resId) {
View customMarkerView = ((LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.custom_marker, null);
customMarkerView.findViewById(R.id.custom_marker_firstlayout);
if(resIdMain != 0){
customMarkerView.setBackgroundResource(resIdMain);
}
ImageView markerImageView = (ImageView) customMarkerView.findViewById(R.id.custom_marker_secondLayout);
if(resId != 0){
markerImageView.setImageResource(resId);
}
customMarkerView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
customMarkerView.layout(0, 0, customMarkerView.getMeasuredWidth(), customMarkerView.getMeasuredHeight());
customMarkerView.buildDrawingCache();
Bitmap returnedBitmap = Bitmap.createBitmap(customMarkerView.getMeasuredWidth(), customMarkerView.getMeasuredHeight(),
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(returnedBitmap);
canvas.drawColor(Color.WHITE, PorterDuff.Mode.SRC_IN);
Drawable drawable = customMarkerView.getBackground();
if (drawable != null)
drawable.draw(canvas);
customMarkerView.draw(canvas);
return returnedBitmap;
}
and set it in my canvas view in onDraw() and set it in the middle of my circle:
canvas.drawBitmap(getMarkerBitmapFromView(0,guildMarkerICON),convertDpToPixel(76,context),imageHieght,null);
because of drawing wrong in different devices i used this methods to change pixel and dp:
public static float convertPixelsToDp(float px,Context context){
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
float dp = px / (metrics.densityDpi / 160f);
return dp;
}
public static float convertDpToPixel(float dp,Context context){
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
float px = dp * (metrics.densityDpi/160f);
return px;
}
and XML layout that provide my bit map (that you can use image or any things you want in it) is (custom_marker.xml) :
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/custom_marker_firstlayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/center_marker_background">
<ImageView
android:id="#+id/custom_marker_secondLayout"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_gravity="center"
android:contentDescription="#null"
/>
</FrameLayout>
and use this method when you want to change the marker(like moving the map):
map.setOnCameraMoveStartedListener(new GoogleMap.OnCameraMoveStartedListener() {
#Override
public void onCameraMoveStarted(int i) {
canvasView.resizeStrokeCircleParams(true,guildMarkerICON);
}
});
map.setOnCameraIdleListener(new GoogleMap.OnCameraIdleListener() {
#Override
public void onCameraIdle() {
canvasView.resizeStrokeCircleParams(false,guildMarkerICON);
}
});
and finally here i s my custom canvas class that i used and i passed my custom icon to it by resize method and set it as i want...enjoy it:
public class CancvasCircle extends androidx.appcompat.widget.AppCompatImageView {
///main circle resize fields
public static final int MAIN_CIRCLE_PRE_RADIUS = 24;
public static final int MAIN_CIRCLE_POST_RADIUS = 26;
public static final String MAIN_CIRCLE_PRE_STROKE_COLOR = "#F44336";
public static final String MAIN_CIRCLE_POST_STROKE_COLOR = "#FFCC59";
//FFCC59
//FBCC38
///// line resize fields
public static final int LINE_HIEGHT_STOP = 24;
public static final int LINE_HIEGHT_START_PRE = 0;
public static final int LINE_HIEGHT_START_POST = 11;
public static final int SHADOW_CIRCLE_PRE_RADIUS = 14;
private final Context context;
/// image view fields
//circle paint fields
Paint strokeCircle;
Paint fillCircle;
Paint shadowCircle;
Paint line;
Paint dot;
Paint imagePaint;
//center
float centerX;
float centerY;
//main circle fields
private int radiusMain = MAIN_CIRCLE_PRE_RADIUS;
private String colorMain = MAIN_CIRCLE_PRE_STROKE_COLOR;
//line fieldsاذغ
private float lineStartY;
private float lineStopY;
//shadow circle fields
private int shadowRadius = SHADOW_CIRCLE_PRE_RADIUS;
private Bitmap canvasBitmap;
private int imageTopPadding;
private int guildMarkerICON
;
public CancvasCircle(Context context) {
super(context);
this.context = context;
init();
}
public CancvasCircle(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
this.context = context;
init();
}
public CancvasCircle(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.context = context;
init();
}
public void init() {
strokeCircle = new Paint();
strokeCircle.setAntiAlias(true);
strokeCircle.setAntiAlias(true);
strokeCircle.setStrokeWidth(12);
strokeCircle.setStyle(Paint.Style.STROKE);
fillCircle = new Paint();
fillCircle.setAntiAlias(true);
fillCircle.setColor(Color.parseColor("#af283232"));
fillCircle.setStyle(Paint.Style.FILL);
shadowCircle = new Paint();
shadowCircle.setAntiAlias(true);
shadowCircle.setColor(Color.parseColor("#1f000000"));
shadowCircle.setStyle(Paint.Style.FILL);
line = new Paint();
line.setAntiAlias(true);
line.setColor(Color.parseColor("#000000"));
line.setStrokeWidth(4);
line.setStyle(Paint.Style.FILL);
dot = new Paint();
dot.setAntiAlias(true);
dot.setColor(Color.parseColor("#000000"));
dot.setStrokeWidth(4);
dot.setStyle(Paint.Style.FILL);
}
public void resizeStrokeCircleParams(Boolean resize , int guildMarkerICON) {
this.guildMarkerICON = guildMarkerICON;
if (resize) {
this.radiusMain = (int) convertDpToPixel(MAIN_CIRCLE_POST_RADIUS,context);
this.colorMain = MAIN_CIRCLE_POST_STROKE_COLOR;
this.lineStartY = centerY -convertDpToPixel( LINE_HIEGHT_START_POST,context);
this.lineStopY =convertDpToPixel( LINE_HIEGHT_STOP,context) + convertDpToPixel(LINE_HIEGHT_START_POST,context) -8;
this.shadowRadius = (int) convertDpToPixel(LINE_HIEGHT_START_POST,context);
this.imageTopPadding = (int) convertDpToPixel(19,context);
} else {
this.radiusMain = (int) convertDpToPixel( MAIN_CIRCLE_PRE_RADIUS,context);
this.colorMain = MAIN_CIRCLE_PRE_STROKE_COLOR;
this.lineStartY = centerY - convertDpToPixel(LINE_HIEGHT_START_PRE,context);
this.lineStopY = convertDpToPixel(LINE_HIEGHT_STOP,context);
this.shadowRadius = (int) convertDpToPixel(SHADOW_CIRCLE_PRE_RADIUS,context);
this.imageTopPadding = (int) convertDpToPixel( 28,context);
}
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
centerX = getWidth() / 2f;
centerY = getHeight() / 2f;
int radius = radiusMain;
float lineStopY = this.lineStopY;
float lineStartY = this.lineStartY;
int shadowRadius = this.shadowRadius;
int imageHieght = this.imageTopPadding;
strokeCircle.setColor(Color.parseColor(colorMain));
// if map is moving (imageHieght == 41)
// if map is not moving (imageHieght == 56)
canvas.drawLine(centerX, lineStartY, centerX, centerY - lineStopY, line);
canvas.drawCircle(centerX, centerY - lineStopY - radius, radius, strokeCircle);
canvas.drawCircle(centerX, centerY - lineStopY - radius, radius, fillCircle);
canvas.drawCircle(centerX, centerY, shadowRadius, shadowCircle);
canvas.drawPoint(centerX,centerY,dot);
canvas.drawBitmap(getMarkerBitmapFromView(0,guildMarkerICON),convertDpToPixel(76,context),imageHieght,null);
invalidate();
}
public static float convertPixelsToDp(float px,Context context){
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
float dp = px / (metrics.densityDpi / 160f);
return dp;
}
public static float convertDpToPixel(float dp,Context context){
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
float px = dp * (metrics.densityDpi/160f);
return px;
}
public Bitmap getMarkerBitmapFromView(#DrawableRes int resIdMain, #DrawableRes int resId) {
View customMarkerView = ((LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.custom_marker, null);
customMarkerView.findViewById(R.id.custom_marker_firstlayout);
if(resIdMain != 0){
customMarkerView.setBackgroundResource(resIdMain);
}
ImageView markerImageView = (ImageView) customMarkerView.findViewById(R.id.custom_marker_secondLayout);
if(resId != 0){
markerImageView.setImageResource(resId);
}
customMarkerView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
customMarkerView.layout(0, 0, customMarkerView.getMeasuredWidth(), customMarkerView.getMeasuredHeight());
customMarkerView.buildDrawingCache();
Bitmap returnedBitmap = Bitmap.createBitmap(customMarkerView.getMeasuredWidth(), customMarkerView.getMeasuredHeight(),
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(returnedBitmap);
canvas.drawColor(Color.WHITE, PorterDuff.Mode.SRC_IN);
Drawable drawable = customMarkerView.getBackground();
if (drawable != null)
drawable.draw(canvas);
customMarkerView.draw(canvas);
return returnedBitmap;
}
}
result:

how to click listener on custom view

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
}
}

Android - rotate and fill animation

I'm trying to figure out how to fill an View clockwise.
I figured out how to rotate an image but not sure how to rotate and fill.
Used this class to create a circle:
public class Circle extends View {
private static final int START_ANGLE_POINT = 270;
private final Paint paint;
private RectF rect;
private float angle;
public Circle(Context context, AttributeSet attrs) {
super(context, attrs);
final int strokeWidth = 60;
Point[] points = new Point[3];
points[0] = new Point(7, 13);
points[1] = new Point(13, 19);
points[2] = new Point(21, 9);
paint = new Paint();
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.FILL);
//Circle color
paint.setColor(Theme.darkRedColour());
//Initial Angle (optional, it can be zero)
angle = 0;
}
#Override
protected void onDraw(Canvas canvas) {
if (rect == null) {
DisplayMetrics metrics = App.getAppContext().getResources().getDisplayMetrics();
int densityDpi = (int)metrics.density;
densityDpi = 3;
int canvasW = getWidth();
int canvasH = getHeight();
Point centerOfCanvas = new Point(canvasW / 2, canvasH / 2);
int rectW = 100; // * (densityDpi - 1);
int rectH = 100; // * (densityDpi - 1);
int left = centerOfCanvas.x - (rectW / 2);
int top = centerOfCanvas.y - (rectH / 2);
int right = centerOfCanvas.x + (rectW / 2);
int bottom = centerOfCanvas.y + (rectH / 2);
rect = new RectF(left, top, right, bottom);
}
super.onDraw(canvas);
canvas.drawArc(rect, START_ANGLE_POINT, angle, true, paint);
}
public float getAngle() {
return angle;
}
public void setAngle(float angle) {
this.angle = angle;
}
}
Then used an AnimiationListener and updated the angle.

Custom Progress as Step - Android

I need to make something like this:
I'd try to draw this using Canvas.drawArc(...) but I failed.
Can anyone help me?
I created a view that can draw the shape that you want.
It starts by creating a path for one of the quarters, and rotating the canvas by 90 degrees to draw the path 4 times. The Paint used to draw the Path is determined by the progress / maxProgress.
I used a second path to denote the region of the canvas to clip out when drawing, so that there are empty spaces between the quarters.
Finally, the text can be drawn in the middle after restoring the canvas rotation and clipping.
public class CustomProgressView extends View {
private int progress;
private int maxProgress;
private float arcWidth;
private float arcPadding;
private Paint paintPositive;
private Paint paintNegative;
private Paint paintText;
private Path path;
private Path clipPath;
private ProgressListener listener;
public CustomProgressView(Context context) {
super(context);
init();
}
public CustomProgressView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public CustomProgressView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
arcWidth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 25, getResources().getDisplayMetrics());
arcPadding = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 6, getResources().getDisplayMetrics());
paintPositive = new Paint();
paintPositive.setColor(Color.RED);
paintPositive.setStyle(Paint.Style.FILL_AND_STROKE);
paintPositive.setAntiAlias(true);
paintNegative = new Paint();
paintNegative.setColor(Color.BLUE);
paintPositive.setStyle(Paint.Style.FILL_AND_STROKE);
paintNegative.setAntiAlias(true);
paintText = new Paint();
paintText.setColor(Color.BLACK);
paintText.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 24, getResources().getDisplayMetrics()));
progress = 0;
maxProgress = 10;
}
#Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
float diameter = Math.min(getWidth(), getHeight());
RectF ovalOuter = new RectF(0, 0, diameter, diameter);
RectF ovalInner = new RectF(ovalOuter.left + arcWidth, ovalOuter.top + arcWidth, ovalOuter.right - arcWidth, ovalOuter.bottom - arcWidth);
path = new Path();
path.moveTo(ovalOuter.centerX(), ovalOuter.top);
path.addArc(ovalOuter, 270, 90);
path.lineTo(ovalInner.right, ovalInner.centerY());
path.addArc(ovalInner, 0, -90);
path.lineTo(ovalOuter.centerX(), ovalOuter.top);
clipPath = new Path();
clipPath.addRect(ovalOuter.left, ovalOuter.centerY() - arcPadding / 2, ovalOuter.right, ovalOuter.centerY() + arcPadding / 2, Path.Direction.CW);
clipPath.addRect(ovalOuter.centerX() - arcPadding / 2, ovalOuter.top, ovalOuter.centerX() + arcPadding / 2, ovalOuter.bottom, Path.Direction.CW);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
float perc = (float) progress / (float) maxProgress;
int state = 0;
if (perc < 0.25) {
state = 1;
} else if (perc < 0.5) {
state = 2;
} else if (perc < 0.75) {
state = 3;
} else {
state = 4;
}
RectF bounds = new RectF();
path.computeBounds(bounds, true);
// Draw Circle
canvas.save();
// Clip padding
canvas.clipPath(clipPath, Region.Op.DIFFERENCE);
canvas.drawPath(path, state == 1 ? paintPositive : paintNegative);
canvas.rotate(90, bounds.left, bounds.bottom);
canvas.drawPath(path, state == 2 ? paintPositive : paintNegative);
canvas.rotate(90, bounds.left, bounds.bottom);
canvas.drawPath(path, state == 3 ? paintPositive : paintNegative);
canvas.rotate(90, bounds.left, bounds.bottom);
canvas.drawPath(path, state == 4 ? paintPositive : paintNegative);
canvas.restore();
// Draw Progress
String text = String.valueOf(progress);
Rect textBounds = new Rect();
paintText.getTextBounds(text, 0, text.length(), textBounds);
float x = bounds.left - textBounds.width() / 2;
float y = bounds.bottom + textBounds.height() / 2;
canvas.drawText(text, x, y, paintText);
}
public int getProgress() {
return progress;
}
public void setProgress(int progress) {
int oldProgress = this.progress;
this.progress = progress;
if (listener != null) {
listener.onProgressChanged(oldProgress, progress);
}
invalidate();
}
public int getMaxProgress() {
return maxProgress;
}
public void setMaxProgress(int maxProgress) {
this.maxProgress = maxProgress;
invalidate();
}
public ProgressListener getListener() {
return listener;
}
public void setListener(ProgressListener listener) {
this.listener = listener;
}
public interface ProgressListener {
void onProgressChanged(int oldProgress, int newProgress);
}
}

How to give border to circle using paint

Hi i have implemented Progress bar and it is working fine, but my problem is i need to give a only border to circle using paint. I worked on that but it is taking all the area of circle, i need only border.
My paint code:
mCirclePaint = new Paint();
mCirclePaint.setAntiAlias(true);
mCirclePaint.setDither(true);
mCirclePaint.setColor(mCircleColor);
mCirclePaint.setStrokeWidth(mCircleStrokeWidth);
mCirclePaint.setStyle(Paint.Style.STROKE);
mCirclePaint.setStrokeJoin(Paint.Join.MITER);
// mCirclePaint.setShadowLayer(4.0f, 0.0f, 2.0f, Color.BLACK);
mCirclePaint.setStrokeCap(Paint.Cap.SQUARE);
canvas.drawPath(mCirclePath, mCirclePaint)
try this ,
paint = new Paint();
paint.setColor(Color.GREEN);
paint.setStrokeWidth(2);
paint.setStyle(Paint.Style.STROKE);
canvas.drawCircle(0, 0, (float) (width1/(1.4)), paint);
and refer this , might be help full to you .Android : canvas.drawBitmap() method not working properly
This is my code for your solution. Just copy this class and try to understand what your were doing wrong. This view will draw progress bar in center of view.
/**
* Created by GIGAMOLE on 23.01.2016.
*/
public class StrokeProgressBar extends View {
private final static float BAR_STROKE = 10.0f;
private final static float BAR_HEIGHT = 60.0f;
private final static float BAR_PADDING = 100.0f;
private final Paint mProgressPaint = new Paint(Paint.ANTI_ALIAS_FLAG) {
{
setDither(true);
setAntiAlias(true);
setColor(Color.BLUE);
setStyle(Style.FILL);
}
};
// private final Paint mBgPaint = new Paint(Paint.ANTI_ALIAS_FLAG) {
// {
// setDither(true);
// setAntiAlias(true);
// setColor(Color.GRAY);
// setStyle(Style.FILL);
// }
// };
private final Paint mBgStrokePaint = new Paint(Paint.ANTI_ALIAS_FLAG) {
{
setDither(true);
setAntiAlias(true);
setColor(Color.BLUE);
setStyle(Style.STROKE);
setStrokeWidth(BAR_STROKE);
setStrokeCap(Cap.SQUARE);
}
};
public StrokeProgressBar(final Context context) {
this(context, null);
}
public StrokeProgressBar(final Context context, final AttributeSet attrs) {
this(context, attrs, 0);
}
public StrokeProgressBar(final Context context, final AttributeSet attrs, final int defStyleAttr) {
super(context, attrs, defStyleAttr);
// Draw always
setWillNotDraw(false);
}
#Override
protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
#Override
protected void onDraw(final Canvas canvas) {
super.onDraw(canvas);
final float height = canvas.getClipBounds().height();
final float width = canvas.getClipBounds().width();
// Background rect
final Rect bgRect = new Rect(
(int) BAR_PADDING,
(int) (height / 2.0f - BAR_HEIGHT / 2.0f),
(int) (width - BAR_PADDING),
(int) (height / 2.0f + BAR_HEIGHT / 2.0f)
);
// Progress bar rect
final Rect progressRect = new Rect(
(int) BAR_PADDING,
(int) (height / 2.0f - BAR_HEIGHT / 2.0f),
(int) ((width - BAR_PADDING) * 0.7f), // 0.7f is the fraction of progress == 70%
(int) (height / 2.0f + BAR_HEIGHT / 2.0f)
);
// At first draw stroke
canvas.drawRect(
bgRect,
mBgStrokePaint
);
// // At second draw bg
// canvas.drawRect(
// bgRect,
// mBgPaint
// );
// At third draw progress
canvas.drawRect(
progressRect,
mProgressPaint
);
}
}

Categories

Resources