I am going to be working on an app which requires drag/drop on a Canvas. Basically, I want to take a ShapeDrawable and convert it into a Bitmap which I can have the user drag around the screen. This is a simple exercise in itself.
However, I want to add text inside my shape. Is there a way I can add text to the drawable itself then convert to a bitmap? I looked into creating a TextView with a drawable as a background.
Is this the best way to do it? I sort of want to avoid creating TextViews in my code. Any advice is appreciated.
Edit 2/21/2013:
In response to JustDanyul's post I have the following code:
int width = 40;
int height = 40;
Bitmap.Config config = Bitmap.Config.ARGB_8888;
bitmap = Bitmap.createBitmap(width, height, config);
Canvas canvas = new Canvas(bitmap);
Resources res = context.getResources();
Drawable shape = res.getDrawable(R.drawable.miss_scarlet);
shape.draw(canvas);
Paint paint = new Paint();
paint.setTextSize(fontSize);
paint.setColor(Color.BLACK);
canvas.drawText(gameToken.getDbName(), 5, 5, paint);
My drawable is not showing up when I draw the bitmap on another canvas. The drawable itself is fine (I tested it as a background to a TextView). The text shows up. Am i missing something in this code?
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:radius="4dp" />
<solid
android:color="#FF0000" />
<stroke
android:width="3dp"
android:color="#000000" />
</shape>
Edit #2 2/21/2013:
I added:
shape.setBounds(0, 0, bitmap.getWidth(), bitmap.getHeight());
to my code and now the drawable appears but my text is gone (or just hidden).
I would suggest you to try something like this, first, create an empty bitmap:
int w = 500
int h = 500; // or whatever sizes you need
Bitmap.Config config = Bitmap.Config.ARGB_8888;
Bitmap bitmap = Bitmap.createBitmap(w, h, config);
Next step, create a new canvas instance, which renders onto your newly created bitmap
Canvas canvas = new Canvas(bitmap);
Now, you can draw the ShapeDrawable onto your empty bitmap using the ShapeDrawable's draw method
myshapedrawable.draw(canvas);
Finally, you can use the drawText method of the canvas instance to draw your text on the canvas.
Related
In my android layout I am setting the background image so that it has a faded look (alpha) by referring to another xml like this:
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/contraintLayout1"
...
android:background="#drawable/bg_fade"
bg_fade.xml then defined like this:
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="#drawable/background"
android:alpha="0.3"/>
where background is my actual jpg image in my drawables folder.
This works fine, and I get the faded look I want.
Now I need to change the actual background image depending on the user preference.
I know I can do this in code for setting a new like this:
contraintLayout1.setBackgroundResource(R.drawable.new_background)
But then I no longer have the faded look, just the "raw" image.
So I somehow need to change the src value in the bg_fade.xml file. But I don't know how I can do this in code.
Can somebody please help?
(PS. I am coding in Kotlin)
you can first define a method for change transparency of images like this
public Bitmap changeTransparency(int src, int value) {
Bitmap bMap = BitmapFactory.decodeResource(getResources(),src);
int width = bMap.getWidth();
int height = bMap.getHeight();
Bitmap transBMap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
Canvas canvas = new Canvas(transBMap);
canvas.drawARGB(0, 0, 0, 0);
final Paint paint = new Paint();
paint.setAlpha(value);
canvas.drawBitmap(bMap, 0, 0, paint);
return transBMap;
}
and then set the returned value to your view's background like this code
view.setBackgroundImage(changeTransparency(R.drawable.new_nackground, ALPHA_VALUE));
i hope be helpful
This album explains what I want to do, and the problem I'm having when the vector doesn't resize: http://imgur.com/a/HM3K2
This is the approach I've taken to try scaling the vector, but it doesn't seem to work:
private Bitmap drawCirclePreview(int color, Shape square) {
//An object from my 'VectorOverlay' class which resolves the resource...
VectorOverlay circleOverlay = new VectorOverlay(color);
//...and returns a drawable
Drawable drawable = circleOverlay.drawCircleOverlay(this);
Bitmap bitmap;
//Make bitmap with same dimensions as the square (redundant, I know)
bitmap = Bitmap.createBitmap(square.getWidth(), square.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
}
Inside the VectorOverlay method that is being used:
public Drawable drawCircleOverlay(Context context){
Drawable drawable = ContextCompat.getDrawable(context, R.drawable.circle_overlay);
drawable = DrawableCompat.wrap(drawable);
DrawableCompat.setTint(drawable, color);
return drawable;
Then I create layers for the new LayerDrawable:
private void drawSquarePreview(){
Drawable[] layers = new Drawable[2];
//[...] omitting code for when the square object is created and drawn
layers[0] = new BitmapDrawable(squareBmp);
layers[1] = new BitmapDrawable(drawCirclePreview(Color.parseColor("#4af9d8"), square));
LayerDrawable layerDrawable = new LayerDrawable(layers);
ivPreview.setImageDrawable(layerDrawable);
}
Yet, the outcome is still as the pictures show. I'm stumped. I've been searching for answers for a long time now and I still can't find a solution. Any help would be greatly appreciated.
ADDITIONAL INFO: I'm using the Support Library to handle vector drawables on older APIs.
There is no need to use a vector for this. Vectors are slower and messier. You can simply create a circle shape (Drawable) in XML.
Like this;
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="#FF000000"/>
<size android:width="40dp"
android:height="40dp"/>
</shape>
Just remember that the size variable is a relative size, but the shape can be scaled to any size. I set the color to black, as that way you can tint it to any color.
I'm trying to change the color in the shape of an appWidget. I have a rectangle with corners, my goal is to change the background(solid) color and the border colors.
My widget layout is a RelativeLayout with an ImageView for the background, the src attribute of this ImageView is this shape :
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<corners
android:radius="5dp"
android:topRightRadius="5dp"
android:bottomRightRadius="5dp"
android:bottomLeftRadius="5dp" />
<stroke
android:width="1dp"
android:color="#android:color/white" />
<solid android:color="#color/transparent"/>
</shape>
Here is what I'm trying to do when I try to change the background color :
RoundRectShape sd = new RoundRectShape(new float[]{30,30,30,30,30,30,30,30}, null, null);
bmp_bg = Bitmap.createBitmap(200, 20, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(bmp_bg);
Paint p = new Paint();
p.setColor(0xFF0000FF);
sd.draw(c, p);
remoteViews.setImageViewBitmap(R.id.imageClock, bmp_bg);
But the background doesn't change. Is this a good way to do that ? Or am I completly wrong ?
thx
EDIT :
I tried this too without any effect :
CustomShapeClockWidget cscw = new CustomShapeClockWidget(0xFF0000FF, 0xFFFF0000);
bmp_bg = Bitmap.createBitmap(200, 20, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(bmp_bg);
cscw.draw(c);
remoteViews.setImageViewBitmap(R.id.imageClock, bmp_bg);
with the class CustomShapeClockWidget being :
public class CustomShapeClockWidget extends ShapeDrawable {
private int bgColor, strokeColor;
private Paint fillPaint, strokePaint;
public CustomShapeClockWidget(int bgColor, int strokeColor){
this.bgColor = bgColor;
this.strokeColor = strokeColor;
}
#Override
protected void onDraw(Shape shape, Canvas canvas, Paint paint){
fillPaint = this.getPaint();
strokePaint = new Paint(fillPaint);
fillPaint.setColor(bgColor);
strokePaint.setStyle(Paint.Style.STROKE);
strokePaint.setStrokeWidth(1.0f);
strokePaint.setColor(strokeColor);
shape.draw(canvas, fillPaint);
shape.draw(canvas, strokePaint);
}
}
(Late answer, hope it helps anyone struggling with shapes in appwidgets like me)
The first code you wrote is almost complete, it just lacks the call to resize(float, float) necessary before draw(Canvas, Paint). There is no need to create a custom shape object.
The SDK documentation says this for RoundRectShape and other shapes:
Draw this shape into the provided Canvas, with the provided Paint.
Before calling this, you must call resize(float, float).
I am working in an android application and I want to place an ImageView in a particular position in my view. For that I applied the particular code and worked successfully :
ImageView image = (ImageView) findViewById(R.id.imageView1);
Bitmap bMap = BitmapFactory.decodeResource(getResources(), R.drawable.mrng);
Matrix mat = new Matrix();
mat.postRotate(350);
Bitmap bMapRotate = Bitmap.createBitmap(bMap, 0, 0, bMap.getWidth(),bMap.getHeight(), mat, true);
image.setImageBitmap(bMapRotate);
Now I want to set a border to this image. For that I made a an shape xml and I have set as the background of the image view.
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#FFFFFF" />
<stroke android:width="3dp" android:color="#000000" />
</shape>
But when I gave the background of the image view the shape it does not give the correct output.please help me.
I do not want a border around the ImageView, but rather border around the rotated image.
EDIT: I'm completely rewriting my answer based on the clarification of the question. Here's how I achieved what you want. The idea is to draw the frame and then rotate:
ImageView image = (ImageView) findViewById(R.id.TestImage);
Bitmap bMap = BitmapFactory.decodeResource(getResources(), R.drawable.image);
final int BORDER_WIDTH = 3;
final int BORDER_COLOR = Color.BLACK;
Bitmap res = Bitmap.createBitmap(bMap.getWidth() + 2 * BORDER_WIDTH,
bMap.getHeight() + 2 * BORDER_WIDTH,
bMap.getConfig());
Canvas c = new Canvas(res);
Paint p = new Paint();
p.setColor(BORDER_COLOR);
c.drawRect(0, 0, res.getWidth(), res.getHeight(), p);
p = new Paint(Paint.FILTER_BITMAP_FLAG);
c.drawBitmap(bMap, BORDER_WIDTH, BORDER_WIDTH, p);
Matrix mat = new Matrix();
mat.postRotate(350);
Bitmap bMapRotate = Bitmap.createBitmap(res, 0, 0, res.getWidth(), res.getHeight(), mat, true);
image.setImageBitmap(bMapRotate);
And here's the screenshot of the result:
There is way to put border around ImageView even any view in android. In XML put Four simple <View>'s on each side of the imageview. And these view's can be assigned any type of style. You can use relative layout in which you can place four borders easily around image view.
Kinda lengthy process but works.
On the emulator, newBitmap (see below) is transparent. I update newBitmap with data from another bitmap. Updated area appears whenever I call to draw newBitmap.
On the phone, I see a black screen. I set the alpha of newBitmap to 0 and it showed defaultbg. How can I achieve the same result that I get on the emulator?
background and background2 are bitmaps:
defaultbg = background;
newBitmap = Bitmap.createBitmap(background2.getWidth(), background2.getHeight(), background2.getConfig());
I update newBitmap like this:
int [] pixels = new int[width * height];
background2.getPixels(pixels, 0, width, cell.getX(), cell.getY(), width, height);
newBitmap.setPixels(pixels, 0, width, cell.getX(), cell.getY(), width, height);
I draw them like this:
canvas.drawBitmap(defaultbg, offset, 0, null);
canvas.drawBitmap(newBitmap, offset, 0, null);
create xml file in drawable with this source
< ?xml version="1.0" encoding="utf-8"?>
< shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#00000000" />
< /shape>
then give xml file name in your layout or wherever
android:background="#drawable/kbb_border"