How to draw circle by canvas in Android? - java

I want to draw circle by canvas. Here is my code:
[MyActivity.java]:
public class MyActivity extends Activity
{
public void onCreate(Bundle savedInstanceState)
{
...
setContentView(new View(this,w,h));
}
}
[View.java]:
public class View extends SurfaceView
{
public View(Context context, int w, int h)
{
super(context);
Canvas grid = new Canvas(Bitmap.createBitmap(h,w, Bitmap.Config.ARGB_8888));
grid. drawColor(Color.WHITE);
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
grid.drawCircle(w/2, h/2 , w/2, paint);
}
}
So I have just black screen without circle.
Why it does not work? How to fix it?

You can override the onDraw method of your view and draw the circle.
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawCircle(x, y, radius, paint);
}
For a better reference on drawing custom views check out the official Android documentation.
http://developer.android.com/training/custom-views/custom-drawing.html

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.View;
public class MainActivity extends Activity
{
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(new MyView(this));
}
public class MyView extends View
{
Paint paint = null;
public MyView(Context context)
{
super(context);
paint = new Paint();
}
#Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
int x = getWidth();
int y = getHeight();
int radius;
radius = 100;
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.WHITE);
canvas.drawPaint(paint);
// Use Color.parseColor to define HTML colors
paint.setColor(Color.parseColor("#CD5C5C"));
canvas.drawCircle(x / 2, y / 2, radius, paint);
}
}
}
Edit
if you want to draw circle at centre. You could also translate your entire canvas to center then draw circle at center.using
canvas.translate(getWidth()/2f,getHeight()/2f);
canvas.drawCircle(0,0, radius, paint);
These two link also help
http://www.compiletimeerror.com/2013/09/introduction-to-2d-drawing-in-android.html#.VIg_A5SSy9o
http://android-coding.blogspot.com/2012/04/draw-circle-on-canvas-canvasdrawcirclet.html

public class CircleView extends View {
private static final String COLOR_HEX = "#E74300";
private final Paint drawPaint;
private float size;
public CircleView(final Context context, final AttributeSet attrs) {
super(context, attrs);
drawPaint = new Paint();
drawPaint.setColor(Color.parseColor(COLOR_HEX));
drawPaint.setAntiAlias(true);
setOnMeasureCallback();
}
#Override
protected void onDraw(final Canvas canvas) {
super.onDraw(canvas);
canvas.drawCircle(size, size, size, drawPaint);
}
private void setOnMeasureCallback() {
ViewTreeObserver vto = getViewTreeObserver();
vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
removeOnGlobalLayoutListener(this);
size = getMeasuredWidth() / 2;
}
});
}
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
private void removeOnGlobalLayoutListener(ViewTreeObserver.OnGlobalLayoutListener listener) {
if (Build.VERSION.SDK_INT < 16) {
getViewTreeObserver().removeGlobalOnLayoutListener(listener);
} else {
getViewTreeObserver().removeOnGlobalLayoutListener(listener);
}
}
}
Xml example: will produce a circle of 5dp
<com.example.CircleView
android:layout_width="10dp"
android:layout_height="10dp"/>

If you are using your own CustomView extending View class, you need to call canvas.invalidate() method which will internally call onDraw method. You can use default API for canvas to draw a circle. The x, y cordinate define the center of the circle. You can also define color and styling in paint & pass the paint object.
public class CustomView extends View {
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
setupPaint();
}
}
Define default paint settings and canvas (Initialise paint in constructor so that you can reuse the same object everywhere and change only specific settings wherever required)
private Paint drawPaint;
// Setup paint with color and stroke styles
private void setupPaint() {
drawPaint = new Paint();
drawPaint.setColor(Color.BLUE);
drawPaint.setAntiAlias(true);
drawPaint.setStrokeWidth(5);
drawPaint.setStyle(Paint.Style.FILL_AND_STROKE);
drawPaint.setStrokeJoin(Paint.Join.ROUND);
drawPaint.setStrokeCap(Paint.Cap.ROUND);
}
And initialise canvas object
private Canvas canvas;
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
this.canvas = canvas;
canvas.drawCircle(xCordinate, yCordinate, RADIUS, drawPaint);
}
And finally, for every view refresh or new draw on the screen, you need to call invalidate method. Remember your entire view is redrawn, hence this is an expensive call. Make sure you do only the necessary operations in onDraw
canvas.invalidate();
For more details on canvas drawing refer https://medium.com/#mayuri.k18/android-canvas-for-drawing-and-custom-views-e1a3e90d468b

