How to make border more smooth - android

I want to add border for view, border width, color, radius can be set by user. So I try to draw a rect for it. When I use drawRoundRect to draw, the line at the corner is not smooth, it is thicker than the other places too. I don't know how to fix it. Please give me some instruction. Is there any other way to do it? I have to use code to draw it.
Thanks very much.
attached code: red corner of rect.
past code:
public class MPCTextView extends TextView {
// private Context context;
private final static String TAG = "MPCTextView";
public final static int DEFAULT_BACKGROUND_COLOR = Color
.parseColor("#28FF28");
public final static int DEFAULT_BORDER_COLOR = Color.parseColor("#FF0000");
public int mBoderWidth = 2;
public int mBoderColor;
public int mBoderRadius = 20;
public int mbackgroundColor;
public boolean isHaveBorder = true;
public boolean isHaveBackground = true;
RectF mRectF = new RectF();
Rect mRec = new Rect();
Paint mPaint = new Paint();
public MPCTextView(Context context) {
super(context);
// this.context = context;
}
#Override
protected void onDraw(Canvas canvas) {
// try to add a boder for this view.
canvas.getClipBounds(mRec);
// draw background
// canvas.drawColor(mbackgroundColor);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(DEFAULT_BACKGROUND_COLOR);
if (mBoderRadius > 0) {
mRectF.set(mRec);
canvas.drawRoundRect(mRectF, mBoderRadius, mBoderRadius, mPaint);
} else {
canvas.drawRect(mRec, mPaint);
}
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(mBoderWidth);
mPaint.setColor(DEFAULT_BORDER_COLOR);
mPaint.setAntiAlias(true);
if (mBoderRadius > 0) {
mRectF.set(mRec);
canvas.drawRoundRect(mRectF, mBoderRadius, mBoderRadius, mPaint);
} else {
canvas.drawRect(mRec, mPaint);
}
super.onDraw(canvas);
}

The core of the problem is the padding, not AntiAliasing. The corner is not thicker, rather, it is the normal width. But, the straight line is clipped.
If you set the stroke width to 2, the really straight line width is 1 because the stroke is rectangular and the axis is the line x = 0. This means the rectangle is (left=0,up=-1,right=length,bottom=1), but the up -1 is outside of the canvas, so it will not be painted. And the corner is full width, because it is in the canvas.
So, you just to need set the padding.
Here is the code to make the rounded rect draw completely inside the canvas:
float pad = 1f;
mRectF.set(new RectF(mRec.left + pad, mRec.top + pad, mRec.right - pad, mRec.bottom - pad));
canvas.drawRoundRect(mRectF, mBoderRadius, mBoderRadius, mPaint);

Set the antialias to the paint you are using to draw the red rectangle . For instance
mPaint.setAntiAlias(true);

I want this code to be help you.
public int mBoderWidth = 2;
public int mBoderColor;
public int mBoderRadius = 20;
public int mbackgroundColor;
public boolean isHaveBorder = true;
public boolean isHaveBackground = true;
RectF mRectF = new RectF();
Rect mRec = new Rect();
Paint mPaint = new Paint();
public MPCTextView(Context context) {
super(context);
// this.context = context;
}
#Override
protected void onDraw(Canvas canvas) {
// try to add a boder for this view.
canvas.getClipBounds(mRec);
// draw background
// canvas.drawColor(mbackgroundColor);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(DEFAULT_BACKGROUND_COLOR);
if (mBoderRadius > 0) {
mRectF.set(mRec);
canvas.drawRoundRect(mRectF, mBoderRadius, mBoderRadius, mPaint);
} else {
canvas.drawRect(mRec, mPaint);
}
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(mBoderWidth);
mPaint.setColor(DEFAULT_BORDER_COLOR);
mPaint.setAntiAlias(true);
if (mBoderRadius > 0) {
mRectF.set(mRec);
///////////// look at this code
mRectF.left += mBorderWidth/2;
mRectF.right -= mBorderWidth/2;
mRectF.top += mBorderWidth/2;
mRectF.bottom -= mBorderWidth/2;
canvas.drawRoundRect(mRectF, mBoderRadius, mBoderRadius, mPaint);
mRectF.left -= mBorderWidth/2;
mRectF.right += mBorderWidth/2;
mRectF.top -= mBorderWidth/2;
mRectF.bottom += mBorderWidth/2;
} else {
canvas.drawRect(mRec, mPaint);
}
super.onDraw(canvas);
}

I know I am answering this question very late but it may help others modify your code like below will work
Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

Related

How to add a imageView in the centre of a customView?

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.

children line number android

I wanna to do line number for children app
The line should look like the following
I think to use seekbar but I found it not possible as a range, not static also need to do an action when the user touches each number. so I ask for help or suggestion.
also has to do functionality of drawing an arc
the arc has to be drawn dynamically while the user moves his finger on numbers
also draw a rectangle when touching any number.
I'd like to ask for any advice or help in implementing something like that.
edit1: the line used to solve an equation as in the third image
You can use Custom View (Custom Drawing) which can help you in drawing the shaps check the link hope it helpscustom-views android-developers
There's probably a much better way to do this but here's what I came up with, hope its enough to point you in the right direction:
Activity:
public class DrawActivity extends AppCompatActivity {
float startPointX = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_draw);
MyDrawable drawing = new MyDrawable(this);
setContentView(drawing);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
MyDrawable drawing = new MyDrawable(this);
if (event.getY() > 1000) { // Click below line to reset
startPointX = 0;
} else if (startPointX == 0) { // Draw rectangle
startPointX = event.getX();
drawing = new MyDrawable(this, startPointX);
} else if (startPointX > 0) { // Draw arc
drawing = new MyDrawable(this, startPointX, event.getX());
}
setContentView(drawing);
return true;
}
}
Drawable:
public class MyDrawable extends View {
private Canvas mCanvas;
private Paint mRedPaint;
private Paint mGreenPaint;
private Paint mBluePaint;
float baseLine = 500;
float rectangleX;
float arcEnd;
public MyDrawable(Context context) {
super(context);
}
public MyDrawable(Context context, float startPoint) {
super(context);
rectangleX = startPoint;
}
public MyDrawable(Context context, float startPoint, float endPoint) {
super(context);
rectangleX = startPoint;
arcEnd = endPoint;
}
#Override
public void onDraw(Canvas canvas) {
mCanvas = canvas;
int width = 1000;
setupPaint();
canvas.drawLine(50, baseLine, width, baseLine, mBluePaint);
int mark = 50;
while(mark < width) {
canvas.drawLine(mark, baseLine-50, mark, baseLine+50, mGreenPaint);
mark += (width /10);
}
drawRectangle();
drawArc();
}
private void setupPaint() {
mRedPaint = new Paint();
mRedPaint.setARGB(255, 180, 0, 0);
mRedPaint.setStyle(Paint.Style.STROKE);
mRedPaint.setStrokeWidth(15);
mGreenPaint = new Paint();
mGreenPaint.setARGB(255, 0, 180, 0);
mGreenPaint.setStrokeWidth(15);
mBluePaint = new Paint();
mBluePaint.setARGB(255, 0, 0, 180);
mBluePaint.setStrokeWidth(30);
}
public void drawRectangle() {
if ( rectangleX > 0) {
mCanvas.drawRect(rectangleX - 25, baseLine-50, rectangleX + 25, baseLine+50, mRedPaint);
}
}
public void drawArc() {
if (arcEnd != 0 && arcEnd < rectangleX) {
mCanvas.drawArc(arcEnd, baseLine-200, rectangleX, baseLine, 0, -180, false, mRedPaint);
} else if (arcEnd != 0 && arcEnd > rectangleX) {
mCanvas.drawArc(rectangleX, baseLine-200, arcEnd, baseLine, 0, -180, false, mRedPaint);
}
}
}

