Change ImageResource Dinamically in Custom ImageView Android - java

I've working in this error all day and can not solve it. I have a custom ImageView as follows:
public class UserDirectionView extends ImageView {
private float mDirection;
private Drawable arrow;
private boolean mCorrectPosition;
// constructors...
#Override
protected void onDraw(Canvas canvas) {
if (arrow == null) {
arrow = getDrawable();
arrow.setBounds(0, 0, getWidth(), getHeight());
// setImageResource(resId); // Not working
}
canvas.save();
canvas.rotate(mDirection, getWidth() / 2, getHeight() / 2);
arrow.draw(canvas);
canvas.restore();
}
public void updateDirection(float direction, boolean correctPos) {
mDirection = direction;
mCorrectPosition = correctPos;
invalidate();
}
}
I am trying to change the imageResource with setImageResource(resId) but nothing is happening. I've tried to call the method inside of onDraw and also outside my class, like so:
UserDirectionView mUserHint = findview....;
mUserHint.setImageResource(resId);
But the image is not changing.
I've also tried to call invalidate, but didn't work.
How could I change the image resource dinamically?

You are missing the super.onDraw() call, which takes care of updating the drawable. Add
super.onDraw(canvas)
In your onDraw

Related

Change Custom View Canvas background color to transparent

I made a custom View Class that draws the waveform of an audio file, unfortunately, I'm having some problems with changing the background color of the canvas/custom view to transparent.
I can change the background color inside the onDraw function canvas.drawColor(Color.WHATEVER);
However, this works with any color but transparent, which shows black instead.
This works: canvas.drawColor(Color.BLUE);
This doesn't: canvas.drawColor(Color.TRANSPARENT);
Also, if I use the Android Studio Layout inspector, it seems to actually work, but in reality it does not. See the screenshot here:
Layout Inspector vs Android Emulator Screenshot
public class SimpleWaveform extends View {
Context context;
public Paint beforePlaySectionPencil = new Paint();
public Paint playSectionPencil = new Paint();
public Paint afterPlaySectionPencil = new Paint();
public Paint peakPencilBefore = new Paint();
public Paint peakPencilPlay = new Paint();
public Paint peakPencilAfter = new Paint();
public Paint xAxisPencil = new Paint();
public void init() {
beforePlaySectionPencil.setStrokeWidth(10);//set bar width (ERA /2)
beforePlaySectionPencil.setColor(ContextCompat.getColor(getContext(), R.color.aaDarkBlue));
playSectionPencil.setStrokeWidth(10); // (ERA /2)
playSectionPencil.setColor(ContextCompat.getColor(getContext(), R.color.aaLightBlue));
afterPlaySectionPencil.setStrokeWidth(10); // (ERA /2)
afterPlaySectionPencil.setColor(ContextCompat.getColor(getContext(), R.color.aaDarkBlue));
peakPencilBefore.setStrokeWidth(barGap / 8);//set peak outline width (ERA /6)
peakPencilBefore.setColor(0xfffe2f3f);
peakPencilPlay.setStrokeWidth(barGap / 8); //(ERA /6)
peakPencilPlay.setColor(0xfffe2f3f);
peakPencilAfter.setStrokeWidth(barGap / 8); //(ERA /6)
peakPencilAfter.setColor(0xfffe2f3f);
xAxisPencil.setStrokeWidth(1);
xAxisPencil.setColor(0x88ffffff);
#Override
protected void onDraw(Canvas canvas) {
if (clearScreenListener != null) {
clearScreenListener.clearScreen(canvas);
} else {
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
}
if (clearScreen) {
clearScreen = false;
return;
}
drawWaveList(canvas);
canvas.drawColor(Color.TRANSPARENT);
}
private void drawWaveList(Canvas canvas) {
if (showBar) {
canvas.drawLines(barPoints, 0, playSectionLeftOffset * barUnitSize, beforePlaySectionPencil);
canvas.drawLines(barPoints, playSectionLeftOffset * barUnitSize, (playSectionRightOffset - playSectionLeftOffset) * barUnitSize, playSectionPencil);
canvas.drawLines(barPoints, playSectionRightOffset * barUnitSize, (barNum - playSectionRightOffset) * barUnitSize, afterPlaySectionPencil);
}
if(showXAxis){
canvas.drawLines(xAxisPoints, xAxisPencil);
}
}
}
I did a bit of research and found out how to achieve that in a canvas.
Take a look at this explanation.

Avoid object allocations during draw/layout operations error in Android

I got this error in Android Studio:
Avoid object allocations during draw/layout operations
Code:
public class cizim extends View {
Path path = new Path();
Paint paint = new Paint();
public cizim (Context c){
super(c);
paint.setColor(Color.BLACK);
paint.setAntiAlias(true);
}
#Override
protected void onDraw(Canvas canvas){
canvas.setBitmap(BitmapFactory.decodeResource(getContext().getResources(), R.drawable.foto));
canvas.drawPath(path, paint);
super.onDraw(canvas);
}
#Override
public boolean onTouchEvent(MotionEvent event){
float x = event.getX();
float y = event.getY();
path.addCircle(x, y, 10, Path.Direction.CW);
invalidate();
return super.onTouchEvent(event);
}
}
I got the error with this code:
canvas.setBitmap(BitmapFactory.decodeResource(getContext().getResources(), R.drawable.foto));
How can I resolve this problem?
I need your help.
Drawing a view is always a heavy task because onDraw method is invoked whenever the view needs to be drawn again, so imagine allocating/creating new objects in that method; it will certainly take a lot of time and will decrease your app performance.
So instead of creating your bitmap every time onDraw is called, create it only once in your view constructor.
Add a new instance variable to your class:
public class cizim extends View {
private Bitmap bitmap;
...
}
Then in your constructor, create that object as follows:
public cizim(Context context) {
super(context);
paint.setColor(Color.BLACK);
paint.setAntiAlias(true);
bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.foto);
}
Finally modify your onDraw method to:
#Override
protected void onDraw(Canvas canvas){
canvas.setBitmap(bitmap);
canvas.drawPath(path, paint);
super.onDraw(canvas);
}
Edit:
There is actually another issue with your code that will result in UnsupportedOperationException when calling canvas.setBitmap. If you refer to the documentation, setBitmap will change the bitmap the canvas will draw to. Since you need to draw the bitmap on the screen, you cannot use setBitmap here. So what you actually need is canvas.drawBitmap
Change your onDraw method to:
#Override
protected void onDraw(Canvas canvas){
canvas.drawBitmap(bitmap, 0, 0, paint);
canvas.drawPath(path, paint);
super.onDraw(canvas);
}