#Override
public void onDraw(Canvas canvas){
canvas.drawCircle(xPos, yPos,radius, paint);
}
Above is the code to render a circle. Tweak the parameters to your suiting.

Try this
The entire code for drawing a circle or download project source code and test it on your android studio. Draw circle on canvas programmatically.
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.widget.ImageView;
public class Shape {
private Bitmap bmp;
private ImageView img;
public Shape(Bitmap bmp, ImageView img) {
this.bmp=bmp;
this.img=img;
onDraw();
}
private void onDraw(){
Canvas canvas=new Canvas();
if (bmp.getWidth() == 0 || bmp.getHeight() == 0) {
return;
}
int w = bmp.getWidth(), h = bmp.getHeight();
Bitmap roundBitmap = getRoundedCroppedBitmap(bmp, w);
img.setImageBitmap(roundBitmap);
}
public static Bitmap getRoundedCroppedBitmap(Bitmap bitmap, int radius) {
Bitmap finalBitmap;
if (bitmap.getWidth() != radius || bitmap.getHeight() != radius)
finalBitmap = Bitmap.createScaledBitmap(bitmap, radius, radius,
false);
else
finalBitmap = bitmap;
Bitmap output = Bitmap.createBitmap(finalBitmap.getWidth(),
finalBitmap.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, finalBitmap.getWidth(),
finalBitmap.getHeight());
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
paint.setDither(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(Color.parseColor("#BAB399"));
canvas.drawCircle(finalBitmap.getWidth() / 2 + 0.7f, finalBitmap.getHeight() / 2 + 0.7f, finalBitmap.getWidth() / 2 + 0.1f, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(finalBitmap, rect, rect, paint);
return output;
}

Here is example to draw stroke circle canvas
val paint = Paint().apply {
color = Color.RED
style = Paint.Style.STROKE
strokeWidth = 10f
}
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
canvas?.drawCircle(200f, 100f, 100f, paint)
}
Result
Example to draw solid circle canvas
val paint = Paint().apply {
color = Color.RED
}
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
canvas?.drawCircle(200f, 100f, 100f, paint)
}
Result
Hope it help

private Paint green = new Paint();
private int greenx , greeny;
green.setColor(Color.GREEN);
green.setAntiAlias(false);
canvas.drawCircle(greenx,greeny,20,green);

Related

How to increase Opacity/Strength of Shadow in canvas android?

I am trying to get a shadow effect on a text in canvas. The problem I am facing is the shadow that is being created is very dim and showing weird shapes. I am trying to overcome these problems. I am open to suggestions where I can create Images and save to disk without using canvas.
Code:
class MainActivity : AppCompatActivity() {
private lateinit var canvasIV: ImageView
private lateinit var imgBitmap: Bitmap
private lateinit var canvas: Canvas
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
canvasIV = findViewById(R.id.canvasIV)
val displayMetrics = DisplayMetrics()
windowManager.defaultDisplay.getMetrics(displayMetrics)
val height = displayMetrics.heightPixels
val width = displayMetrics.widthPixels
imgBitmap =
Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565)
canvas = Canvas(imgBitmap)
canvas.drawBitmap(imgBitmap, 0f, 0f, null)
val shadowPaint = Paint()
shadowPaint.isAntiAlias = true
shadowPaint.color = Color.parseColor("#F897B9")
val tSize = 80.0f
shadowPaint.textSize = tSize
shadowPaint.strokeWidth = 20.0f
shadowPaint.style = Paint.Style.FILL
shadowPaint.alpha = 0x100
//shadowPaint.setShadowLayer(20.0f, 5f, 5f, Color.parseColor("#F897B9"))
shadowPaint.setShadowLayer(tSize, 5f, 5f, Color.GREEN)
canvas.drawText("Sayok Dey Majumder", 50f, 200f, shadowPaint)
//canvasIV.setLayerType(View.LAYER_TYPE_SOFTWARE, null)
canvasIV.setImageDrawable(BitmapDrawable(resources, imgBitmap))
}
fun convertToPixels(context: Context, nDP: Int): Float {
val conversionScale: Float = context.getResources().getDisplayMetrics().density
return (nDP * conversionScale + 0.5f)
}
fun getTextWidth(text: String, paint: Paint): Int {
val bounds = Rect()
paint.getTextBounds(text, 0, text.length, bounds)
return bounds.left + bounds.width()
}
fun getTextHeight(text: String, paint: Paint): Int {
val bounds = Rect()
paint.getTextBounds(text, 0, text.length, bounds)
return bounds.bottom + bounds.height()
}
}
What I am getting is:
What I am trying to achieve:
The Bitmap with config Bitmap.Config.ARGB_8888 don't support Alpha channel.
Use this instead:
imgBitmap =Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
also the following line don't do anything:
canvas.drawBitmap(imgBitmap, 0f, 0f, null)
Better Solution:
Also, shadow layer has limited capacity and I recommend to draw the shadow manually.
val shadowPaint = Paint(defaultPaint)
// ... here customize shadow paint
canvas.drawText("your text", x, y, defaultPaint);
canvas.drawText("your text", x, y, shadowPaint);
Also, you could extend TextView and override the onDraw function. Here I create customView that add shadow. you could adjust it.
import android.content.Context;
import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.text.TextPaint;
import android.util.AttributeSet;
public class ShadowTextView extends androidx.appcompat.widget.AppCompatTextView {
private TextPaint normalPaint;
private int color;
TextPaint shadowPaint;
public ShadowTextView(Context context) {
super(context);
init();
}
public ShadowTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public ShadowTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
normalPaint=new TextPaint(getPaint());
shadowPaint=new TextPaint(getPaint());
shadowPaint.setStyle(Paint.Style.FILL_AND_STROKE);
shadowPaint.setStrokeCap(Paint.Cap.ROUND);
shadowPaint.setStrokeJoin(Paint.Join.ROUND);
shadowPaint.setStrokeWidth(30);
shadowPaint.setMaskFilter(new BlurMaskFilter( 10, BlurMaskFilter.Blur.NORMAL));
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
this.savePaint();
getPaint().set(shadowPaint);
setTextColor(Color.argb(100,255,0,0));
super.onDraw(canvas);
this.restorePaint();
}
public void savePaint() {
normalPaint.set(getPaint());
color=getCurrentTextColor();
}
public void restorePaint() {
getPaint().set(normalPaint);
setTextColor(color);
}
}

