I'm trying to implement a footer for my ListView which will act as a menu-type frame with five elements. I want the elements to be able to (dynamically, based on user input) display either images or text (or possibly both, but I'm not there yet). Eventually it will be more interactive but for now I was trying to implement it so that the ImageView (which by default displays an image) would erase the image and display text instead.
I thought the best way to implement this was to draw text on a canvas and use the android.view.View.draw(canvas c) method to draw it onto the ImageView. However, I'm having trouble doing this. Specifically, I can modify the view in almost any way (set the background color, change the drawable, etc etc) and it all works fine, and the code to draw the canvas compiles properly, but it doesn't do anything at runtime. The view remains completely unchanged.
(Note: I've tried to eliminate any stupid mistakes through code (i.e. made sure text wasn't transparent/same color as bg, made sure text was drawn inside the area of the view, etc) but I am not 100% it's error free.)
I tried both drawing to the view passed into the onClick function and drawing to a new ImageView constructed from the passed view - neither works.
Does anyone have any suggestions?
Code follows:
login_button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
Bitmap img = Bitmap.createBitmap( 60, 60, Config.ARGB_8888);
Canvas c = new Canvas();
c.setBitmap(img);
Paint myPaint = new Paint();
myPaint.setTypeface(mFace);
myPaint.setColor(android.R.color.black);
myPaint.setTextSize(2);
myPaint.setTextAlign(Paint.Align.LEFT);
String content = "testing";
c.drawText(content, 0,0, myPaint);
view.draw(c);//does nothing
ImageView view2 = (ImageView) view;
view2.setBackgroundColor(android.R.color.white); //this works perfectly
view2.draw(c);//does nothing
Toast.makeText(MainListView.this, ""+c.getHeight(), Toast.LENGTH_SHORT).show(); //making sure c has height - this returns 60 as expected
Toast.makeText(MainListView.this, "end of method", Toast.LENGTH_SHORT).show();
}
});
View.draw(Canvas) draws the View onto the Canvas, not vice versa like you seem to expect.
If you want to do it along the lines that you already are, you need to extend an existing View class, likely TextView or ImageView, and override onDraw(), as explained in the Custom Components Dev Guide.
I think what I would do is use something like a FrameLayout and set it to contain either the appropriate TextView or ImageView as necessary. That seems cleaner than manually rendering text in an ImageView.
You could create the Canvas from the Bitmap, and set the Bitmap as the Image for your ImageView.
Bitmap img = Bitmap.createBitmap( 60, 60, Config.ARGB_8888);
Canvas c = new Canvas(img);
Paint myPaint = new Paint();
myPaint.setTypeface(mFace);
myPaint.setColor(android.R.color.black);
myPaint.setTextSize(2);
myPaint.setTextAlign(Paint.Align.LEFT);
String content = "testing";
c.drawText(content, 0,0, myPaint);
ImageView view2 = (ImageView) view;
view2.setImageBitmap(img);
Toast.makeText(MainListView.this, ""+c.getHeight(), Toast.LENGTH_SHORT).show(); //making sure c has height - this returns 60 as expected
Toast.makeText(MainListView.this, "end of method", Toast.LENGTH_SHORT).show();
Although, I believe the "right" way to do this is to use an extension of View and override the onDraw method to draw differently based on some local variables:
login_button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
((MyView)view).mContextVariable = true; //or false, etc
//you might not need this invalidate, because the click event probably causes and invalidate to be called
view.invalidate();
}
}
class MyView extends View
{
Paint myPaint;
boolean mContextVariable;
public MyView(Context context)
{
super(context);
myPaint = new Paint();
myPaint.setTypeface(mFace);
myPaint.setColor(android.R.color.black);
myPaint.setTextSize(2);
myPaint.setTextAlign(Paint.Align.LEFT);
}
#Override
protected void onDraw(Canvas canvas)
{
if(mContextVariable)
{
//draw something
}
else
{
//draw something else
}
canvas.drawText("testing", 0,0, myPaint);
}
}
Related
The Title says it all. drawline works outside the setOnClick Listener, but not inside, so I can set it to run with a button press.
//Bitmap Object creation
bitmap = Bitmap.createBitmap(600,800,Bitmap.Config.RGB_565);
//Create Canvas object and set to bitmap variable
canvas = new Canvas(bitmap);
canvas.drawColor(Color.BLACK);
paint.setColor(Color.BLUE);
paint.setStrokeWidth(50);
imageView.setImageBitmap(bitmap);
up.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick (View v) {
paint.setColor(Color.BLUE);
canvas.drawLine(100,100,100,200,paint);
}
});
Something else I want to look into is drawing multiple lines, and making sure each one lines up to the tip of the last one drawn, similar to this:
This will work for multiple buttons, but I only need it for one button right now. I hope this is sufficient information, please let me know if more is needed
I'm tearing my hair out over why my view only draws the first time. I've created a custom view that draws a bitmap for me. It's onDraw looks like this:
protected void onDraw(Canvas canvas) {
Paint p = new Paint();
canvas.drawBitmap(mBitmap, 0, 0, p);
Log.e(TAG, "CALLED");
}
Then in my main activity I set it up like this:
mDView = new drawableView(this, null);
mDView.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT));
mDView.setOnClickListener(this);
mDView.setClickable(false);
mDView.setFocusable(false);
mDView.setWillNotDraw(false);
int id = 201;
mDView.setId(id);
wm.addView(mDView, topLeftParams);
wm is my windows manager
wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
Then finally I have a call back function that gets called in my main activity:
#Override
public void onFillEvent()
{
Log.e(TAG, "onFillMain");
mDView.setBitmap(mDepth.mFrameBuffer);
mDepth.fillDepthBuffer();
int id = 201;
getParent().findViewById(id).invalidate();
mDView.invalidate();
mDView.postInvalidate();
}
I've tried all three methods to invalidate the view in the windows manager. But what happens is the first bitmap it drew stays on the screen. I never see onDraw log "CALLED" after the first time. I do see my call back getting called all the time and logging onFillMain.
I later tried adding an onLayout method to my custom view but that doesn't call and log either. I'm pretty stuck what am I missing?
In order to trigger a change in the overlay, you have to call
wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
wm.updateViewLayout(mDView, topLeftParams);
I have a custom ImageView and I am drawing background to it dynamically like:
#Override
protected void onDraw(Canvas canvas){
p.setColor(SkinHelper.getColor(getContext(), R.color.color_transparent_white));
canvas.drawPath(hexagon.getPoints(0, 0), p);
p.setColor(SkinHelper.getColor(getContext(), R.color.color_dark));
canvas.drawPath(hexagon.getPartPoints(0, 0, (int) mNumericValue), p);
super.onDraw(canvas);
}
If I set the image of the imageview in xml like
android:src="#drawable/selector_plan_cancel"
than everything works well. But I am using the support library, so I want to set the image of the imageView like
app:srcCompat="#drawable/selector_plan_cancel"
and it's not working. What should I do differently?
Try to extend AppCompatImageView instead of ImageView and keep the app:srcCompat.
I am creating an image by using Canvas- and Bitmap class. I want to set it as a background for the user. Then I want to add some more images on top of it.
this is the code for image that is supposed to be as background.
ImageView imgMap1 = (ImageView) findViewById(R.id.imgMap1);
imgMap1.setImageDrawable(new BitmapDrawable(Bitmap.createBitmap(bmp, 0, 0, 500, 500)));
and this is the code to make it as background:
LinearLayout ll = new LinearLayout(this);
ll.setBackgroundResource(R.drawable.nn);
this.setContentView(ll);
The Problem here is: When I set it as background, I can't see the other photo anymore.
How can I do this?
Thanks in advance.
The other Images are added in the Layout. they are movable by finger touch. user can reposition them by finger.
ImageView i1 = (ImageView) findViewById(R.id.Image1);
ImageView i2 = (ImageView) findViewById(R.id.Image2);
The layout is built from the top down in your XML file, or in the order you add elements in code. It sounds like your other images is being added to the layout first, either as a higher-up element in the XML file, or earlier in your code. You'll need to add the other code as context for a complete answer.
Just noticed that you can directly set Bitmap as your ImageView's content using setImageBitmap(Bitmap bm)See the Android Reference
Then let talk about your question.
First, create your own class extends the View;
Second, load background image and overlay image using Bitmap
Third, invoke onTouch event, so that the onDraw method will automatically redraw the overlay image using the coordinates returned by onTouch
Something like:
public class dragndrop extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
// using this to load your background image
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inPreferredConfig = Bitmap.Config.RGB_565; // this is not a must
bmBackground = BitmapFactory.decodeFile(filePath, opt);
super.onCreate(savedInstanceState);
DrawView dv = new DrawView(dragndrop.this);
setContentView(dv);
}
public class DrawView extends View {
Point coordinate;
public DrawView(Context context) {
super(context);
setFocusable(true); //necessary for getting the touch events
}
#Override
protected void onDraw(Canvas canvas) {
// assume you have already load your background image as bitmap
canvas.drawBitmap(bmBackground, 0, 0, null);
// assume bm is the overlay image you need to put on top,
// the method here will draw the object with the coordinate you give
canvas.drawBitmap(bm, coordinate.x, coordinate.y, null);
}
// events when touching the screen
public boolean onTouchEvent(MotionEvent event) {
int eventaction = event.getAction();
int x = (int)event.getX();
int y = (int)event.getY();
switch (eventaction ) {
case MotionEvent.ACTION_DOWN:
// add code here to determine the point user touched is within the object or not
break;
}
}
break;
case MotionEvent.ACTION_MOVE: // touch 'n' drag
// pass the touch point to your object
coordinate.x = x;
coordinate.y = y;
break;
case MotionEvent.ACTION_UP:
// touch drop - just do things here after dropping
break;
}
// redraw the canvas
invalidate();
return true;
}
}
}
This is my own snippet, please edit before use, and please let me know when your question is resolved.
I try to have a bitmap moving over my android application. I m be able to have my bitmap behind my text view, but not over them.
public void onCreate(Bundle savedInstanceState)
...
// ll is a FrameLayout
ll.addView(text1);
ll.addView(text2);
ll.addView(new Panel(this),200,400);
my Panel class is defined like this :
class Panel extends SurfaceView
......
#Override
public void onDraw(Canvas canvas) {
canvas.drawColor(0, PorterDuff.Mode.CLEAR);
Bitmap bitmap;
GraphicObject.Coordinates coords;
for (GraphicObject graphic : _graphics) {
bitmap = graphic.getGraphic();
coords = graphic.getCoordinates();
canvas.drawBitmap(bitmap, coords.getX(), coords.getY(), null);
}
}
Can you help me ? How Can i Draw a transparent bitmap over my views of my application?
I never tried myself, but what about using this?
setForeground(Drawable drawable):
Supply a Drawable that is to be
rendered on top of all of the child views in the frame layout.
The drawable should be transparent: https://developer.android.com/reference/android/graphics/drawable/ColorDrawable.html
and the color might be something like #00XXXXXX as the 2 first digits are the alpha channel.