Let's say I have a horizontally long image, "grass". Now, I want to use it as a background image for views, but I want to dock it to the bottom. After searching the web, I discovered that I need to wrap the image as a drawable like:
<?xml version="1.0" encoding="utf-8"?>
<bitmap
xmlns:android="http://schemas.android.com/apk/res/android"
android:src="#drawable/grass"
android:gravity="bottom|left" />
The problem is that the image is clipped to the right. So I have tried bottom|left|right but then the aspect ratio was not kept. Can I make the image fit horizontally, but keep the aspect ratio by automatically scaling it vertically? Or is this not possible with drawables?
what your searching for is centerInside ScaleType . please remove the ScaleType from the ImageView and try this :
public static synchronized Bitmap centerInside(Bitmap bitmap,int width,int height){
if(bitmap.getWidth() == bitmap.getHeight()){
Log.i("crop","already matched");
return Bitmap.createScaledBitmap(bitmap, width, height, true);
}
//int size = width > height ? width : height;
float scale = ImageUtils.calculateImageSampleSize(bitmap.getWidth(), bitmap.getHeight(),width,height);
width = (int) ((float)bitmap.getWidth() / scale);
height = (int) ((float)bitmap.getHeight() / scale);
bitmap = Bitmap.createScaledBitmap(bitmap, width, height, true);
if (bitmap.getWidth() >= bitmap.getHeight()){
bitmap = Bitmap.createBitmap(
bitmap,
bitmap.getWidth()/2 - bitmap.getHeight()/2,
0,
bitmap.getHeight(),
bitmap.getHeight()
);
}else{
bitmap = Bitmap.createBitmap(
bitmap,
0,
bitmap.getHeight()/2 - bitmap.getWidth()/2,
bitmap.getWidth(),
bitmap.getWidth()
);
}
return bitmap;
}
You cannot achieve this with XML only. If you don't want to have to draw the bitmap programmatically, you wrap an ImageView in a RelativeLayout and set the ImageView's scaleType property:
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ImageView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:src="#drawable/grass"
android:scaleType="fitXY" />
</RelativeLayout>
If I understand Your requirement right Your image need to stretch vertically and be in bounds horizontally.
A good solution I could suggest is creating a 9 patch image out of Your drawable and define the area where the image can stretch.
You can use this tutorial for reference.
Related
I have a cardview with an ImageView aligned to bottom left.
I am getting the height of the ImageView and setting it as the height of the bitmap.
iv.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
int height = iv.getMeasuredHeight();
Paint widthPaint = new Paint();
widthPaint.setTextSize(200f);
float width = widthPaint.measureText(text);
Bitmap bmOverlay = Bitmap.createBitmap((int) width + S.dpToPx(ctx, 20), height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bmOverlay);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStyle(Paint.Style.FILL);
canvas.drawColor(Color.argb(220, 244, 244, 244));
paint.setColor(Color.TRANSPARENT);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
paint.setTextSize(200f);
paint.setTextAlign(Paint.Align.CENTER);
canvas.drawText(text, canvas.getWidth() / 2, (canvas.getHeight() / 2) - ((paint.descent() + paint.ascent()) / 2), paint);
iv.setImageBitmap(bmOverlay);
}
});
The output of both iv.getMeasuredHeight(); and bmOverlay.getHeight() is 120. But the bitmap is not covering the ImageView. I cannot understand why.
XML of the ImageView.
<ImageView
android:id="#+id/rquiz_iv_topic"
android:layout_width="80dp"
android:layout_height="40dp"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"/>
What you want to archive: Set ImageView exactly size with the Bitmap is something wrong.
You needs to fits all the phone screen instead of settings it View by pixel.
You can:
1. Respect Parent Way:
Put ImageView in LinearLayout, Set Weight as 0.5 (means fits 50% of LinearLayout), and set related (Vertical or Horizontal) Height or Width to 0dp(to let Layout Manager to handles the size).
And, set your image scale to fitXY / centerCrop.(Or you can try other scaling)
2.Respect Bitmap Way:
Put ImageView in RelativeLayout, set other nearby Views to stand with ImageView by layout_alignBottom/layout_alignLeft etc. And set ImageView Height and/or Width to wrap_content, let the Layout handles the size.
In your imageview set scaleType="centerInside" and adjustViewBounds="true".
<ImageView
android:id="#+id/rquiz_iv_topic"
android:layout_width="80dp"
android:layout_height="40dp"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:adjustViewBounds="true"
android:scaleType="centerInside"
/>
Refer for more details ImageView.ScaleType
I have an image like this->
And I want to show like this->
Then I can choose how much I can see(0~1,0=can not see,1=Whole picture,0.5=half picture,....etc,read from user input)
How to do that?
I tried to use android:scaleType but it is not working.
My best suggestion is to wrap your BitmapDrawable with a ClipDrawable.
ClipDrawable lets you define clipping for any other drawable, so instead of drawing the entire drawable, only a part of it will be drawn.
How would that work? Your ImageView can display a drawable - assignable through setImageDrawable(). Naturally, you would place a BitmapDrawable of your image bitmap there. If you wrap your BitmapDrawable first with ClipDrawable, and only then assign to the ImageView, you should be fine.
<ImageView
android:id="#+id/imageView1"
android:layout_width="100dp"
android:layout_height="100dp"
android:src="#drawable/clip_source" />
and this is clip_source drawable:
<?xml version="1.0" encoding="utf-8"?>
<clip xmlns:android="http://schemas.android.com/apk/res/android"
android:clipOrientation="vertical"
android:drawable="#drawable/your_own_drawable"
android:gravity="top" />
You can define the amount of clipping by calling the function setLevel() on your ClipDrawable (clip_source). A level of 0 means the image is completely hidden and a level of 10000 means the image is completely revealed. You can use any int value in the middle.
You'll have to set the level in code, so your code should first get a reference to the ClipDrawable. You can do this by running getDrawable() on your ImageView instance. When you have a reference to your ClipDrawable, simply run setLevel(5000) on it (or any other number 0-10000).
ImageView img = (ImageView) findViewById(R.id.imageView1);
mImageDrawable = (ClipDrawable) img.getDrawable();
mImageDrawable.setLevel(5000);
here is another way to achieve this
public static Bitmap getScaleBitmap(Bitmap bitmap) {
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
bitmap.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = 0xff424242;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()/2);
final RectF rectF = new RectF(rect);
final float roundPx = 0;
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
}
Here in below line
final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()/2);
set hight as you require..
Enjoy :)
I've achieved this by setting the scrollY on my ImageView in the markup. From android's documentation, clearly this is not an option if you're dealing with devices running less than API 14. Also, in my case, I'm using fixed size images that I'm loading based on application state, so they're always the same size. As such, I'm able to just implement it in markup. I realize this approach won't work for everyone.
I wrap the image in a layout that's half as tall as the icon and intentionally have the icon's size at it's actual size. Without the scrollY set, it displays only the top half of the image. Setting the scrollY moves it to where I want it - displaying only the lower half of the image.
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="horizontal"
android:gravity="center_horizontal">
<ImageView
android:id="#+id/icon"
android:layout_width="100dp"
android:layout_height="100dp"
android:src="#drawable/default_icon"
android:scrollY="50dp" />
</LinearLayout>
So, from my example, it's only displaying the bottom half of the icon.
Here's an easy way.. Create a separate layout in your main layout just for your images. Make sure it is realitive. Now put your image view for your pictures in side the layout and make it fill parent. OK now make a blank image and add that image view to the bottom of the layout and the top to the center of the layout. Just mess with the margins and size of the imageviews till it looks the way you want it. Hope this helps.
Convert your drawable into a bitmap and crop to get top of the image to form another bitmap, then display it into your image view.
// to convert drawable to bitmap
Bitmap resource = BitmapFactory.decodeResource(context.getResources(),
R.drawable.your_resource);
// to set width of bitmap to imageview's width if necessary,
int width = imageView.getMeasuredWidth();
// to crop the bitmap to specific width and height,
resource = Bitmap.createBitmap(resource, 0, 0, width, height);
here is the code to crop image into two part
public static Bitmap getScaleBitmap(Bitmap bitmap, int check) {
final Bitmap toBeCropped = bitmap;
final BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
bitmapOptions.inTargetDensity = 1;
toBeCropped.setDensity(Bitmap.DENSITY_NONE);
int top = 0;
int bottom = 0;
int targetheight = 0;
if (check == 0) {// return 1st half of image
top = 0;
bottom = bitmap.getHeight() / 2;
} else {// return 2nd half of image
top = (bitmap.getHeight() / 2) - 10;
bottom = (bitmap.getHeight() / 2) - 10;
}
int fromHere = (int) (toBeCropped.getHeight() * 0.5);
Bitmap croppedBitmap = Bitmap.createBitmap(toBeCropped, 0, top, toBeCropped.getWidth(), bottom);
return croppedBitmap;
}
I'm trying to scale and crop image at the same time and show it from left to right screen edge. I receive image that is just little bit wider than users screen and I'm able to scale it like this (XML):
<ImageView
android:id="#+id/category_image_top"
android:layout_width="match_parent"
android:layout_height="170dp"
android:maxHeight="170dp"
android:scaleType="centerCrop"
android:adjustViewBounds="true"
android:focusable="false"
/>
But this is what I get:
I would like to align image to top right like so:
Is this possible? I've tried all scaleTypes but noting works, image is either scaled to fit by X and Y (fitXY, fitStart) or image cropped but centered (centerCrop). I need something like android:scaleType="cropStart"
<ImageView
android:id="#+id/category_image_top"
android:layout_width="match_parent"
android:layout_height="170dp"
android:maxHeight="170dp"
android:scaleType="centerCrop"
android:paddingLeft="half of your screen width"
android:paddingBottom="half of your screen height"
android:adjustViewBounds="true"
android:focusable="false"
/>
You can set padding to move image left or right and also top and bottom padding to move up and down
As I didn't find a way to deal with this situation through xml (views) I turned (as #serenskye suggested) to code. Here's my code, I hope it helps (ps: I've changed my logic a little bit, I wanted to fit image by width so I've scaled it to predefined imageWidght and then cropped it to imageHeight)
//bm is received image (type = Bitmap)
Bitmap scaledImage = null;
float scaleFactor = (float) bm.getWidth() / (float) imageWidth;
//if scale factor is 1 then there is no need to scale (it will stay the same)
if (scaleFactor != 1) {
//calculate new height (with ration preserved) and scale image
int scaleHeight = (int) (bm.getHeight() / scaleFactor);
scaledImage = Bitmap.createScaledBitmap(bm, imageWidth, scaleHeight, false);
}
else {
scaledImage = bm;
}
Bitmap cropedImage = null;
//if cropped height is bigger then image height then there is no need to crop
if (scaledImage.getHeight() > imageHeight)
cropedImage = Bitmap.createBitmap(scaledImage, 0, 0, imageWidth, imageHeight);
else
cropedImage = scaledImage;
iv.setImageBitmap(cropedImage);
add
android:layout_gravity="center"
Android: how to set the height/width of the image(src image intead of the background) of a ImageButton?
I want to set the height/width of the top level image(not the background) image, the size of image should be customized instead of fullfill the button automatically
You can just Use the scaleType attribute of ImageButton.
Set it to fitXY or fitCenter or anything else according to your need.
like this
<ImageButton
android:id="#+id/imageButton"
android:layout_width="100dp"
android:layout_height="100dp"
android:scaleType="fitCenter"
android:src="#drawable/some_image">
</ImageButton>
You can use Bitmap.createScaledBitmap to scale the image to the size you want.
Bitmap image = ... //load image from your source
image = Bitmap.createScaledBitmap(image, desiredHeight, desiredWidth, true);
xml
<ImageButton
android:id="#+id/picture_id"
android:layout_width="10dp" //here width with unit. 5 dp exemple
android:layout_height="3dp" //here height with unit. 3 dp exemple
android:src="#drawable/picture_name"
/>
EDIT: (java code)
// load the origial BitMap (500 x 500 px)
Bitmap bitmapOrg = BitmapFactory.decodeResource(getResources(),
R.drawable.android);
int width = bitmapOrg.width();
int height = bitmapOrg.height();
int newWidth = 200;
int newHeight = 200;
// calculate the scale - in this case = 0.4f
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
// create a matrix for the manipulation
Matrix matrix = new Matrix();
// resize the bit map
matrix.postScale(scaleWidth, scaleHeight);
// rotate the Bitmap
matrix.postRotate(45);
// recreate the new Bitmap
Bitmap resizedBitmap = Bitmap.createBitmap(bitmapOrg, 0, 0,
width, height, matrix, true);
// make a Drawable from Bitmap to allow to set the BitMap
// to the ImageView, ImageButton or what ever
BitmapDrawable bmd = new BitmapDrawable(resizedBitmap);
ImageView imageView = new ImageView(this);
// set the Drawable on the ImageView
imageView.setImageDrawable(bmd);
// center the Image
imageView.setScaleType(ScaleType.CENTER);
// add ImageView to the Layout
linLayout.addView(imageView,
new LinearLayout.LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT
)
);
I had same problem... change the size of 'src' image of image button(not the size of button just image only).
what i did--
I moved those '.png' file from 'drawable' folder to 'drawable-hdpi' folder.
weird... but it worked.
thanks,
set padding and scaletype to centerInside
Padding will help you customize the source image to provide the required height and width.
<ImageButton
android:layout_width="50dp"
android:layout_height="50dp"
android:src="#drawable/location"
android:padding="10dp"
android:scaleType="centerInside"
android:background="#drawable/blue_circle_border"/>
I have a 10x10 tablelayout with each cell containing an ImageView. I simulate the moving across this gamegrid by updating the pictures in each grid on a move event. I also rotate the image to align the image with the direction of travel. My problem is that as the image rotates it causes my cell rows and columns to expand to fit the rotated image.
What I would like is to have the image cropped to remain within the dimensions of the table row and columns. If that isnt possible then I would like to scale the image to remain within the dimensions of the original table cell.
Another potential issue is that the images are getting scaled initially to fit into the cells (this is done automatically as the table expands to fill the screen). I don't want to change that behavior. I just want to trim off the corners of the image as they pass the original boundaries of the table cell when they are rotated.
My rotation code is below:
Matrix matrix = new Matrix();
matrix.postRotate((float) (360 - sector.getShip().getHeading()));
Bitmap bMap = BitmapFactory.decodeResource(image.getContext().getResources(), getShip().getGridSymbol());
image.setImageBitmap(Bitmap.createBitmap(bMap, 0, 0, bMap.getWidth(), bMap.getHeight(), matrix, true));
image.setImageResource(sector.getShip().gridParams.default);
My table configuration is below:
<TableLayout android:id="#+id/quadrantGrid" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignWithParentIfMissing="true" android:stretchColumns="*" android:background="#000000">
...
<TableRow>
<TextView android:text="1" android:background="#404040" android:gravity="center"></TextView>
<ImageView android:id="#+id/grid00"></ImageView>
<ImageView android:id="#+id/grid01"></ImageView>
<ImageView android:id="#+id/grid02"></ImageView>
<ImageView android:id="#+id/grid03"></ImageView>
<ImageView android:id="#+id/grid04"></ImageView>
<ImageView android:id="#+id/grid05"></ImageView>
<ImageView android:id="#+id/grid06"></ImageView>
<ImageView android:id="#+id/grid07"></ImageView>
<ImageView android:id="#+id/grid08"></ImageView>
<ImageView android:id="#+id/grid09"></ImageView>
</TableRow>
...
UPDATE:
I found a solution, though I'm not sure its the most efficient solution.
All my images are 25x25. And so the OS figures how to scale those images to fit into the cell. The solution just performs two operations. First it rotates, and then it creates a smaller image from the rotated image. (note: When I created my image I made sure the important parts of the image would be contained within a circle with a diameter of the width of the image to allow for this type of cropping).
My code is below. I would prefer to perform both operations within one method, but Im not sure how so I just break it down into two steps.
Matrix matrix = new Matrix();
matrix.postRotate((float) (360 - sector.getShip().getHeading()));
Bitmap bMap = BitmapFactory.decodeResource(image.getContext().getResources(), getShip().getGridSymbol());
bMap = Bitmap.createBitmap(bMap, 0, 0, 25, 25, matrix, true);
int x = (bMap.getWidth() - 25) / 2;
int y = (bMap.getHeight() - 25) / 2;
image.setImageBitmap(Bitmap.createBitmap(bMap, x, y, 25, 25));
Try adding
android:scaleType="centerCrop"
to each ImageView item in your xml layout.
The final solution has to leverage the "getMeasuredHeight()" of the image. I didnt have to use the getMeasuredWidth() because for my particular layout the height is the limiting factor.
Here is the final bitmap code that works:
private Bitmap getRotatedShipBitmap(SectorGridImageView image,
Bitmap bitmap, Matrix matrix) {
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
bitmap.getHeight(), matrix, true);
int yHeight = (image.getMeasuredHeight() == 0) ? bitmap.getHeight()
: image.getMeasuredHeight();
int xWidth = yHeight;
int x = (bitmap.getWidth() - xWidth) / 2;
int y = (bitmap.getHeight() - yHeight) / 2;
return Bitmap.createBitmap(bitmap, x, y, xWidth, yHeight);
}