Is it possible to disable the bottom of a paint with stroke style programmatically

I'm using a custom Class which extends ShapeDrawable to draw programmatically background and border with custom colors.
The code :
public class CustomBorderDrawable extends ShapeDrawable {
private Paint fillpaint, strokepaint;
private int WIDTH = 3;
public CustomBorderDrawable(Shape s) {
super(s);
fillpaint = this.getPaint();
strokepaint = new Paint(fillpaint);
strokepaint.setStyle(Paint.Style.STROKE);
strokepaint.setStrokeWidth(WIDTH);
strokepaint.setARGB(255, 0, 0, 0);
}
#Override
protected void onDraw(Shape shape, Canvas canvas, Paint fillpaint) {
shape.draw(canvas, fillpaint);
shape.draw(canvas, strokepaint);
}
public void setFillColour(int c){
fillpaint.setColor(c);
}
public void setBorderColour(int c){
strokepaint.setColor(c);
}
public void setStrokeWidth(int px){
this.WIDTH = px;
strokepaint.setStrokeWidth(WIDTH);
}
public void setBottomEnable(boolean enable){
//TODO
}}
As you can see I want to add a function which allow to enable or not the bottom part of my strokepaint.
I have only found XML solution, how to do that programmatically?
A solution could be to put a bar in front of the bottom of my border, but I don't know how to do that.
If you just want to disable the stroke then call setStrokeWidth(0). Setting Width as 0 will not display the stroke.

Android Custom Brush Colors