Is there any method to fill a Rect in a Canvas with an image?

I've setted up a simple application that once I have structured a Canvas puts an Rectangle inside it. I was asking myself if there's a method that allows me to fill that rettangle with an image.
This is my Canvas Class code:
public class MioCanvas extends View {
Paint paint;
Rect rect;
public MioCanvas(Context context) {
super(context);
paint = new Paint();
rect = new Rect();
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paint.setColor(Color.GRAY);
paint.setStrokeWidth(3);
canvas.drawRect(0, 1999999, canvas.getWidth() / 2, canvas.getHeight() / 2, paint);
}
}
This is my activity code:
public class MainActivity extends AppCompatActivity {
MioCanvas mioCanvas;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mioCanvas = new MioCanvas(this);
mioCanvas.setBackgroundColor(Color.GREEN);
setContentView(mioCanvas);
}
}
You can use a Bitmap with your custom rect as input.
Rect rectangle = new Rect(0,0,100,100);
canvas.drawBitmap(bitmap, null, rectangle, null);

Android Canvas drawLine not drawing on MainActivity

I want to draw a line on the Main Activity using Canvas. The problem is, it is not drawing anything. I have the following code:
Bitmap bitmap = Bitmap.createBitmap(1920, 1080, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.FILL_AND_STROKE);
paint.setStrokeWidth(10);
float left = 20;
float top = 20;
float right = 50;
float bottom = 100;
canvas.drawLine(left, top, right, bottom, paint);
you can display the bitmap like that:
canvas.drawBitmap(bmp, positionX, positionY, paint);
in your case you can try somthing like this:
canvas.drawBitmap(bitmap, 0, 0, null);
but you need to use a diffrent canvas for it. The canvas wich let you draw stuff on your screen will be passed to your onDraw() method in your View. So you need to make a View class first and add it in your MainActivity.
You can do that like this:
First you create a class called MyView and add this code to it:
public class MyView extends View {
Bitmap bitmap;
public MyView(Context context) {
bitmap = Bitmap.createBitmap(1920, 1080, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.FILL_AND_STROKE);
paint.setStrokeWidth(10);
float left = 20;
float top = 20;
float right = 50;
float bottom = 100;
canvas.drawLine(left, top, right, bottom, paint);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(bitmap, 0, 0, null);
super.onDraw(canvas);
}
}
then you change the code in your onCreate() method in your MainActivity to this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MyView myView = new MyView(this);
setContentView(myView);
}
Create a class like this
public class MyView extends View {
public MyView(Context context) {
super(context);
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
protected void onDraw(Canvas canvas) {
Paint paint = new Paint();
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.FILL_AND_STROKE);
paint.setStrokeWidth(10);
float left = 20;
float top = 20;
float right = 50;
float bottom = 100;
canvas.drawLine(left, top, right, bottom, paint);
}
}

