I have a custom view that is a circle. Here is the code for my CircleView:
public class CircleView extends View {
private static final int START_ANGLE_POINT = 90;
private final Paint paint;
private final RectF rect;
private float angle;
public CircleView(Context context, AttributeSet attrs) {
super(context, attrs);
final int strokeWidth = 40;
paint = new Paint();
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(strokeWidth);
//Circle color
paint.setColor(Color.RED);
rect = new RectF(strokeWidth, strokeWidth, 1000 + strokeWidth, 1000 + strokeWidth);
//Initial angle is zero
angle = 0;
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawArc(rect, START_ANGLE_POINT, angle, false, paint);
}
public float getAngle() {
return angle;
}
public void setAngle(float angle) {
this.angle = angle;
} }
and here is how I declare it in the xml layout of an activity:
<com.my_package.ui.recording.CircleView
android:id="#+id/circleView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
All standard stuff. This is how my custom image looks like
Now, I want to place an imageView in the centre on the circleView? Does any one know how can I achieve that?
This is ideally what I would like to end up with:
Thank you in advance.
If you aren't set on using an ImageView and really just want to draw the bitmap in the center then have a look at canvas' drawBitmap method. This will allow you to draw it however/wherever you want.
Related
I have an ImageView with the background set to a drawable.circle. The circle has thick stroke width. I would like to animate that stroke width to shrink from what it is set at to 1dp over a specified duration. If this can't be done with a drawable, I also have a customView that path's a circle with a paint.style set to Stroke. I would like to apply that animation to either the drawable.circle or the customView.
CustomCirleView:
public class CustomCircle extends View {
private Path path;
private Paint paint;
float customStrokeWidth = 80;
public float getCustomStrokeWidth() {
return customStrokeWidth;
}
public void setCustomStrokeWidth(float customStrokeWidth) {
this.customStrokeWidth = customStrokeWidth;
}
public CustomCircle(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
path = new Path();
paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setAntiAlias(true);
paint.setColor(Color.parseColor("#FC6C2B"));
paint.setStrokeWidth(customStrokeWidth);
path.addCircle(getMeasuredWidth()/2, getMeasuredHeight()/2, (getMeasuredWidth()/2)-customStrokeWidth, Path.Direction.CW);
canvas.drawPath(path, paint);
}
}
Thanks
I would do something like this and then just draw the circle in your onDraw method. And please never do all the paint initialization inside the onDraw method as it always takes some time and the onDraw method should do as less as possible
private void init() {
animator = ObjectAnimator.ofFloat(this, "animationProgress", startVal, endVal);
animator.setStartDelay(ANIMATION_START_DELAY);
animator.setDuration(ANIMATION_DURATION);
animator.setInterpolator(new FastOutSlowInInterpolator());
path = new Path();
paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setAntiAlias(true);
paint.setColor(Color.parseColor("#FC6C2B"));
paint.setStrokeWidth(customStrokeWidth);
path.addCircle(getMeasuredWidth()/2, getMeasuredHeight()/2, (getMeasuredWidth()/2)-customStrokeWidth, Path.Direction.CW);
}
/**
* Is called by the {#link #animator} after an animation update
*/
protected void setAnimationProgress(float strokeWidth) {
this.strokeWidth = strokeWidth;
postInvalidateOnAnimation();
}
fixed size circle aniamtion problem
hello there , i have this class :
public circle (Context context, AttributeSet attrs) {
super(context, attrs);
final int strokeWidth = 30;
paint = new Paint();
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(strokeWidth);
//Circle color
paint.setColor(Color.YELLOW);
//size 200x200 example
rect = new RectF(strokeWidth, strokeWidth, 350 + strokeWidth, 350 +
strokeWidth);
//Initial Angle (optional, it can be zero)
angle = 0;
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawArc(rect, START_ANGLE_POINT, angle, false, paint);
}
public float getAngle() {
return angle;
}
public void setAngle(float angle) {
this.angle = angle;
}
}
and this class is responsible for animation draw circle
the animation class is :
public class CircleAngleAnimation extends Animation {
private circle circle;
private float oldAngle;
private float newAngle;
public CircleAngleAnimation(circle circle, int newAngle) {
this.oldAngle = circle.getAngle();
this.newAngle = newAngle;
this.circle = circle;
}
#Override
protected void applyTransformation(float interpolatedTime, Transformation
transformation) {
float angle = oldAngle + ((newAngle - oldAngle) * interpolatedTime);
circle.setAngle(angle);
circle.requestLayout();
}
}
i attached xml value in my mainactivity.xml to the circle class like this :
<com.mynetwork.zaidkhaled.speech.circle
android:id="#+id/circle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:gravity="center_horizontal"
/>
in mainactivity i set animation = new CircleAngleAnimation(circle, 360); animation.setDuration(1000); then i call start animation by circle.startanimation(animation);
now my problem is when this circle is drawn in the activity , if the screen resolution is high it will be drawn perfectly , perfect sized , if the screen resolution is low it will be drawn very very big , how can set this cricle to be drawn in the same size on every mobile device ?
thanks for help :)
How can I make move in coordinates Y, a canvas.drawCircle?
I want to make the sensation like the circle fall where I touch on the screen but I don't know how to animate it.
My onDraw:
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
int x = getWidth();
int y = getHeight();
anchoX = x;
anchoY = y;
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.BLUE);
canvas.drawPaint(paint);
/*Texto*/
paint.setColor(Color.BLACK);
paint.setTextSize(80);
canvas.drawText("CONECTA 4", 70, 130, paint);
/*Separador*/
paint.setColor(Color.parseColor("#5C5C5C"));
canvas.drawRect(0, 200, 600, 210, paint);
/*Tablero*/
int radius = 25;
for (int i = 0; i < Game.NFILAS; i++)
for (int j = 0; j < Game.NCOLUMNAS; j++){
if (game.estaVacio(i,j)){
color = Color.WHITE;
paint.setColor(color);
canvas.drawCircle(getPixelFromColumna(j), getPixelFromFila(i), radius, paint);
} else if (game.estaJugador(i,j)){
paint.setColor(coloreado);
canvas.drawCircle(getPixelFromColumna(j), getPixelFromFila(i), radius, paint);
} else {
color = Color.RED;
paint.setColor(color);
canvas.drawCircle(getPixelFromColumna(j),getPixelFromFila(i), radius, paint);
}
}
}
you can check this answer. This is what you were looking for draw a circle with animation
For creating the circle you can you java file like this
public class Circle extends View {
private static final int START_ANGLE_POINT = 90;
private final Paint paint;
private final RectF rect;
private float angle;
public Circle(Context context, AttributeSet attrs) {
super(context, attrs);
final int strokeWidth = 40;
paint = new Paint();
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(strokeWidth);
//Circle color
paint.setColor(Color.RED);
//size 200x200 example
rect = new RectF(strokeWidth, strokeWidth, 200 + strokeWidth, 200 + strokeWidth);
//Initial Angle (optional, it can be zero)
angle = 120;
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawArc(rect, START_ANGLE_POINT, angle, false, paint);
}
public float getAngle() {
return angle;
}
public void setAngle(float angle) {
this.angle = angle;
}
}
and for creating animation
public class CircleAngleAnimation extends Animation {
private Circle circle;
private float oldAngle;
private float newAngle;
public CircleAngleAnimation(Circle circle, int newAngle) {
this.oldAngle = circle.getAngle();
this.newAngle = newAngle;
this.circle = circle;
}
#Override
protected void applyTransformation(float interpolatedTime, Transformation transformation) {
float angle = oldAngle + ((newAngle - oldAngle) * interpolatedTime);
circle.setAngle(angle);
circle.requestLayout();
}
}
and you can use like this in xml for defining
<com.package.Circle
android:id="#+id/circle"
android:layout_width="300dp"
android:layout_height="300dp" />
Animate you circle by using this sample code
Circle circle = (Circle) findViewById(R.id.circle);
CircleAngleAnimation animation = new CircleAngleAnimation(circle, 240);
animation.setDuration(1000);
circle.startAnimation(animation);
Requirement is to:
Req 1 : Fetch images from url
R2: save them in cache
R3: make ImageView rounded not the image
So for R1 & R2 I found a library:
http://loopj.com/android-smart-image-view/
For R3 I've done a lot of R&D , & everything I found converts the image not the ImageView. This is what I've searched:
Mask ImageView with round corner background
How to make an ImageView with rounded corners?
https://github.com/vinc3m1/RoundedImageView
https://github.com/lopspower/CircularImageView
I know it's possible to use the ImageView bitmap & get the image rounded but with the specific library I want to use that isn't possible(maybe possible with very complex threading).
So please help me to get the ImageView rounded not the image.
so this is the minimalistic version:
class RoundImageView extends ImageView {
private static final int RADIUS = 32;
private Paint mPaint;
private Paint mSrcIn;
private RectF mRect;
public RoundImageView(Context context) {
super(context);
// setBackgroundColor(0xffffffff);
mSrcIn = new Paint();
mSrcIn.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mRect = new RectF();
}
#Override
public void onDraw(Canvas canvas) {
Drawable dr = getDrawable();
if (dr != null) {
mRect.set(dr.getBounds());
getImageMatrix().mapRect(mRect);
mRect.offset(getPaddingLeft(), getPaddingTop());
int rtc = canvas.saveLayer(mRect, null, Canvas.ALL_SAVE_FLAG);
// draw DST
canvas.drawRoundRect(mRect, RADIUS, RADIUS, mPaint);
canvas.saveLayer(mRect, mSrcIn, Canvas.ALL_SAVE_FLAG);
// draw SRC
super.onDraw(canvas);
canvas.restoreToCount(rtc);
}
}
}
or use even shorter one when hardware acceleration is not used and you can use Canvas.clipPath:
class RoundImageViewClipped extends ImageView {
private static final int RADIUS = 32;
private RectF mRect;
private Path mClip;
public RoundImageViewClipped(Context context) {
super(context);
// setBackgroundColor(0xffffffff);
mRect = new RectF();
mClip = new Path();
}
#Override
public void onDraw(Canvas canvas) {
Drawable dr = getDrawable();
if (dr != null) {
mRect.set(dr.getBounds());
getImageMatrix().mapRect(mRect);
mRect.offset(getPaddingLeft(), getPaddingTop());
mClip.reset();
mClip.addRoundRect(mRect, RADIUS, RADIUS, Direction.CCW);
canvas.clipPath(mClip);
super.onDraw(canvas);
}
}
}
I'm pretty sure you can't "make the ImageView round," since all Views are actually rectangular, so what you're going to have to do is fake it.
Use a method like this to cut a circle from the image:
public Bitmap getRoundedBitmap(Bitmap scaleBitmapImage) {
int targetRadius = scaleBitmapImage.getWidth();
if(targetRadius > scaleBitmapImage.getHeight()) targetRadius = scaleBitmapImage.getHeight();
Bitmap targetBitmap = Bitmap.createBitmap(targetRadius, targetRadius, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(targetBitmap);
Path path = new Path();
path.addCircle(((float) scaleBitmapImage.getWidth() - 1) / 2, ((float) scaleBitmapImage.getHeight() - 1) / 2, (Math.min(((float) scaleBitmapImage.getWidth()), ((float) scaleBitmapImage.getHeight())) / 2), Path.Direction.CCW);
canvas.clipPath(path);
Bitmap sourceBitmap = scaleBitmapImage;
canvas.drawBitmap(sourceBitmap, new Rect(0, 0, sourceBitmap.getWidth(), sourceBitmap.getHeight()), new Rect(0, 0, scaleBitmapImage.getWidth(), scaleBitmapImage.getHeight()), null);
return targetBitmap;
}
Since the clipped part is transparent, it will appear as if the actual View is a circle. Also make sure that the bounds of the View are squared (or that adjustViewBounds="true") else you may get visual distortions in terms of width or height.
Pretty sure that's as close to a "rounded View" as you can actually get.
How about the solution give by Romain Guy to use a custom Drawable. You're ImageView will not be round and your source image will be untouched.
class StreamDrawable extends Drawable {
private final float mCornerRadius;
private final RectF mRect = new RectF();
private final BitmapShader mBitmapShader;
private final Paint mPaint;
private final int mMargin;
StreamDrawable(Bitmap bitmap, float cornerRadius, int margin) {
mCornerRadius = cornerRadius;
mBitmapShader = new BitmapShader(bitmap,
Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setShader(mBitmapShader);
mMargin = margin;
}
#Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
mRect.set(mMargin, mMargin, bounds.width() - mMargin, bounds.height() - mMargin);
}
#Override
public void draw(Canvas canvas) {
canvas.drawRoundRect(mRect, mCornerRadius, mCornerRadius, mPaint);
}
#Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
#Override
public void setAlpha(int alpha) {
mPaint.setAlpha(alpha);
}
#Override
public void setColorFilter(ColorFilter cf) {
mPaint.setColorFilter(cf);
}
}
You can add rounded corners in a android view with the GradientDrawable.
So ,
GradientDrawable gd = new GradientDrawable();
gd.setColor(Color.TRANSPARENT);
gd.setCornerRadius(15f);
gd.setStroke(1f,Color.BLACK);
yourImageView.setBackground(gd);
SmartImageView extends from ImageView .. so you just have to extend from SmartImageView
Here is a working solution (based on pskink code & smartImageView lib )
Create a new Class
public class RoundedCornersSmartImageView extends SmartImageView{
private int RADIUS = 0;
private RectF mRect;
private Path mClip;
public RoundedCornersSmartImageView(Context context) {
super(context);
init();
}
public RoundedCornersSmartImageView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public RoundedCornersSmartImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
#Override
public void onDraw(Canvas canvas) {
Drawable dr = getDrawable();
if (dr != null) {
mRect.set(dr.getBounds());
getImageMatrix().mapRect(mRect);
mRect.offset(getPaddingLeft(), getPaddingTop());
mClip.reset();
mClip.addRoundRect(mRect, RADIUS, RADIUS, Path.Direction.CCW);
canvas.clipPath(mClip);
super.onDraw(canvas);
}
}
public void setRadius(int radius){
this.RADIUS = radius;
}
private void init(){
mRect = new RectF();
mClip = new Path();
}
}
USAGE
in your layout file your SmartimageView should look like this
<your.package.path.RoundedCornersSmartImageView
android:id="#+id/list_image"
android:layout_width="60dip"
android:layout_height="60dip"
android:src="#drawable/profile_anonyme_thumb"/>
..and init the view in your code this way
RoundedCornersSmartImageView thumb_image=(RoundedCornersSmartImageView) findViewById(R.id.list_image);
thumb_image.setRadius(4);
//SmartImageView methode
thumb_image.setImageUrl(bla.MY_THUMB_URL));
Edit your radius for a round image ..
I am trying to redraw the custom view in onCreate() method
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
circleView = (CircleView)findViewById(R.id.circleView);
circleView.setCircle(100, 100, 25);
circleView.wrapView();
}
and custom view is :
public class CircleView extends View
{
private Paint paint = null;
private int x = 50;
private int y = 50;
private int radius = 50;
public CircleView(Context context, AttributeSet attrs)
{
super(context, attrs);
init();
}
public CircleView(Context context)
{
super(context);
init();
}
private void init()
{
paint = new Paint();
}
public void setCircle(int x, int y, int radius)
{
this.x = x;
this.y = y;
this.radius = radius;
init();
this.invalidate();
}
#Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
paint.setColor(Color.WHITE);
canvas.drawCircle(x, y, radius, paint);
Log.e("", "radius : " + radius);
}
public void setColor(int color)
{
paint.setColor(color);
}
public void wrapView()
{
this.setLayoutParams(new RelativeLayout.LayoutParams(radius*2, radius*2));
this.invalidate();
}
}
and xml is:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/layoutMain"
>
<com.pep1439.view.CircleView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/circleView" />
</RelativeLayout>
i just want to resize the circle, but failed. Help me to draw circle with any radius. How to do this. Its working fine if i use default values. It draws the circle when i remove the line circleView.setCircle(100, 100, 25);. I want to adjust circle at run time.
thanks.
You set x and y to 100 and radius to 25. Then you resize your view to radius*2, which is 50, so in the end you're drawing a circle of radius 25 at position 100,100 on a view that is only 50x50 in size. In other words: You draw your circle outside the area of your view.