Android CustomView behave abnormal - android

I am creating an application, in which a camera is showing with an option on screen to hide and show grids on the screen. I created this grid by CustomView and it was working fine. but when I hide the grid and click show then horizontal lines are not showing... please help...
custom view
<com.***.GridLinesView
android:id="#+id/cameraView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true" />
OnClick Hide/Unhide Button
#Override
public void onClick(View v) {
// get an image from the camera
View grid = (View)findViewById(R.id.cameraView1);
if(grid.getVisibility() == View.VISIBLE)
grid.setVisibility(View.INVISIBLE);
else
grid.setVisibility(View.VISIBLE);
}
Custom View
public class GridLinesView extends View {
private Paint p;
int width = 0;
int height = 0;
int pass = 0;
int xpos = 0;
int ypos = 0;
public GridLinesView(Context context) {
super(context);
// TODO Auto-generated constructor stub
p = new Paint();
p.setColor(Color.WHITE);
p.setStyle(Paint.Style.STROKE);
p.setStrokeWidth(1);
p.setAntiAlias(true);
}
public GridLinesView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
p = new Paint();
p.setColor(Color.WHITE);
p.setStyle(Paint.Style.STROKE);
p.setStrokeWidth(1);
p.setAntiAlias(true);
}
public GridLinesView(Context context, AttributeSet attrs) {
super(context, attrs);
p = new Paint();
p.setColor(Color.WHITE);
p.setStyle(Paint.Style.STROKE);
p.setStrokeWidth(1);
p.setAntiAlias(true);
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
width = getWidth();
height = getHeight();
int ratio = 5;
if(width < 300 || height < 300){
ratio = 3;
}
xpos = width / ratio;
ypos = height / ratio;
p.setStyle(Style.STROKE);
for (int i = 0; i < ratio; i++) {
p.setColor(Color.argb(100, 255, 255, 255));
canvas.drawLine(0, (ypos * pass) + ratio, width, (ypos * pass) + ratio, p);
pass++;
}
for (int i = 0; i < ratio; i++) {
p.setColor(Color.argb(100, 255, 255, 255));
canvas.drawLine(xpos + (xpos * i), 0, xpos + (xpos * i), height, p);
}
}
}
Any help will be appreciable... Thank you.

Related

How to bring canvas on top of other views

I am using magnifier view for my application which is a library I got from here :
https://github.com/nomanr/android-image-magnifier
I have modified this class to extend FrameLayout (It was ImageView before) to work on my FrameLayout.
It's working well except the painted canvas view stays back of all the views which are added in that custom view.
How to bring that canvas on front of those added views?
Custom view class that i am using :
public class ImageMagnifier extends FrameLayout {
private PointF zoomPos;
private boolean zooming = false;
private Matrix matrix;
private Paint paint;
private Bitmap bitmap;
private BitmapShader shader;
private int sizeOfMagnifier = 300;
int cheight, cwidth;
Context con;
C c = C.getInstance();
public ImageMagnifier(Context context) {
super(context);
init();
con=context;
}
public ImageMagnifier(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
con=context;
}
public ImageMagnifier(Context context, AttributeSet attrs) {
super(context, attrs);
init();
con=context;
}
private void init() {
zoomPos = new PointF(0, 0);
matrix = new Matrix();
paint = new Paint();
cwidth = c.Width * 109 / 1280;
cheight = cwidth * 134 / 109;
}
public void otherTouch(int x, int y) {
if (x > c.getwidth1(28) && x < c.getwidth1(921) && y > c.getheight1(135) && y < c.getheight1(560)) {
zoomPos.x = x - 10;
zoomPos.y = y - 75;
zooming = true;
this.invalidate();
} else {
RemoveMagnifire();
}
}
public void RemoveMagnifire() {
zooming = false;
this.invalidate();
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (!zooming) {
buildDrawingCache();
} else {
bitmap = getDrawingCache();
shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP,Shader.TileMode.CLAMP);
paint.setShader(shader);
matrix.reset();
matrix.postScale(2f, 2f, zoomPos.x-10, zoomPos.y+60);
paint.getShader().setLocalMatrix(matrix);
int width = c.Width;
int height = c.Height;
float leftX = zoomPos.x - ((width * 100) / 1280);
float topY = zoomPos.y - ((height * 250) / 720);
float rightX = zoomPos.x + ((width * 100) / 1280);
float bottomY = zoomPos.y - ((height * 100) / 720);
canvas.drawRect(leftX , topY, rightX, bottomY, paint);
}
}
}
A ViewGroup draws its child Views in the dispatchDraw() method. We just need to move the magnifier drawing to after that happens.
The fix is simple. Move everything after the super call in onDraw() to after the super call in dispatchDraw().
...
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// Removed
}
#Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
if (!zooming) {
buildDrawingCache();
}
else {
bitmap = getDrawingCache();
shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
paint.setShader(shader);
matrix.reset();
matrix.postScale(2f, 2f, zoomPos.x - 10, zoomPos.y + 60);
paint.getShader().setLocalMatrix(matrix);
int width = c.Width;
int height = c.Height;
float leftX = zoomPos.x - ((width * 100) / 1280);
float topY = zoomPos.y - ((height * 250) / 720);
float rightX = zoomPos.x + ((width * 100) / 1280);
float bottomY = zoomPos.y - ((height * 100) / 720);
canvas.drawRect(leftX , topY, rightX, bottomY, paint);
}
}
...
You can just remove the onDraw() override, if you no longer need it for anything else.