Cant get two classes to draw using canvas

Iam doing my first game for android.
I want to do a very simple thing which is to have a background and a ball that will "spawn" in it.
So I have made my GameView:
package com.example.newarkanoid;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.MotionEvent;
import android.view.View;
public class Tela extends View {
Paint paint;
int x,y;
int lastx,lasty;
Bola bola;
public Tela(Context context, Bola BOLA) {
super(context);
paint = new Paint();
x=0;lastx=0;
y=0;lasty=0;
bola = BOLA;
bola.paint.setColor(Color.BLACK);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paint.setColor(Color.WHITE);
canvas.drawPaint(paint);
bola.invalidate();
}
public boolean onTouchEvent(MotionEvent event) {
x = (int)event.getX();
y = (int)event.getY();
if(lastx !=x || lasty !=y){
lastx=x;
lasty=y;
bola.x = x;
bola.y = y;
bola.invalidate();
}
return false;
}
}
Well, above is my MainDisplay, now i need a ball:
package com.example.newarkanoid;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.View;
public class Bola extends View {
Paint paint;
float x,y,raio;
public Bola(Context context, float x, float y, float raio) {
super(context);
this.x = x;
this.y = y;
this.raio = raio;
paint = new Paint();
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paint.setStyle(Paint.Style.FILL);
canvas.drawCircle(x, y, raio, paint);
}
}
So, I did like that cause my teacher told me, you dont have to call invalidate for the intire main display, you can call invalidate just for your ball, so i made my ball drawing code, also its properties.
So as you can see in the code, when i click somewhere in the touchscreen my ball x and y will change to the click position, and then call invalidate.
The thing is, the ball does not even appear when i create my mainDisplay, so I was wondering, is there something like a context problem? why my ball isnt drawn?
Also, here is my MainActivity:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bola bola = new Bola(this,20,20,5);
Tela t = new Tela(this,bola);
setContentView(t);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paint.setColor(Color.WHITE);
canvas.drawPaint(paint);
bola.invalidate();
}
when bola invalidate, bola will draw with its canvas, different the Tela's canvas. You can create a class, not extends view, with draw method
public void draw(Canvas canvas) {
paint.setStyle(Paint.Style.FILL);
canvas.drawCircle(x, y, raio, paint);
}
and call in tela:
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paint.setColor(Color.WHITE);
canvas.drawPaint(paint);
bola.draw(canvas);
}
use bola.draw(canvas); in your onDraw()

How should I give images rounded corners in Android?

