I'm trying to create a custom shape using the Path object in Android and I'm running into a weird problem.
What I'm trying to achieve is depicted in the picture below
Here is the code I'm using to draw and fill the shape:
public class BallView extends RelativeLayout {
....
protected void onDraw(Canvas canvas) {
...
PaintArc(canvas);
}
private void PaintArc(Canvas canvas) {
Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
p.setAntiAlias(true);
p.setStyle(Paint.Style.FILL_AND_STROKE);
p.setStrokeWidth(2);
p.setColor(Color.RED);
RectF oval = new RectF(20, 20, getWidth() - 20, getHeight() - 20);
RectF oval2 = new RectF(0, 0, getWidth(), getHeight());
Path path = new Path();
path.setFillType(Path.FillType.EVEN_ODD);
path.addArc(oval, 0, 180);
path.addArc(oval2, 0, 180);
float y=20+oval.height()/2;
float x=20;
path.moveTo(x,y);
path.lineTo(x - 20, y);
x=oval.width()+20;
path.moveTo(x,y);
path.lineTo(x+20,y);
path.close();
canvas.drawPath(path, p);
}
}
The actual result that I'm getting looks like this:
The resulting shape without Filling looks like this:
Can you tell me what I'm doing wrong ?
try this:
class MyView extends View {
private Path mPath;
private Paint mPaint;
private RectF mOval;
public MyView(Context context) {
super(context);
mPath = new Path();
mPaint = new Paint();
mPaint.setColor(0xffff0000);
mOval = new RectF();
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
int dx = w / 4;
mOval.set(0, 0, w, w);
mPath.reset();
mPath.moveTo(0, w / 2f);
mPath.arcTo(mOval, 180, 180);
mPath.rLineTo(-dx, 0);
mOval.inset(dx, dx);
mPath.addArc(mOval, 0, -180);
mPath.rLineTo(-dx, 0);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(0xffffffff);
mPaint.setStyle(Style.FILL);
canvas.drawPath(mPath, mPaint);
canvas.translate(0, getWidth() / 2);
mPaint.setStyle(Style.STROKE);
canvas.drawPath(mPath, mPaint);
}
}
- I have just edited my answer
and i add below code
RectF oval3 = new RectF(10, 20, getWidth() - 10, getHeight() - 10);
/**
*Now check this code output seem like your thought
*/
private void PaintArc(Canvas canvas) {
Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
p.setAntiAlias(true);
p.setStyle(Paint.Style.STROKE);
p.setStrokeWidth(2);
p.setColor(Color.RED);
Paint p1 = new Paint(Paint.ANTI_ALIAS_FLAG);
p1.setAntiAlias(true);
p1.setStyle(Paint.Style.STROKE);
p1.setStrokeWidth(10);
p1.setColor(Color.RED);
RectF oval = new RectF(20, 20, getWidth() - 20, getHeight() - 20);
RectF oval2 = new RectF(0, 0, getWidth(), getHeight());
RectF oval3 = new RectF(10, 20, getWidth() - 10, getHeight() - 10);
Path path = new Path();
path.setFillType(Path.FillType.EVEN_ODD);
path.addArc(oval, 0, 180);
path.addArc(oval2, 0, 180);
path.addArc(oval3, 0, 180);
float y = 20 + oval.height() / 2;
float x = 20;
path.moveTo(x, y);
path.lineTo(x - 20, y);
x = oval.width() + 20;
path.moveTo(x, y);
path.lineTo(x + 20, y);
path.close();
canvas.drawArc(oval3, 0, 180, false, p1);
canvas.drawPath(path, p);
}
Related
I am create a custom ImageView with Pinch IN-OUT zoom and circular crop image.The Pinch in-out is wroking fine but when i trying to cropping image, can't get the particulr circle image. I'm using Pinch in-out working based on onTuchListener and Circular Cropping based on canvas class.
I have used below mentioned code for Pinch in-out and Circle Crop image:
#Override
protected void onDraw(Canvas canvas) {
onDrawReady = true;
imageRenderedAtLeastOnce = true;
if (delayedZoomVariables != null) {
setZoom(delayedZoomVariables.scale, delayedZoomVariables.focusX, delayedZoomVariables.focusY, delayedZoomVariables.scaleType);
delayedZoomVariables = null;
}
super.onDraw(canvas);
if (bitmap == null) {
circleWindowFrame(); //Creating circle view
}
canvas.drawBitmap(bitmap, 0, 0, null);
}
protected void circleWindowFrame() {
bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
Canvas osCanvas = new Canvas(bitmap);
RectF outerRectangle = new RectF(0, 0, bitmap.getWidth(), bitmap.getHeight());
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(getResources().getColor(R.color.overlay));
paint.setAlpha(99);
osCanvas.drawRect(outerRectangle, paint);
paint.setColor(Color.TRANSPARENT);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT));
float centerX = getWidth() / 2;
float centerY = getHeight() / 2;
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
int width = metrics.widthPixels;
float radius = width / 2;
osCanvas.drawCircle(centerX, centerY, radius, paint);
}
This code for Cropping:
public static Bitmap getCrop() {
Bitmap circleBitmap;
circleBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
BitmapShader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
Paint paint = new Paint();
paint.setShader(shader);
paint.setAntiAlias(true);
Canvas c = new Canvas(circleBitmap);
c.drawCircle(bitmap.getWidth() / 2, bitmap.getHeight() / 2, bitmap.getWidth() / 2, paint);
return bitmap;
}
Thanks for Advance...
try this
public static Bitmap toOvalBitmap(#NonNull Bitmap bitmap) {
int width = bitmap.getWidth();
int height = bitmap.getHeight();
Bitmap output = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(output);
int color = 0xff424242;
Paint paint = new Paint();
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
RectF rect = new RectF(0, 0, width, height);
canvas.drawOval(rect, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(bitmap, 0, 0, paint);
bitmap.recycle();
return output;
}
I am drawing a hexagonal path in android app. Now I want to place an image in the drawn path. Below is the code I am using to draw the path.
combPath = getHexPath(cellWidth / 2f, cellWidth / 2f, (float) (cellWidth * Math.sqrt(3) / 4));
fillPaint.setColor(cellSet[c][r] ? Color.RED : Color.WHITE);
canvas.drawPath(combPath, fillPaint);
Method getHexPath()
private Path getHexPath(float size, float centerX, float centerY) {
Path path = new Path();
for (int j = 0; j <= 6; j++) {
double angle = j * Math.PI / 3;
float x = (float) (centerX + size * Math.cos(angle));
float y = (float) (centerY + size * Math.sin(angle));
if (j == 0) {
path.moveTo(x, y);
} else {
path.lineTo(x, y);
}
}
return path;
}
Now I have to place an image in the hexagonal path using "path()" variable. How can I achieve it?
TIA
Try to use something like this:
Bitmap bitmap = getBitmap(); // retrieve bitmap that you want to draw somehow
Paint paint = new Paint();
paint.setAntiAlias(true);
combPath = getHexPath(cellWidth / 2f, cellWidth / 2f, (float) (cellWidth * Math.sqrt(3) / 4));
canvas.drawPath(combPath, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, 0, 0, paint);
UPDATED
Here is an example function of how you can do that
private Bitmap getCroppedBitmap(Bitmap original) {
Bitmap output = Bitmap.createBitmap(original.getWidth(),
original.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = 0xff424242;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, original.getWidth(), original.getHeight());
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
Path path = new Path();
path.moveTo(30, 20);
path.lineTo(120, 30);
path.lineTo(110, 120);
path.lineTo(20, 110);
path.lineTo(30, 20);
// canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
canvas.drawPath(path, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(original, rect, rect, paint);
return output;
}
You just need to place your bitmap, play with width/height and also insert your path. This code worked for me.
Is it possible to create custom shape like image below on relativelayout ?
i've tried with this code :
#Override
protected void onDraw(Canvas canvas) {
int w = this.getWidth() - (this.getWidth()/4);
int w2 = this.getWidth() - (this.getWidth()/6);
int h = this.getHeight();
Point a = new Point(0, 0);
Point b = new Point(w, 0);
Point c = new Point(w2, h);
Point d = new Point(0, h);
Path path = new Path();
path.moveTo(a.x, a.y);
path.lineTo(b.x, b.y);
path.lineTo(c.x, c.y);
path.lineTo(d.x, d.y);
path.lineTo(a.x, a.y);
path.close();
Paint p = new Paint();
p.setColor(Color.WHITE);
canvas.drawPath(path, p);
super.onDraw(canvas);
}
But it is not working. Any idea ?
I'm trying to draw two circles like this:
This is how I'm trying to do it:
Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_4444);
Canvas c = new Canvas(bmp);
RectF rect = new RectF(0,0,width,width);
Paint paint = new Paint();
drawCircles(paint, c, width, height, width);
ImageView img = (ImageView) findViewById(R.id.imageView1);
img.setImageBitmap(bmp);
img.setScaleType(ScaleType.FIT_CENTER);
And here is my drawCircles() method:
private void drawCircles(Paint paint, Canvas c, int width, int height, int radius) {
paint.setARGB(255, 255 , 10, 21);
paint.setStrokeWidth(10);
paint.setAntiAlias(true);
paint.setStrokeCap(Paint.Cap.BUTT);
paint.setStyle(Paint.Style.STROKE);
if(width < height && radius == 0){
radius = width/2;
height = width;
} else if (radius == 0){
radius = height/2;
width = height;
}
Paint paint2 = new Paint();
paint2.setARGB(255, 255 , 10, 21);
paint2.setStrokeWidth(10);
paint2.setAntiAlias(true);
paint2.setStrokeCap(Paint.Cap.BUTT);
paint2.setStyle(Paint.Style.STROKE);
c.drawCircle(width/2, height/2, radius-10, paint);
c.drawCircle(width/2, height/2, 50, paint2);
}
I don't know why but I get only one circle, the small one (the one drawn with paint2).
What can be the reason?
Try this code.Hope it may helps :)
public class SimpleCircleActivity extends Activity
{
private CircleDemoView circledemoView ;
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
circledemoView =new CircleDemoView(this);
setContentView(circledemoView);
}
private class CircleDemoView extends View
{
public CircleDemoView(Context context)
{
super(context);
}
#Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
Paint p = new Paint();
p.setColor(Color.RED);
DashPathEffect dashPath = new DashPathEffect(new float[]{5,5}, (float)1.0);
p.setPathEffect(dashPath);
p.setStyle(Style.STROKE);
for (int i = 0; i < 2; i ++) {
canvas.drawCircle(200, 200, 50+(i*40), p);
}
invalidate();
}
}
}
So i have this onDraw function
protected void onDraw(Canvas canvas) {
Paint paint = mPaint;
canvas.drawColor(Color.WHITE);
paint.setAntiAlias(true);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.FILL);
int w = canvas.getWidth();
int h = canvas.getHeight();
int cx = w / 2;
int cy = h / 2;
canvas.translate(cx, cy);
if (mValues != null) {
canvas.rotate(-mValues[0]);
}
canvas.drawPath(mPath, mPaint);
Paint paint1 = new Paint();
paint1.setColor(Color.BLACK);
paint1.setTextSize(25);
canvas.drawText("Some Text", 10, 25, paint1);
}
And what it does it draws a arrow that is rotating and the text is also rotating near the arrow what I want is a static text somewhere under the arrow... or something like that.
Use canvas.save(); and canvas.restore(); something like:
protected void onDraw(Canvas canvas) {
Paint paint = mPaint;
canvas.drawColor(Color.WHITE);
paint.setAntiAlias(true);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.FILL);
int w = canvas.getWidth();
int h = canvas.getHeight();
int cx = w / 2;
int cy = h / 2;
canvas.save();
canvas.translate(cx, cy);
if (mValues != null) {
canvas.rotate(-mValues[0]);
}
canvas.drawPath(mPath, mPaint);
canvans.restore();
Paint paint1 = new Paint();
paint1.setColor(Color.BLACK);
paint1.setTextSize(25);
canvas.drawText("Some Text", 10, 25, paint1);
}
Hope that helps.