Custom Progress as Step - Android

I need to make something like this:
I'd try to draw this using Canvas.drawArc(...) but I failed.
Can anyone help me?
I created a view that can draw the shape that you want.
It starts by creating a path for one of the quarters, and rotating the canvas by 90 degrees to draw the path 4 times. The Paint used to draw the Path is determined by the progress / maxProgress.
I used a second path to denote the region of the canvas to clip out when drawing, so that there are empty spaces between the quarters.
Finally, the text can be drawn in the middle after restoring the canvas rotation and clipping.
public class CustomProgressView extends View {
private int progress;
private int maxProgress;
private float arcWidth;
private float arcPadding;
private Paint paintPositive;
private Paint paintNegative;
private Paint paintText;
private Path path;
private Path clipPath;
private ProgressListener listener;
public CustomProgressView(Context context) {
super(context);
init();
}
public CustomProgressView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public CustomProgressView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
arcWidth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 25, getResources().getDisplayMetrics());
arcPadding = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 6, getResources().getDisplayMetrics());
paintPositive = new Paint();
paintPositive.setColor(Color.RED);
paintPositive.setStyle(Paint.Style.FILL_AND_STROKE);
paintPositive.setAntiAlias(true);
paintNegative = new Paint();
paintNegative.setColor(Color.BLUE);
paintPositive.setStyle(Paint.Style.FILL_AND_STROKE);
paintNegative.setAntiAlias(true);
paintText = new Paint();
paintText.setColor(Color.BLACK);
paintText.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 24, getResources().getDisplayMetrics()));
progress = 0;
maxProgress = 10;
}
#Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
float diameter = Math.min(getWidth(), getHeight());
RectF ovalOuter = new RectF(0, 0, diameter, diameter);
RectF ovalInner = new RectF(ovalOuter.left + arcWidth, ovalOuter.top + arcWidth, ovalOuter.right - arcWidth, ovalOuter.bottom - arcWidth);
path = new Path();
path.moveTo(ovalOuter.centerX(), ovalOuter.top);
path.addArc(ovalOuter, 270, 90);
path.lineTo(ovalInner.right, ovalInner.centerY());
path.addArc(ovalInner, 0, -90);
path.lineTo(ovalOuter.centerX(), ovalOuter.top);
clipPath = new Path();
clipPath.addRect(ovalOuter.left, ovalOuter.centerY() - arcPadding / 2, ovalOuter.right, ovalOuter.centerY() + arcPadding / 2, Path.Direction.CW);
clipPath.addRect(ovalOuter.centerX() - arcPadding / 2, ovalOuter.top, ovalOuter.centerX() + arcPadding / 2, ovalOuter.bottom, Path.Direction.CW);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
float perc = (float) progress / (float) maxProgress;
int state = 0;
if (perc < 0.25) {
state = 1;
} else if (perc < 0.5) {
state = 2;
} else if (perc < 0.75) {
state = 3;
} else {
state = 4;
}
RectF bounds = new RectF();
path.computeBounds(bounds, true);
// Draw Circle
canvas.save();
// Clip padding
canvas.clipPath(clipPath, Region.Op.DIFFERENCE);
canvas.drawPath(path, state == 1 ? paintPositive : paintNegative);
canvas.rotate(90, bounds.left, bounds.bottom);
canvas.drawPath(path, state == 2 ? paintPositive : paintNegative);
canvas.rotate(90, bounds.left, bounds.bottom);
canvas.drawPath(path, state == 3 ? paintPositive : paintNegative);
canvas.rotate(90, bounds.left, bounds.bottom);
canvas.drawPath(path, state == 4 ? paintPositive : paintNegative);
canvas.restore();
// Draw Progress
String text = String.valueOf(progress);
Rect textBounds = new Rect();
paintText.getTextBounds(text, 0, text.length(), textBounds);
float x = bounds.left - textBounds.width() / 2;
float y = bounds.bottom + textBounds.height() / 2;
canvas.drawText(text, x, y, paintText);
}
public int getProgress() {
return progress;
}
public void setProgress(int progress) {
int oldProgress = this.progress;
this.progress = progress;
if (listener != null) {
listener.onProgressChanged(oldProgress, progress);
}
invalidate();
}
public int getMaxProgress() {
return maxProgress;
}
public void setMaxProgress(int maxProgress) {
this.maxProgress = maxProgress;
invalidate();
}
public ProgressListener getListener() {
return listener;
}
public void setListener(ProgressListener listener) {
this.listener = listener;
}
public interface ProgressListener {
void onProgressChanged(int oldProgress, int newProgress);
}
}

