How to create a drawable from Java in Android? - java

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.

Related

Recyclerview is Laggy?

I am following the tutorial in this link to learn about RecyclerView. The tutorial loads images from drawable folder. When I do the same the app just runs out of memory. So I made a little change to resize images.
#Override
public void onBindViewHolder(MyAdapter.ViewHolder viewHolder, int i) {
viewHolder.title.setText(galleryList.get(i).getImage_title());
viewHolder.img.setScaleType(ImageView.ScaleType.CENTER_CROP);
viewHolder.img.setImageResource((galleryList.get(i).getImage_ID()));
}
Changed the 3rd line to this
viewHolder.img.setImageDrawable(scaleImage(galleryList.get(i).getImage_ID(), ScaleFactor));
And defined scaleImage as
private Drawable scaleImage(int imageId, float scaleFactor)
{
Drawable image = context.getResources().getDrawable(imageId);
if ((image == null) || !(image instanceof BitmapDrawable)) {
return image;
}
Bitmap b = ((BitmapDrawable)image).getBitmap();
int sizeX = Math.round(image.getIntrinsicWidth() * scaleFactor);
int sizeY = Math.round(image.getIntrinsicHeight() * scaleFactor);
Bitmap bitmapResized = Bitmap.createScaledBitmap(b, sizeX, sizeY, false);
image = new BitmapDrawable(context.getResources(), bitmapResized);
return image;
}
But as I scroll RecyclerView lags until It loads the coming rows which I think is because I load each image individually and then resize it. Is there a way to do this asychronously?
It's become cause you are resizing the image, it's a heavy process.
try to resize images async or use image loader libs.
There are some useful libraries you can use for loading images like Glide
Also, you can see this Picasso v/s Imageloader v/s Fresco vs Glide

Custom ImageView background draw with app:srcCompat

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.

Add an image as background and put other images on top of it

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.

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

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