Hello I am trying to make the bitmap to rounded shape programmatically but I see that in new phone it is less rounded then same APK I installed there I see more rounded corners in old phone. See in the screenshot
Sony Z Xperia 4.3
Samsung Y Dous 2.3
I could not understand why it so displaying different border radius somewhat more rounded and less rounded in another device. Any idea how I can resolve this to make same for all devices.
Code :
public class RoundedCornersDrawable extends BitmapDrawable {
private final BitmapShader bitmapShader;
private final Paint p;
private final RectF rect;
private final float borderRadius;
public RoundedCornersDrawable(final Resources resources, final Bitmap bitmap) {
super(resources, bitmap);
bitmapShader = new BitmapShader(getBitmap(), Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
p = getPaint();
p.setAntiAlias(true);
p.setShader(bitmapShader);
final int w = (int) (resources.getDisplayMetrics().widthPixels) - (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, 35, resources.getDisplayMetrics());
final int h = 200;
rect = new RectF(0, 0, w, h);
borderRadius = 15;
}
#Override
public void draw(final Canvas canvas) {
canvas.drawRoundRect(rect, borderRadius, borderRadius, p);
}
}
Thanks in advance
I guess that has to do with the different screen densities of the devices (how many pixel are in one inch of the screen). One pixel is not the same size on the screen on all devices. Here's some info about supporting multiple screens. You should also have a look at DisplayMetrics, there you can get the current screen density that you should add to you height and radius calculations.
Alternatively, you could use the display width as basis for the height and the radius calculation. Right now you are using a fix amount of 200 and 15 pixel.
Something like this:
h = w/10;
borderRadius = h / 3;
Related
Background
I have an ImageView which is used to display previews of a file.
I would like to have the ImageView with a checkerboard background, so that when a file with transparency is rendered on top (such as PNG and SVG files) the checkerboard shows through on the transparent parts.
I have found lots of questions on StackOverflow on how to create the checkered background and this question is not entirely specific to that.
I am currently doing it in code. I create a 2 by 2 bitmap (top left/bottom right are one colour, top right, bottom left are the other colour) where the size of each box is specified. Then i create the main bitmap by drawing this small bitmap repeatedly.
int checkeredBackgroundSquareSize= 16;
private static Bitmap getCheckeredBitmap(int size) {
size = (size > 0) ? size : DEFAULT_SQUARE_SIZE;
int colorOne = ContentApplication.appCtx().getColor(R.color.checkerboard_background_color_one);
int colorTwo = ContentApplication.appCtx().getColor(R.color.checkerboard_background_color_two);
// width/height is twice the size of the individual squares
Bitmap squareBitmap = Bitmap.createBitmap(size*2, size*2, Bitmap.Config.ARGB_8888);
Paint bitmapPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
bitmapPaint.setStyle(Paint.Style.FILL);
Canvas canvas = new Canvas(squareBitmap);
// draw 2 rectangles on 2 rows
// top left and bottom right are the first colour
// top right and bottom left are the second colour
// set colour for top left/bottom right squares
bitmapPaint.setColor(colorOne);
// Square 1 : top left
Rect rect = new Rect(0, 0, size, size);
canvas.drawRect(rect, bitmapPaint);
// Square 2 : bottom right
rect.offset(size, size);
canvas.drawRect(rect, bitmapPaint);
// change colour for top right/bottom left squares
bitmapPaint.setColor(colorTwo);
// Square 3 : top right
rect.offset(-size, 0);
canvas.drawRect(rect, bitmapPaint);
// Square 4: bottom left
rect.offset(size, -size);
canvas.drawRect(rect, bitmapPaint);
return squareBitmap;
}
I then create a Bitmap the size of my preview image, and use the checkered background bitmap to repeatedly draw on the canvas before the preview image is added on top.
// Create a Bitmap to render our SVG to
Bitmap bitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888);
// Create a Canvas to use for rendering
Canvas canvas = new Canvas(bitmap);
// If we don't specify a viewport box, then AndroidSVG will use the bounds of the Canvas
// as the viewport. So a scale of 1.0 corresponds to that size
canvas.scale(scaling,scaling );
// create the checkered background, indicating transparency
Bitmap square = getCheckeredBitmap(checkeredBackgroundSquareSize);
BitmapShader shader = new BitmapShader(square, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
Paint paint = new Paint();
paint.setShader(shader);
// in your draw method
canvas.drawRect(0, 0, bitmapWidth, bitmapHeight, paint);
The issue
My previews can be different sizes, for example 100x100, 6000x2000 etc As i am creating the initial bitmap on these sizes, the final image for the files all render looking like the squares on the checkered background are different sizes.
I need to have the checkerboard look exactly the same regardless of the overlaid image's size.
Is there a way to set a background image for an ImageView to be an image. I can only see how to set it to a drawable and I can not see how to define a checkboard as an xml drawable.
Mike M gave the answer that solved my issue. See Mike's comments to the first post
Create your own Drawable that renders the checkerboard
public class CheckerboardDrawable extends Drawable {
// I inadvertently ran the example image with Paint.ANTI_ALIAS_FLAG, but
// we actually don't want that 'cause we're looking for crisp, clean lines.
private final Paint paint = new Paint();
private int checkeredBackgroundSquareSize = 16;
private int colorOne = Color.LTGRAY;
private int colorTwo = Color.WHITE;
#Override
public void draw(#NonNull Canvas canvas) {
final Rect bounds = getBounds();
final int squareSize = checkeredBackgroundSquareSize;
final int columns = bounds.width() / squareSize + 1;
final int rows = bounds.height() / squareSize + 1;
canvas.translate(bounds.left, bounds.top);
for (int c = 0; c < columns; c++) {
for (int r = 0; r < rows; r++) {
paint.setColor((c + r) % 2 == 0 ? colorOne : colorTwo);
final int x = c * squareSize;
final int y = r * squareSize;
canvas.drawRect(x, y, x + squareSize, y + squareSize, paint);
}
}
canvas.translate(-bounds.left, -bounds.top);
}
#Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
#Override
public void setAlpha(int alpha) {}
#Override
public void setColorFilter(#Nullable ColorFilter colorFilter) {}
}
Then add the drawable to the ImageView
final ImageView imageView = findViewById(R.id.image);
imageView.setBackground(new CheckerboardDrawable());
In my app I need to draw circles using bitmap and the drawCircle() method.
Everything was working fine and exactly as it should up until Android 6.0.
It still draws circles on all the previous versions, but draws rectangles when I use the app on 6.0. But if I change it to be filled, it draws a circle both in api 22 and api 23.
Anyone has the same problem or any idea why this happens?
Here is the source code and a screenshot (app running on API 23 on the left, and API 22 on the right). same app on different api's
public final class Circle1View extends View {
private float xCenter, yCenter;
private Bitmap grid = null;
public Circle1View (Context context) {
super(context);
init();
}
private void init() {
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
#Override
protected void onDraw(Canvas canvas) {
int w = getWidth();
int h = getHeight();
xCenter = w / 2;
yCenter = h / 2;
drawBitmaps(w, h);
canvas.translate(xCenter, yCenter);
canvas.scale(xCenter, yCenter);
canvas.drawBitmap(grid, null, new RectF(-1, -1, 1, 1), null);
}
private void drawBitmaps(int w, int h) {
grid = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas();
canvas.translate(xCenter, yCenter);
canvas.scale(xCenter, yCenter);
Paint gridPaint = new Paint();
gridPaint.setStrokeWidth(0.01f);
// Works with FILL
// gridPaint.setStyle(Paint.Style.FILL);
gridPaint.setStyle(Paint.Style.STROKE);
canvas.setBitmap(grid);
canvas.drawCircle(0, 0, 0.5f, gridPaint);
}
}
I think it has something to do with the scaling and translation you do. Imagine the circle that is drawn is so small, it only takes 4 pixels. When enlarging this back to the full size, you are left with 4 straight lines between these pixels.
When I change the stroke width to 0.04f, the issue is gone. I would suggest you simplify your code by drawing on the supplied Canvas directly:
#Override
protected void onDraw(Canvas canvas) {
int w = getWidth();
int h = getHeight();
xCenter = w / 2;
yCenter = h / 2;
Paint gridPaint = new Paint();
gridPaint.setStrokeWidth(1f);
gridPaint.setStyle(Paint.Style.STROKE);
canvas.drawCircle(xCenter, yCenter, w/4, gridPaint);
}
As for your question about the difference between API levels: Marshmallow introduced changes for drawBitmap(). You can have a look at the respective source code for Lollipop and Marshmallow.
So, recently me and my two teammates started on our exam project. Which is a basic 2D skijumping game.
We've done programming on android before but never in relation to games and we have the basic techniques down for creating animations using a thread and all that. But we seem to have a scaling issue.
Currently we have a background image in the drawable folder in the resolution 1920x1080, we are using BitmapFactory to scale the background image to the users screen size, which seems to be working fine it fits perfectly on all our 3 different smartphones.
Were creating an animation of the player sprite skiing down the hill and jumping off the edge, which looks very funny and works perfectly. For this I simply divided the screen width and height by 100 and used that percentage of either 1% screen width to move him at certain speeds on the x-axis and likewise on the y-axis with the 1% of the screen height.
It works on most phones but, for some reason it won't work on all of them? I don't understand why not? I mean the math should always work shouldn't it? On some phones he skies outside of the hill in the air and not on the proper trajectory. I don't get what I'm missing but I'm suspecting it has something to do with the screen format or something?
Can anyone enlighten me on this? Please keep in mind this is our first android game so were new at game dev.
And thanks for all your input if you have any in advance.
try this:
class V extends View implements Callback {
private Bitmap mBitmap;
private Matrix mMatrix;
private Handler mHandler;
private float mX;
private Paint mPaint;
public V(Context context) {
super(context);
Resources res = getResources();
mBitmap = BitmapFactory.decodeResource(res, R.drawable.layer0);
mMatrix = new Matrix();
mHandler = new Handler(this);
mHandler.obtainMessage(0).sendToTarget();
mPaint = new Paint();
mPaint.setColor(0xff00ff00);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
RectF src = new RectF(0, 0, mBitmap.getWidth(), mBitmap.getHeight());
RectF dst = new RectF(0, 0, w, h);
mMatrix.setRectToRect(src, dst, ScaleToFit.CENTER);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.concat(mMatrix);
canvas.drawBitmap(mBitmap, 0, 0, null);
canvas.drawRect(mX, 20, mX + 20, 40, mPaint);
}
#Override
public boolean handleMessage(Message msg) {
msg = mHandler.obtainMessage(0);
if (mX < mBitmap.getWidth()) {
mX += 1.5f;
mHandler.sendMessageDelayed(msg, 50);
} else {
Log.d(TAG, "handleMessage stop");
}
invalidate();
return true;
}
}
I am trying to create an Oval Bitmap and I need to get a feather effect around the margins,
Does anyone have any idea How I can achieve this ?
Thanks.
You could consider the 'feather effect' as a gradial gradient, with the alpha fading from 100% to 0%.
Android offers the RadialGradient class for this purpose. You'll want to use the constructor where you can specify the control points for the radient, as you'll want the fading to start near the edge, not in the middle.
The one problem with Android's RadialGradient class is that it only supports perfect circles, not for ovals. To compensate for this, we'll just draw a perfect circle and scale afterwards.
Example code:
private Bitmap makeFeatheredOval(int width, int height) {
// Determine largest dimension, use for rectangle.
int size = Math.max( width, height);
RadialGradient gradient = new RadialGradient(size / 2, size / 2, size / 2,
new int[] {0xFFFFFFFF, 0xFFFFFFFF, 0x00FFFFFF},
new float[] {0.0f, 0.8f, 1.0f},
android.graphics.Shader.TileMode.CLAMP);
Paint paint = new Paint();
paint.setShader(gradient);
Bitmap bitmap = Bitmap.createBitmap(size, size, Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
canvas.drawCircle(size / 2, size / 2, size / 2, paint);
// Scale the bitmap, creating an oval
bitmap = Bitmap.createScaledBitmap(bitmap, width, height, true);
return bitmap;
}
Example image (it's the oval "moon" in the upper left corner):
Bonus points for everyone who recognizes that backdrop image.
I want to get an animated text in Android where it should run from left to right on the screen.
Eg.
I want to get this text
private static final String QUOTE =
"Nobody uses Java anymore. It's this big heavyweight ball and chain.";
running from right to left using animation.
However, this text gets truncated to "Nobody uses Java anymore. It's" in Portrait mode and to
"Nobody uses Java anymore. It's this big heavyweight" in landscape mode.
This is the code that I have used
Paint paint = new Paint();
paint.setColor(Color.BLUE);
private static final String QUOTE =
"Nobody uses Java anymore. It's this big heavyweight ball and chain.";
paint.setTextSize(20);
paint.setAntiAlias(true);
int len= QUOTE.length();
canvas.scale(1,-1);
canvas.drawText(QUOTE, 0, len-1, 100, 60, paint);
canvas.drawText(QUOTE,0,100 , paint);
createAnim(canvas);
private void createAnim(Canvas canvas) {
anim2= new TranslateAnimation(500,-500,30,30);
anim2.setRepeatCount(Animation.INFINITE);
anim2.setInterpolator(new AccelerateDecelerateInterpolator());
anim2.setRepeatMode(Animation.RESTART);
anim2.setDuration(1000L);
startAnimation(anim2);
}
How to do Text Animations using Android SDK?
Please refer this post for text animations.
Please check height and width of canvas ,
// Custom Font Text
Bitmap bitmap = Bitmap.createBitmap((int) getWindowManager()
.getDefaultDisplay().getWidth(),
(int) getWindowManager().getDefaultDisplay()
.getHeight() / 2, Bitmap.Config.ARGB_8888);
canvas = new Canvas(bitmap);
drawingImageView.setImageBitmap(bitmap);
paint = new Paint();
paint.setColor(Color.BLACK);
paint.setTextSize(150);
Typeface chops = Typeface.createFromAsset(this.getAssets(),
"WC_Speed_Bold_Bta.ttf");
paint.setTypeface(chops);
int xPos = (canvas.getWidth() / 2);
int yPos = (int) ((canvas.getHeight() / 2) - ((paint.descent() + paint
.ascent()) / 2));
canvas.drawText("Hello", xPos, yPos, paint);