Android Create a circle hole in a centerCropped image

I come again for an android brain idea!
I would like to put a circle hole hole in a imageView which bitmap is scaled as centerCrop. I know where I need to put the circle hole( in dp from left and bottom) and the hole radius. But don't know how to build it!
I know that I can use Porterduff to do the hole but what you suggest to do?
Custom bitmap
Custom drawable/view
Custom code
Thanks
Following Answers there is my CustomImage with hole:
public class MyImageView extends ImageView {
private AttributeSet attrs;
private float y;
private float x;
private float r;
private Paint paint;
private Rect mSrcRect;
private Rect mDestRect;
private Bitmap mBitmap;
private int alreadycalled = 0;
public MyImageView(Context context, AttributeSet attrs) {
super(context, attrs);
this.attrs = attrs;
initView();
}
public MyImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.attrs = attrs;
initView();
}
public MyImageView(Context context, float x, float y, float radius) {
super(context);
this.x = x;
this.y = y;
this.r = radius;
Log.d("parameters", String.format("left:%s , right:%s, radius:%s", String.valueOf(x), String.valueOf(y), String.valueOf(r)));
initView();
}
private void initView() {
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStyle(Paint.Style.FILL_AND_STROKE);
paint.setStrokeWidth(10);
paint.setColor(0xff000000);
}
#Override
protected void onDraw(Canvas canvas) {
alreadycalled++;
Log.d("alreadycalled", "called " + alreadycalled);
Drawable mDrawable = getDrawable();
if (mDrawable == null) {
return; // couldn't resolve the URI
}
int dWidth = mDrawable.getIntrinsicWidth();
int dHeight = mDrawable.getIntrinsicHeight();
float scale = 1.0f;
scale = Math.max(getWidth() * 1.0f / dWidth, getHeight()
* 1.0f / dHeight);
int nWidth = (int) (dWidth * scale);
int nHeight = (int) (dHeight * scale);
int offsetLeft = (nWidth - getWidth()) / 2;
int offsetTop = (nHeight - getHeight()) / 2;
mBitmap = ((BitmapDrawable) mDrawable).getBitmap();
//custom mSrcRect mDestRect to achieve centerCrop
mSrcRect = new Rect(0, 0, dWidth, dWidth);
mDestRect = new Rect(-offsetLeft, -offsetTop, getWidth() + offsetLeft, getHeight() + offsetTop);
Log.d("src", mSrcRect.toString());
Log.d("dest", mDestRect.toString());
int sc = canvas.saveLayer(0, 0, getWidth(), getHeight(), null,
Canvas.MATRIX_SAVE_FLAG | Canvas.CLIP_SAVE_FLAG
| Canvas.HAS_ALPHA_LAYER_SAVE_FLAG
| Canvas.FULL_COLOR_LAYER_SAVE_FLAG
| Canvas.CLIP_TO_LAYER_SAVE_FLAG);
paint.setColor(0xffffffff);
canvas.drawBitmap(mBitmap, mSrcRect, mDestRect, paint);
paint.setColor(0xffff0000);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
Log.d("position", String.format("%s , %s", String.valueOf(x), String.valueOf(y)));
canvas.drawCircle(x, y, r, paint);
paint.setXfermode(null);
canvas.restoreToCount(sc);
}
I called it programmatically with theses lines :
BitmapDrawable bd=(BitmapDrawable) getResources().getDrawable(R.drawable.triangle_bas_accueil2);
MyImageView customImView = new MyImageView(getApplicationContext(), mX, mY, mRadius);
customImView.setImageDrawable(bd);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
params.gravity = Gravity.BOTTOM;
customImView.setLayoutParams(params);
down_relative.addView(customImView);
But the onDraw() method is called twice (maybe it needs) but that makes me two holes, one that I can change parameters but the other still at the same place ! The container of the MyImageView is a RelativeLayout.
If someOne has an idea?
#tiny-sunlight ?
This one is just for CenterCrop and can't deal with scaleType.And this code may have some problems because I'm not good at canvas.
public class MyImageView extends ImageView {
private final AttributeSet attrs;
private Paint paint;
private Rect mSrcRect;
private Rect mDestRect;
private Bitmap mBitmap;
public MyImageView(Context context, AttributeSet attrs) {
super(context, attrs);
this.attrs = attrs;
initView();
}
public MyImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.attrs = attrs;
initView();
}
private void initView() {
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStyle(Paint.Style.FILL_AND_STROKE);
paint.setStrokeWidth(10);
paint.setColor(0xff000000);
}
#Override
protected void onDraw(Canvas canvas) {
// super.onDraw(canvas);
//create the drawable.Maybe you can cache it.
Drawable mDrawable = (BitmapDrawable) getResources().getDrawable(R.drawable.triangle_bas_accueil2);
if (mDrawable == null) {
return; // couldn't resolve the URI
}
int dWidth = mDrawable.getIntrinsicWidth();
int dHeight = mDrawable.getIntrinsicHeight();
float scale = 1.0f;
scale = Math.max(getWidth() * 1.0f / dWidth, getHeight()
* 1.0f / dHeight);
int nWidth = (int) (dWidth*scale);
int nHeight = (int) (dHeight*scale);
int offsetLeft = (nWidth - getWidth())/2;
int offsetTop = (nHeight - getHeight())/2;
//cache mBitmap
mBitmap = mBitmap == null ? ((BitmapDrawable) mDrawable).getBitmap(): mBitmap;
//custom mSrcRect mDestRect to achieve centerCrop
mSrcRect = new Rect(0, 0, dWidth, dWidth);
mDestRect = new Rect(-offsetLeft, -offsetTop,getWidth()+offsetLeft, getHeight()+offsetTop);
int x = 250;int r = 100;
int sc = canvas.saveLayer(0, 0, getWidth(), getHeight(), null,
Canvas.MATRIX_SAVE_FLAG | Canvas.CLIP_SAVE_FLAG
| Canvas.HAS_ALPHA_LAYER_SAVE_FLAG
| Canvas.FULL_COLOR_LAYER_SAVE_FLAG
| Canvas.CLIP_TO_LAYER_SAVE_FLAG);
paint.setColor(0xffffffff);
canvas.drawBitmap(mBitmap,mSrcRect,mDestRect,paint);
paint.setColor(0xff000000);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
canvas.drawCircle(x,x,r,paint);
paint.setXfermode(null);
canvas.restoreToCount(sc);
}
}
Custom code. Loop through each pixel and change the alpha. Here is some pseudocode:
for (int y = 0; y < imageHeight; y++) {
for (int x = 0; x < imageWidth; x++) {
// Check if the current pixel is within the circle
if (dist(x, y, centerX, centerY) <= radius) {
// Change the alpha
image.setPixelAlpha(x, y, 0);
}
}
}

