i have an imageview in my xml file and i want to put another image over it where user clicks.
i have used a canvas to place an image where user clicks but i am stuck when it comes to putting the canvas over my imageview.
Or is there any way around when we want to put another image over an imageview while detecting user clicks?
Thanks
Since you're already overriding a View method, I would say have that draw the image rather than an ImageView. Your onDraw() method would essentially be:
#Override
public void onDraw(Canvas canvas) {
canvas.drawBitmap(bottomBitmap, xCorner, yCorner, paintObject);
canvas.drawBitmap(topImage, fingerXCorner, fingerYCorner, paintObject);
}
EDIT:
Alternatively, if you want to keep the ImageView because of the convenient scaletypes, then you can override a FrameLayout. Place the ImageView inside of it, then override the draw() method to draw a bitmap.
#Override
public void draw(Canvas canvas) {
super.draw(canvas); // draws everything in the FrameLayout
canvas.drawBitmap(topImage, fingerXCorner, fingerYCorner, paintObject);
}
Have you tried using an ImageButton?
<ImageButton
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:onClick="onButtonClick"
android:src="#drawable/yourImageFile" />
Then define your onButtonClick method in your Activity,
public void onButtonClick(View v) {
/* Do something */
}
Related
I'm making a custom View thats derived from an ImageViewand I control where the image has to be within this ImageView using padding.
I have set OnClickListener on my custom ImageView that resizes it:
image.setOnClickListener(new ImageView.OnClickListener(){
#Override
public void onClick(View v) {
image.resize_image();
}
});
and this is how this function is looking like
public void resize_image(){
ViewGroup.LayoutParams params = getLayoutParams();
params.height = new_heigth;
params.width = new_width;
setLayoutParams(params);
}
After this resizing is done I don't want my displayed image to change size (only the custom ImageView is changing size so I can draw an extra stuff around this image) within my custom ImageView so inside onDraw(Canvas) member function I set the new padding
class custom_ImageView extends ImageView{
//...
#Override
protected void onDraw(Canvas canvas) {
//...
setPadding(new_left_padding, new_top_padding, new_right_padding, new_bottom_padding);
//...
}
//...
}
Result is that width and heigth are changed like I wanted but my displayed image is neither in the right position or size.
Interesting this is that if I add an extra line of invalidate(); in the end of my resize_image() and I click on my custom_ImageView twice - on the 2nd click image draws itself in right size and position like I wanted.
Can anyone tell me why this is happening?
I kind of worked around this by not using ImageView at all but just drawing image where it needs to be by using Canvas.drawBitmap(Bitmap, RectF, RectF, Paint)
This way I don't have to specify images location using setPadding within onDraw, but I can do it simply by specifying position using RectF.
The event onDraw() is emitted every time the View need to be repainted cause some graphic changes inside.
Unfortunately if the View is hidden (invisible) this event is not emitted since, obviously, there is no need to repaind anything. However I would to know if there is some trick to "cheat" the View to emit the onDraw() event and redraw itself exactly like it would really showed inside the screen.
Basically I need to capture screenshot status of a View component in all its changes but whitout show it (running it in background).
I guess it would be very hard to get such result but, just in case, I'll try to ask.
Thank you
I believe a View's visibility is checked by its parent and not the View itself. You can pass in a Canvas backed by a Bitmap straight in to View#draw(Canvas canvas) and it will draw itself on to the Bitmap. However, the based on the source code of View#setVisibility(), the View's background will still be invisible.
public void setVisibility(int visibility) {
setFlags(visibility, VISIBILITY_MASK);
if (mBGDrawable != null) mBGDrawable.setVisible(visibility == VISIBLE, false);
}
Everything else should appear in the View as is (unless it's children are also set to invisible of course).
EDIT:
Converting a view to Bitmap without displaying it in Android?
There are examples there on how to do that.
public static Bitmap getBitmapFromView(View view) {
Bitmap returnedBitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(),Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(returnedBitmap);
view.draw(canvas);
return returnedBitmap;
}
EDIT 2:
Since setVisibility() is not part of the View, you could override it and simply not set the View to be invisible. Something like:
boolean isInvisible = false;
#Override
public void setVisibility(int visibility) {
if (visibility == View.INVISIBLE) {
invisible = true;
} else {
invisible = false;
super.setVisibility();
}
}
#Override
public void onDraw(Canvas canvas) {
// change state code
if (!invisible) {
// draw code
super.onDraw(canvas);
}
}
#Override
public void draw(Canvas canvas) {
if (!invisible) {
// draw code
super.draw(canvas);
}
}
I have no idea what side-effects this would cause so be extremely careful and weary. Perhaps someone else would have a better solution. Another solution is you can simply call onDraw() on a different canvas whenever you want to draw it. This would require you to create a super class that is the parent layout View of the View you want to draw. Then in the parent's onDraw() method, call the child's onDraw() method separately if it's visibility is set to INVISIBLE.
If someone is interested I managed to solve this problem by override the invalidate() method. Instead of onDraw() that is called by the system only if the view is currently visible the invalidate() function is called "internally" and can be used to check if the view need to be reapinted in the same way.
I have a code where I draw image:
class Panel extends View {
public Panel(Context context) {
super(context);
}
#Override
public void onDraw(Canvas canvas) {
Bitmap _scratch = BitmapFactory.decodeResource(getResources(), R.drawable.calvin_logo_small);
canvas.drawColor(Color.WHITE);
canvas.drawBitmap(_scratch, x-point, y-point, null);
}
}
How can I draw this image in my activity, but I don't want to change may layout. I have layout: setContentView(R.layout.main); This is possible to draw in this lauout with canvas? I have this activity and this layout have a lot of components. I only want image in place where I click with canvas. This is idea. I start application where start activity with my setContentView(R.layout.main);. After that I click on the screen and canvas draw picture in place where I clicked. This is possible to do?
Your code should work. Just override the onTouchEvent() for the view, store the co-ordinates of the touch event in field variables and invalidate() the view so that onDraw() would be called. Use the co-ordinates in onDraw() to render the image as you've already done.
To improve performance, you can cache the bitmap if it's not going to change.
How can I draw a button on top of the canvas in a custom view? (Preferably on the mid-right side) Is there something I have to call before doing the button.draw(canvas)?
public class MyClass extends View {
public Simulation(Context context) {
super(context);
pauseButton.setText("TestButton");
pauseButton.setClickable(true);
pauseButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Log.i(TAG, "Button Pressed!");
}
});
public onDraw(Canvas canvas) {
super.onDraw(canvas);
pauseButton.draw(canvas);
}
}
Thanks for your time
You cannot insert a button into canvas. Canvas is an interface for bitmap or a bitmap buffer for a view. You can only draw other bitmap or pixels in it, not insert an object or a widget.
There are some solutions:
as Nikolay suggested, use a FrameLayout and create two layers (views), first your custom view and the second LinerView or RelativeView, which will come on top, where you can have buttons etc
draw an image of a buttun on Canvas then use onTouchEvent in your custom view and test for the coordinates of the touch, then do something... an example for onTouchEvent here: Make certain area of bitmap transparent on touch
Why do you need to draw the button yourself? Use a FrameLayout and simply have the button overlayed on your custom view.
Try this
public onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.save();
pauseButton.draw(canvas);
canvas.restore();
}
I am trying to create a "hidden edit view" which will give me the functionality of text editing within a 3rd party GUI on Android. I figured that the easiest way to make it not draw would be to just override onDraw() with a no-op; however it's having no effect. I've added a log statement to check that it is being called. Does anyone have an idea why it's still being drawn?
private class HiddenEditText extends EditText
{
public HiddenEditText(Context context)
{
super(context);
}
#Override
protected void onDraw(Canvas canvas)
{
Log.e("DBG", "onDraw()");
}
}
// ...
EditText EditTextGreen = new HiddenEditText(this);
EditTextGreen.setFocusable(true);
EditTextGreen.setLayoutParams(new TableLayout.LayoutParams(TableLayout.LayoutParams.FILL_PARENT, TableLayout.LayoutParams.WRAP_CONTENT));
layout.addView(EditTextGreen, 0);
Another way of achieving this result, is to specify the background of the EditText as transparent:
<EditText android:background="#android:color/transparent" ...
The background is drawn by View.draw(). onDraw() is invoked by View.draw(), so you need to follow Mannaz' advice and set the background to a transparent color or just set it to null.