I would like to change an image I loaded to have round corners.
Any hints, tutorials, best practices you know of?
For a more controlled method draw a rounded rectangle and mask it onto your image using the porter-duff Xfer mode of the paint.
First setup the Xfer paint and the rounded bitmap:
Bitmap myCoolBitmap = ... ; // <-- Your bitmap you want rounded
int w = myCoolBitmap.getWidth(), h = myCoolBitmap.getHeight();
// We have to make sure our rounded corners have an alpha channel in most cases
Bitmap rounder = Bitmap.createBitmap(w,h,Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(rounder);
// We're going to apply this paint eventually using a porter-duff xfer mode.
// This will allow us to only overwrite certain pixels. RED is arbitrary. This
// could be any color that was fully opaque (alpha = 255)
Paint xferPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
xferPaint.setColor(Color.RED);
// We're just reusing xferPaint to paint a normal looking rounded box, the 20.f
// is the amount we're rounding by.
canvas.drawRoundRect(new RectF(0,0,w,h), 20.0f, 20.0f, xferPaint);
// Now we apply the 'magic sauce' to the paint
xferPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
Now apply this bitmap ontop of your image:
Bitmap result = Bitmap.createBitmap(myCoolBitmap.getWidth(), myCoolBitmap.getHeight() ,Bitmap.Config.ARGB_8888);
Canvas resultCanvas = new Canvas(result)
resultCanvas.drawBitmap(myCoolBitmap, 0, 0, null);
resultCanvas.drawBitmap(rounder, 0, 0, xferPaint);
Bitmap with rounded corners now resides in result.
Why not use clipPath?
protected void onDraw(Canvas canvas) {
Path clipPath = new Path();
float radius = 10.0f;
float padding = radius / 2;
int w = this.getWidth();
int h = this.getHeight();
clipPath.addRoundRect(new RectF(padding, padding, w - padding, h - padding), radius, radius, Path.Direction.CW);
canvas.clipPath(clipPath);
super.onDraw(canvas);
}
Romain Guy himself writes about this in his blog:
To generate the rounded images I simply wrote a custom Drawable that
draws a rounded rectangle using Canvas.drawRoundRect(). The trick is
to use a Paint with a BitmapShader to fill the rounded rectangle with
a texture instead of a simple color. Here is what the code looks like:
BitmapShader shader;
shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setShader(shader);
RectF rect = new RectF(0.0f, 0.0f, width, height);
// rect contains the bounds of the shape
// radius is the radius in pixels of the rounded corners
// paint contains the shader that will texture the shape
canvas.drawRoundRect(rect, radius, radius, paint);
The sample application goes a little further and fakes a vignette
effect by combining the BitmapShader with a RadialGradient.
Here's a way I discovered to do it with an ImageView. I tried other methods, including the answers here and on similar questions, but I found that they didn't work well for me, as I needed the corners to be applied to the image view and not directly to the bitmap. Applying directly to the bitmap won't work if you're scaling/cropping/panning that bitmap, since the corners will also be scaled/cropped/panned.
public class RoundedCornersImageView extends ImageView {
private final Paint restorePaint = new Paint();
private final Paint maskXferPaint = new Paint();
private final Paint canvasPaint = new Paint();
private final Rect bounds = new Rect();
private final RectF boundsf = new RectF();
public RoundedCornersImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public RoundedCornersImageView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public RoundedCornersImageView(Context context) {
super(context);
init();
}
private void init() {
canvasPaint.setAntiAlias(true);
canvasPaint.setColor(Color.argb(255, 255, 255, 255));
restorePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP));
maskXferPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY));
}
#Override
protected void onDraw(Canvas canvas) {
canvas.getClipBounds(bounds);
boundsf.set(bounds);
canvas.saveLayer(boundsf, restorePaint, Canvas.ALL_SAVE_FLAG);
super.onDraw(canvas);
canvas.saveLayer(boundsf, maskXferPaint, Canvas.ALL_SAVE_FLAG);
canvas.drawARGB(0, 0, 0, 0);
canvas.drawRoundRect(boundsf, 75, 75, canvasPaint);
canvas.restore();
canvas.restore();
}
}
Here's an alternative that uses hardware layers for the final layer composite:
public class RoundedCornersImageView extends ImageView {
private final Paint restorePaint = new Paint();
private final Paint maskXferPaint = new Paint();
private final Paint canvasPaint = new Paint();
private final Rect bounds = new Rect();
private final RectF boundsf = new RectF();
public RoundedCornersImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public RoundedCornersImageView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public RoundedCornersImageView(Context context) {
super(context);
init();
}
private void init() {
canvasPaint.setAntiAlias(true);
canvasPaint.setColor(Color.argb(255, 255, 255, 255));
restorePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP));
maskXferPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY));
setLayerType(View.LAYER_TYPE_HARDWARE, restorePaint);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.getClipBounds(bounds);
boundsf.set(bounds);
super.onDraw(canvas);
canvas.saveLayer(boundsf, maskXferPaint, Canvas.ALL_SAVE_FLAG);
canvas.drawARGB(0, 0, 0, 0);
canvas.drawRoundRect(boundsf, 75, 75, canvasPaint);
canvas.restore();
}
}
At first I wasn't able to get it to work with this method because my corners were becoming black; I later realized what the problem was after reading this question: Android how to apply mask on ImageView?. It turns out that modifying the alpha in the canvas is actually "scratching it out" directly on the screen, and punching a hole to the underlying window which is black. That's why two layers are needed: one to apply the mask, and another to apply the composited image to the screen.
How about creating a NinePatchDrawable image that has just rounded corners and has a transparent body. Overlay your image with an appropriately re-sized version of your NinePatchDrawable.
package com.pkg;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Bitmap.Config;
import android.graphics.PorterDuff.Mode;
import android.os.Bundle;
import android.os.Environment;
import android.widget.ImageView;
public class RoundedImage extends Activity {
/** Called when the activity is first created. */
ImageView imag;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
imag=(ImageView)findViewById(R.id.image);
//ImageView img1=(ImageView)findViewById(R.id.imageView1);
BitmapFactory.Options bitopt=new BitmapFactory.Options();
bitopt.inSampleSize=1;
// String img=Environment.getExternalStorageDirectory().toString();
// String filepath =Environment.getExternalStorageDirectory().toString();
String filepath ="/mnt/sdcard/LOST.DIR";
File imagefile = new File(filepath + "/logo.jpg");
FileInputStream fis = null;
try
{
fis = new FileInputStream(imagefile);
}
catch (FileNotFoundException e1)
{
// TODO Auto-generated catch block
e1.printStackTrace();
}
Bitmap bi = BitmapFactory.decodeStream(fis);
if(bi!=null){
imag.setImageBitmap(getRoundedCornerBitmap(bi));
}
}
public static Bitmap getRoundedCornerBitmap(Bitmap bitmap) {
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
bitmap.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = 0xff424242;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
final RectF rectF = new RectF(rect);
final float roundPx = 12;
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
}
}
Here's another rounded ImageView implementation using Path. The performance is great, but in certain conditions some bugs may appear on emulators because of the hardware drawing.
public class RoundImageView extends ImageView {
private Path mPath;
private RectF mRect;
private Paint mPaint;
private int mCornerRadius;
private float mImageAlpha;
private boolean mIsCircular;
public RoundImageView(Context context) {
this(context, null);
}
public RoundImageView(Context context, AttributeSet attrs) {
this(context, attrs, R.attr.roundImageViewStyle);
}
public RoundImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray a = context.obtainStyledAttributes(
attrs, R.styleable.RoundImageView, defStyle, 0);
mCornerRadius = a.getDimensionPixelSize(R.styleable.RoundImageView_cornerRadius, 0);
mIsCircular = a.getBoolean(R.styleable.RoundImageView_isCircular, false);
mImageAlpha = a.getFloat(R.styleable.RoundImageView_imageAlpha, 1);
a.recycle();
setAlpha((int) (mImageAlpha * 255));
// Avoid expensive off-screen drawing
setLayerType(LAYER_TYPE_HARDWARE, null);
mPath = new Path();
mRect = new RectF();
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPath.reset();
if (mIsCircular) {
float halfWidth = canvas.getWidth() / 2;
float halfHeight = canvas.getHeight() / 2;
float radius = Math.max(halfWidth, halfHeight);
mPath.addCircle(halfWidth, halfHeight, radius, Path.Direction.CW);
} else {
mRect.right = canvas.getWidth();
mRect.bottom = canvas.getHeight();
mPath.addRoundRect(mRect, mCornerRadius, mCornerRadius, Path.Direction.CW);
}
canvas.drawPath(mPath, mPaint);
}
}
P.S. Learn OpenGL ES provided the best solution. It's very smooth and works on emulators too.
best solution I found ->
1) create rounded corner drawable. And set to imageview as background.
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<corners
android:radius="10dp" /></shape>
2) Then set image view object property of setClipToOutline(true) in java code.
imageview.setClipToOutline(true);
It works like charm

Categories

Resources