problems with Android FrameLayout when override onDraw - android

protected void onDraw(Canvas canvas) {
float width = canvas.getWidth();
float height = canvas.getHeight();
Path path = new Path();
path.addArc(new RectF(0, 0, width, height), 90, 180);
canvas.clipPath(path);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.RED);
canvas.drawRect(new RectF(0, 0, width, height), paint);
}
I use this code to override other views; it's ok(show a semicircle);
but when I use this to override FrameLayout, show me a rectangle?!
Why?
How can I modify it?

Related

Android - Cut circle and create separate Bitmap from existing one

I have onDraw method where I want to cut a small piece of large bitmap. This will be a circle (position X and Y). Then I want to draw it by canvas.
I rewrite method from this answer for that reason, but always got grey circle instead circle piece of large Bitmap.
private Bitmap cutCircleBitmap() {
Bitmap output = Bitmap.createBitmap(2 * RADIUS, 2 * RADIUS, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = 0xff424242;
final Paint paint = new Paint();
final Rect rect = new Rect(bitmapX - RADIUS, bitmapY - RADIUS, 2 * RADIUS, 2 * RADIUS);
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawCircle(RADIUS, RADIUS, RADIUS, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
}
Use Canvas.drawRoundRect() and BitmapShader to do it :
public class CropView extends View {
public CropView(Context context) {
this(context, null);
}
public CropView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CropView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setFilterBitmap(true);
mPaint.setAntiAlias(true);
mPaint.setDither(true);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(radius * 2, radius * 2);
}
private Paint mPaint;
private int radius = 100;
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.BLACK); // draw background help us see the result
Bitmap srcBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.sample);
canvas.drawBitmap(cropCircleBitmap(srcBitmap, 200, 60), 0, 0, mPaint);
}
private Bitmap cropCircleBitmap(Bitmap srcBitmap, float left, float top) {
Bitmap dstBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(dstBitmap);
canvas.drawBitmap(srcBitmap, -left, -top, mPaint);
mPaint.setShader(new BitmapShader(dstBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
dstBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
canvas.setBitmap(dstBitmap);
canvas.drawRoundRect(new RectF(0, 0, getWidth(), getHeight()), radius, radius, mPaint);
return dstBitmap;
}
}

Set gradient to Canvas.drawtext

I'm an android developer. i'm working on a game and i need to change my letters style as below picture. How to add gradient in canvas as in the picture
this code add gradient but to whole view. if letters at bottom they are white if letters at top they are black
Paint p = new Paint();
// start at 0,0 and go to 0,max to use a vertical
// gradient the full height of the screen.
p.setShader(new LinearGradient(0, 0, 0, getHeight(), Color.BLACK, Color.WHITE, Shader.TileMode.MIRROR));
canvas.drawPaint(p);
try something like this:
class V extends View {
private String text = "Back To The Future";
private Paint paint;
public V(Context context) {
super(context);
paint = new Paint();
paint.setTextSize(32);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
Rect bounds = new Rect();
paint.getTextBounds(text, 0, text.length(), bounds);
Shader shader = new LinearGradient(0, paint.getTextSize() + bounds.top, 0, paint.getTextSize(), Color.RED, Color.YELLOW, TileMode.MIRROR);
paint.setShader(shader);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawText(text, 0, paint.getTextSize(), paint);
}
}

Rotate Text in Canvas

How do you rotate text that is in the canvas? I need to flip the text I have upside down.
paint.setTextSize(20);
canvas.drawText("3AM", xStored, yStored, paint);
refer this link
int x = 75;
int y = 185;
paint.setColor(Color.GRAY);
paint.setTextSize(25);
String rotatedtext = "Rotated helloandroid :)";
//Draw bounding rect before rotating text:
Rect rect = new Rect();
paint.getTextBounds(rotatedtext, 0, rotatedtext.length(), rect);
canvas.translate(x, y);
paint.setStyle(Paint.Style.FILL);
canvas.drawText(rotatedtext , 0, 0, paint);
paint.setStyle(Paint.Style.STROKE);
canvas.drawRect(rect, paint);
canvas.translate(-x, -y);
paint.setColor(Color.RED);
canvas.rotate(-45, x + rect.exactCenterX(),y + rect.exactCenterY());
paint.setStyle(Paint.Style.FILL);
canvas.drawText(rotatedtext, x, y, paint);
I got the solution from the comment by Romain Guy below the accepted answer
How can you display upside down text with a textview in Android?
Quoting You can just scale by -1 on the Y axis.
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int cx = this.getMeasuredWidth() / 2;
int cy = this.getMeasuredHeight() / 2;
canvas.scale(1f, -1f, cx, cy);
canvas.drawText("3AM", cx, cy, p);
}
Complete Example:
public class SView extends View {
Paint p,paint;
public SView(Context context) {
super(context);
// TODO Auto-generated constructor stub
p = new Paint();
p.setColor(Color.RED);
p.setTextSize(40);
paint = new Paint();
paint.setColor(Color.BLUE);
paint.setTextSize(40);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int cx = this.getMeasuredWidth() / 2;
int cy = this.getMeasuredHeight() / 2;
canvas.drawText("3AM", cx, cy, paint);
canvas.save();
canvas.scale(1f, -1f, cx, cy);
canvas.drawText("3AM", cx, cy, p);
canvas.restore();
}
}
Snap
You need to rotate the canvas prior to the drawText() call:
canvas.save(); // save the current state of the canvas
canvas.rotate(180.0f); //rotates 180 degrees
canvas.drawText("3AM", xStored, yStored, paint);
canvas.restore(); //return to 0 degree
**EDIT - That will only invert it but it will be back-to-front. You actually need to mirror on the text-basline, assuming that is what you meant.