Custom view doesn't draw Bitmap

I´m trying to display a moving cloud over a blue sky. The blue background is displayed but the cloud doesn't appear. I've tried the different approaches in other questions here but nothing works. My code is:
public class CloudBackground extends View {
Bitmap cloud;
int x = 0;
int y = 0;
Paint paint = new Paint();
Rect rectangle = new Rect(0,0,100,100);
public CloudBackground(Context context,AttributeSet attrs) {
super(context,attrs);
cloud = BitmapFactory.decodeResource(getResources(),R.drawable.cloud1);
}
#Override
protected void onDraw (Canvas canvas){
super.onDraw(canvas);
Rect back = new Rect();
back.set(0,0,canvas.getWidth(), canvas.getHeight());
Paint pBlue = new Paint();
pBlue.setStyle(Paint.Style.FILL);
pBlue.setColor(Color.CYAN);
canvas.drawRect(back, pBlue);
drawCloud(x,y,canvas);
if (x < canvas.getWidth())
x = x + 10;
else {
y = y + 10;
x = 0;
}
invalidate();
}
private void drawCloud(int x2, int y2, Canvas canvas) {
canvas.drawBitmap(cloud, x2, y2,paint);
}
Ok. Try this:
public CloudBackground(Context context,AttributeSet attrs) {
super(context,attrs);
cloud = BitmapFactory.decodeResource(context.getApplicationContext().getResources(),R.drawable.cloud1);
}
The issue was finally solved using a.jpg instead a .png. As simple as that and with no reason.

Animate canvas.drawCircle

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);

Make Image view rounded (not the image)

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

Categories

Resources