Android: View embedded in layout. onDraw() method triggered but the screen not update immediately

I am new on Android. I am working on simple Sudoku solver and I have problem with my view.
My SolverView contain on Custom View embedded into a layout that contains 2 buttons.
When I click on a cell of sudoku grid, a keypad dialog appear that allow me to choose the number for that cell. However, after click on a number on keypad, my sudoku grid not display it immediately although the onDraw() method was called. Instead, it only update on the next time I touch screen.
Following is the code
public class SolverView extends View{
private String TAG = "Solver View";
private int size;
private Solver solver;
private static int selU, selV;
public SolverView(Context context) {
super(context);
this.solver = (Solver) context;
setFocusable(true);
setFocusableInTouchMode(true);
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
public SolverView(Context context, AttributeSet attrs) {
super(context, attrs);
this.solver = (Solver) context;
setFocusable(true);
setFocusableInTouchMode(true);
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
public SolverView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.solver = (Solver) context;
setFocusable(true);
setFocusableInTouchMode(true);
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
public int getBoardSize() {
int height = getHeight();
int width = getWidth();
return Math.min(height, width);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
size = getBoardSize();
int cellSize = size / 9;
Paint light = new Paint();
light.setColor(getResources().getColor(R.color.puzzle_light));
Paint dark = new Paint();
dark.setColor(getResources().getColor(R.color.puzzle_dark));
dark.setTypeface(Typeface.DEFAULT_BOLD);
for (int i = 0; i <= 9; i++) {
canvas.drawLine(i * cellSize, 0, i * cellSize, size, light);
if (i % 3 == 0)
canvas.drawLine(i * cellSize, 0, i * cellSize, size, dark);
}
for (int i = 0; i <= 9; i++) {
canvas.drawLine(0, i * cellSize, size, i * cellSize, light);
if (i % 3 == 0)
canvas.drawLine(0, i * cellSize, size, i * cellSize, dark);
}
Paint foreground = new Paint(Paint.ANTI_ALIAS_FLAG);
foreground.setColor(getResources().getColor(R.color.puzzle_dark));
foreground.setStyle(Style.FILL);
foreground.setTextSize(cellSize * 0.75f);
foreground.setTextAlign(Paint.Align.CENTER);
FontMetrics fm = foreground.getFontMetrics();
float x = cellSize / 2 - (fm.ascent + fm.descent) / 2;
float y = cellSize / 2 ;
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
canvas.drawText(this.solver.getCellString(i, j), j * cellSize + y, i * cellSize + x, foreground);
}
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() != MotionEvent.ACTION_DOWN)
return super.onTouchEvent(event);
int cellSize = size / 9;
int i = (int)event.getY() / cellSize;
int j = (int)event.getX() / cellSize;
if (i < 0 || i > 8 || j < 0 || j > 8)
return false;
this.selU = i;
this.selV = j;
Log.d(TAG, "onTouchEvent: " + selU + " , " + selV);
this.solver.showKeypad(i, j);
invalidate();
return true;
}
public void setCell(int t) {
Log.d(TAG, "in setCell: t = " + t);
Log.d(TAG, "in setCell: selU = " + selU);
Log.d(TAG, "in setCell: selV = " + selV);
if (solver.setCellIfValid(selU, selV, t)) {
Log.d(TAG, "setCell: going to invalidate()");
Log.d(TAG, "setCell: value change: " + solver.a[selU][selV]);
invalidate();
}
}
}
And this is the structure of layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/zero"
android:paddingLeft="#dimen/zero"
android:paddingRight="#dimen/zero"
android:paddingTop="#dimen/zero"
tools:context="com.trungkienioicamp.helloworld.Solver" >
<com.trungkienioicamp.helloworld.SolverView
android:id="#+id/board"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true" />
<Button
android:id="#+id/clear"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_marginBottom="74dp"
android:layout_marginLeft="29dp"
android:text="Clear" />
<Button
android:id="#+id/solve"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="#+id/clear"
android:layout_alignBottom="#+id/clear"
android:layout_alignParentRight="true"
android:layout_marginRight="61dp"
android:text="Solve" />
Can anyone suggest me the solution for this one? Thank for reading
UPDATED: The problem gone when I set the content view of main activity as solverView instance
setContentView(solverView);
But it will not work when I set the content view as a layout
setContentView(R.layout.activity_solver);
Instead, it only update on the next time I touch screen
Try to call invalidate your instance of SolverView after click on a number on keypad.