I'm trying to make custom brushes for my Android painting app. I started with Michael's code (found here) and I have managed to get .png brushes and use that as a bitmap and redraw it. It works fine but I can't change the colour. Tried using the setcolorfilter and colormatrixfilter but it doesn't seem to be working. Anyone knows how I can do this?
private Bitmap mBitmapBrush;
private Vector2 mBitmapBrushDimensions;
private List<Vector2> mPositions = new ArrayList<Vector2>(100);
private Paint mPanit;
public MyView(Context c) {
super(c);
mPath = new Path();
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
mBitmapBrush = BitmapFactory.decodeResource(c.getResources(),R.drawable.brush1);
mBitmapBrushDimensions = new Vector2(mBitmapBrush.getWidth(), mBitmapBrush.getHeight());
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(0xFFAAAAAA);
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
for (Vector2 pos : mPositions) {
canvas.drawBitmap(mBitmapBrush, pos.a, pos.b, mPanit);
}
invalidate();
}
When I tried using the Colormatrixfilter, the .set function was giving an error.
I had the same issue. In order to change the bitmap color you need to add color to your paint object and apply it into bitmap. See the working example here,
for (Vector2 pos : customBrushMap.get(p)) {
Paint paint = new Paint();
ColorFilter filter = new PorterDuffColorFilter(R.Color.GREEN, PorterDuff.Mode.SRC_IN);
paint.setColorFilter(filter);
canvas.drawBitmap(mBitmapBrush, pos.x, pos.y, paint);
}
Result,

Android Scratch card app

I am doing a small project for college and wondering if someone can tell me how I would go about doing a scratch card app. This app should have one image overlaying another. The one on top should allow the user to remove the image depending on where they rub on the image and thus part of the image that was removed revealing the image underneath. Pretty much like a scratch card. Any help would be great!
This is the code im using at the moment .
public class workinggraphics extends Activity
{
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
//setContentView(R.layout.main);
setContentView(new Panel(this));
LinearLayout l1 = (LinearLayout) findViewById(R.id.LAYOUTTEST1);
Panel p1 = new Panel(null);
}
class Panel extends View{
private Bitmap mBitmap;
private Canvas mCanvas;
private Path mPath;
private Paint mPaint;
// private Paint nPaint;
Bitmap bitmap;
Canvas pcanvas ;
int x = 0;
int y =0;
int r =0;
public Panel(Context context) {
super(context);
Log.v("Panel", "STROKE");
setFocusable(true);
setBackgroundColor(Color.TRANSPARENT);
/*
WallpaperManager wallpaperManager = WallpaperManager.getInstance(context);
//WallpaperDrawable wallpaperDrawable=wallpaperManager.getDrawable();
try {
wallpaperManager.setBitmap(bmp);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}*/
//setBackgroundDrawable(bmp);
// setting paint
/* nPaint = new Paint();
nPaint.setStyle(Paint.Style.FILL);*/
mPaint = new Paint();
mPaint.setAlpha(0);
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mPaint.setStrokeCap(Paint.Cap.BUTT);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));//.Mode.DST_IN));
mPaint.setAntiAlias(false);
// getting image from resources
Resources r = this.getContext().getResources();
Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.mainscreen_background);
Bitmap bm1 = BitmapFactory.decodeResource(getResources(),R.drawable.foreground_image);
// converting image bitmap into mutable bitmap
bitmap = bm.createBitmap(bm.getWidth(), bm.getHeight(), Config.ARGB_8888);
//bitmap = bm1.createBitmap(bm1.getWidth(),bm1.getHeight(),Config.ARGB_8888);
pcanvas = new Canvas();
pcanvas.setBitmap(bitmap); // drawXY will result on that Bitmap
pcanvas.drawBitmap(bm, 0, 0, null);
pcanvas.drawBitmap(bm1,0,0,null);
}
#Override
protected void onDraw(Canvas canvas) {
Rect cBK = new Rect();
//canvas.set
cBK.set(0,0,canvas.getWidth(),canvas.getHeight());
//pcanvas.drawRect(cBK, nPaint);
// draw a circle that is erasing bitmap
pcanvas.drawCircle(x, y, r, mPaint);
//pcanvas.drawLine(x, y, 0, 0, mPaint);
canvas.drawBitmap(bitmap, 0, 0,null);
super.onDraw(canvas);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
// set paramete to draw circle on touch event
x = (int) event.getX();
y = (int) event.getY();
r =20;
// Atlast invalidate canvas
invalidate();
return true;
}
}
}
Now as you can see above there is a lot of comments for things we have tried. Ideally I would like to be able to create an instance of the Panel class, set the workinggraphics class contextview to a XML LinearLayout (OR SurfaceView w/e would be used I dont really know), and then just set a background image on the defined LinearLayout in XML to be revealed when the canvas erases the bitmap image we have set.
Anyway any suggestions would be appricated thanks alot in advanced!
I created a library call WScrarchView where you can implement scratch view just few lines in layout xml. Hope this can help those who still looking for the solution https://github.com/winsontan520/Android-WScratchView

Categories