How do I draw a partial bitmap-arc? Like a circular progress wheel, but with a bitmap that gets more and more displayed.

What I am searching for, is a view that reveals an image in a clockwise circular fashion. When the progress is 25% the first 90 degrees should be revealed and when its 100% the full 360 degrees should be drawn.
It is very close to using the canvas.drawArc(), but this method only works with Paint objects, not bitmaps.
Other answers also only work with full colors:
How To Make Circle Custom Progress Bar in Android
I have found it to be a very hard problem, I hope someone has a solution.
tre this:
public class MyView extends View {
private Bitmap mBitmap;
private Paint mPaint;
private RectF mOval;
private float mAngle = 135;
private Paint mTextPaint;
public MyView(Context context) {
super(context);
// use your bitmap insted of R.drawable.ic_launcher
mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mOval = new RectF();
mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mTextPaint.setTextSize(48);
mTextPaint.setTextAlign(Align.CENTER);
mTextPaint.setColor(0xffffaa00);
mTextPaint.setTypeface(Typeface.DEFAULT_BOLD);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
Matrix m = new Matrix();
RectF src = new RectF(0, 0, mBitmap.getWidth(), mBitmap.getHeight());
RectF dst = new RectF(0, 0, w, h);
m.setRectToRect(src, dst, ScaleToFit.CENTER);
Shader shader = new BitmapShader(mBitmap, TileMode.CLAMP, TileMode.CLAMP);
shader.setLocalMatrix(m);
mPaint.setShader(shader);
m.mapRect(mOval, src);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(0xff0000aa);
canvas.drawArc(mOval, -90, mAngle, true, mPaint);
canvas.drawText("click me", getWidth() / 2, getHeight() / 2, mTextPaint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float w2 = getWidth() / 2f;
float h2 = getHeight() / 2f;
mAngle = (float) Math.toDegrees(Math.atan2(event.getY() - h2, event.getX() - w2));
mAngle += 90 + 360;
mAngle %= 360;
invalidate();
return true;
}
}

EditText with custom background using onDraw

I am trying to have a custom EditText with a custom background which is not possible to draw using drawable XMLs
Here is what I have right now
public class EMEditText extends EditText {
private Bitmap framedBitmap;
public EMEditText(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
#Override
protected void onDraw(Canvas canvas) {
if(framedBitmap == null) {
createDrawable(getWidth(), getHeight());
}
Paint paint = new Paint();
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
// canvas.drawBitmap(framedBitmap, 0, 0, paint);
}
private void createDrawable(int width, int height) {
// create a new bitmap of given size
Bitmap start = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(start);
RectF outerRect = new RectF(0, 0, width, height);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.WHITE);
// paint.setStrokeWidth(1);
// paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT));
canvas.drawRoundRect(outerRect, height / 2, height / 2, paint);
framedBitmap = start;
}
}
What is probably wrong in your code is that you are creating your own Canvas object in createDrawable() method though onDraw() method gives you the right Canvas which you should use for your drawings.
So what you probably want is to change createDrawable(int width, int height) method to createDrawable(int width, int height, Canvas c). Your code should look like this then:
#Override
protected void onDraw(Canvas canvas) {
if(framedBitmap == null) {
createDrawable(getWidth(), getHeight(), canvas);
}
Paint paint = new Paint();
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
// canvas.drawBitmap(framedBitmap, 0, 0, paint);
}
private void createDrawable(int width, int height, Canvas c) {
// create a new bitmap of given size
Bitmap start = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
c.setBitmap(start);
RectF outerRect = new RectF(0, 0, width, height);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.WHITE);
// paint.setStrokeWidth(1);
// paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT));
c.drawRoundRect(outerRect, height / 2, height / 2, paint);
framedBitmap = start;
}
As you can see, I changed also the body of your createDrawable() method so that it uses Canvas from onDraw() and sets it's Bitmap to the one created by you.

Categories

Resources