How to display Text in Android Canvas ShapeDrawable with in the RectShape or OvalShape?

I'm trying to display Text in RectShape which uses ShapeDrawable to display in Canvas.
I'm able to display RectShape in this code, but looking for how to display the String on that!
public class CustomDrawableView extends View {
private ShapeDrawable mDrawable;
public CustomDrawableView(Context context) {
super(context);
int x = 10;
int y = 10;
int width = 300;
int height = 50;
mDrawable = new ShapeDrawable(new OvalShape());
mDrawable.getPaint().setColor(0xff74AC23);
mDrawable.setBounds(x, y, x + width, y + height);
}
protected void onDraw(Canvas canvas) {
mDrawable.draw(canvas);
}
}
or
public class ShapeDrawableTest extends View {
ShapeDrawable shapes = new ShapeDrawable();
public ShapeDrawableTest(Context context) {
super(context);
}
public ShapeDrawableTest(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
shapes.draw(canvas);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
int x = (int) event.getX(); // Use getX(int) for multi-finger
// gestures
int y = (int) event.getY();
makeShapeDrawable(x, y);
invalidate();
return (true); // Handled touch event
} else {
return (false); // Did not handle touch event
}
}
private void makeShapeDrawable(int x, int y) {
int maxWidth = getWidth() / 10;
int maxHeight = getHeight() / 10;
Shape shape;
shape = new RectShape();
shapes = new ShapeDrawable(shape);
int width = RandomUtils.randomInt(maxWidth) + 5;
int height = RandomUtils.randomInt(maxHeight) + 5;
shapes.setBounds(x - width / 2, y - height / 2, x + width / 2, y
+ height / 2);
shapes.getPaint().setColor(Color.BLUE);
}
}
What I tried is:
public class CustomDrawableView extends View {
public ShapeDrawable mDrawable;
public CustomDrawableView(Context context) {
super(context);
}
public CustomDrawableView(Context context, AttributeSet attrs) {
super(context, attrs);
int x = 10;
int y = 10;
int width = 300;
int height = 50;
mDrawable = new ShapeDrawable(new OvalShape());
//mDrawable.getPaint().setColor(0xff74AC23);
final String s = "Hello";
Paint p = new Paint();
Rect bounds = new Rect();
bounds.set(x, y, x + width, y + height);
p.setTextSize(20);
p.setColor(Color.YELLOW);
p.getTextBounds(s, 0, s.length(), bounds);
mDrawable.getPaint().getTextBounds(s, 0, s.length(), bounds);
mDrawable.setBounds(x, y, x + width, y + height);
}
// public CustomDrawableView(Context context, AttributeSet attrs, int defStyle) {
// super(context, attrs, defStyle);
//
// }
public void onDraw(Canvas canvas) {
mDrawable.draw(canvas);
}
}
Screenshot:
The best option for me is to create a custom TextDrawable that handles properly how to display a piece of text. Then in your CustomDrawableView in your onDraw(Canvas c) method you can call it to display the text and the oval.
Take a look at this answer I wrote recently as it contains how to do it properly.

Categories

Resources