Custom ImageView background draw with app:srcCompat - java

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.

Related

onDraw not called in a custom view added to overlay with windows manager

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);

How to create a drawable from Java in Android?

How can i create a rectangle drawable with border only not filling the color from code not from XML...
Is there any way to accomplish this using code?
Really Appreciate your helps...
Thanks #Xaver and #Vipul for the Answer :D
EDIT:
You can create a Drawable with a border around it just like #vipulmittal suggested by using a GradientDrawable.
GradientDrawable drawable = new GradientDrawable();
drawable.setStroke(width, Color.RED);
EDIT2:
The setBackground method is for API level 16 and up and setBackgroundDrawable is used for anything below API level 16. So what you have to do is something like this:
// Build.VERSION_CODES.JELLY_BEAN is API LEVEL 16
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
imageView.setBackground(drawable);
} else {
imageView.setBackgroundDrawable(drawable);
}
I tend to create a helper method for cases like this:
public static void setBackground(ImageView imageView, Drawable drawable) {
// Build.VERSION_CODES.JELLY_BEAN is API LEVEL 16
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
imageView.setBackground(drawable);
} else {
imageView.setBackgroundDrawable(drawable);
}
}
And then everytime you set the background of a ImageView you just have to call:
ImageViewHelper.setBackground(imageView, drawable);
You can create a Bitmap with a solid color like this:
Bitmap bitmap = Bitmap.createBitmap(1, 1, Config.ARGB_8888);
bitmap.setPixel(0, 0, Color.BLUE); // Set color to blue
Bitmap resultBitmap = Bitmap.createScaledBitmap(bitmap, width, height, true);
bitmap.recycle();
You can than wrap it with BitmapDrawable if you really need a Drawable but I can't really tell from your question what you need it for.
BitmapDrawable drawable = new BitmapDrawable(resultBitmap);
EDIT:
You can create a Drawable with a border around it just like #vipulmittal suggested by using a GradientDrawable.
GradientDrawable drawable = new GradientDrawable();
drawable.setStroke(width, Color.RED);
EDIT2:
The setBackground method is for API level 16 and up and setBackgroundDrawable is used for anything below API level 16. So what you have to do is something like this:
// Build.VERSION_CODES.JELLY_BEAN is API LEVEL 16
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
imageView.setBackground(drawable);
} else {
imageView.setBackgroundDrawable(drawable);
}
I tend to create a helper method for cases like this:
public static void setBackground(ImageView imageView, Drawable drawable) {
// Build.VERSION_CODES.JELLY_BEAN is API LEVEL 16
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
imageView.setBackground(drawable);
} else {
imageView.setBackgroundDrawable(drawable);
}
}
And then everytime you set the background of a ImageView you just have to call:
ImageViewHelper.setBackground(imageView, drawable);
You can simply create a gradient drawable object and set stroke to it.
GradientDrawable gd=new GradientDrawable();
gd.setStroke(1, Color.RED);
Just set this as background of any view and it will draw border to the view.

Problems drawing text onto an ImageView using a Canvas

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);
}
}

shrinking surfaceview to be in a box

I would like to change the current SurfaceView in my app from
to
Is there a way to do this without using main.xml at all?
I'm trying to code the GUI in run-time. I can achieve the current SurfaceView (top picture) by overriding onMeasure() and using setMeasuredDimension(), but I would like to achieve the bottom picture. The green area is the rest of the screen.
EDIT:
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
this.setMeasuredDimension(500, 300);
param.gravity = Gravity.CENTER_VERTICAL;
}
Have you tried using the android:layout_gravity-attribute to center your View in the Layout?
The corresponding class would be FrameLayout.LayoutParams, possible gravity's are listed here. The code could then look something like this:
FrameLayout f = new FrameLayout(this);
ImageView test = new ImageView(this);
f.addView(test, new FrameLayout.LayoutParams(500, 300, Gravity.CENTER));

Transparent View with Android

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.

Categories