I'm downloading a bitmap from internet, then I cast this bitmap as a Drawable to set it as a background in my LinearLayout.
I see that unfortunately the image is scaled to fill the view, how can I scale the image until the smallest size reach the border (so it's not stretched)?
(And possibly centered)
I've tried something like this but without any success.
Am I on the way?
LinearLayout layout = (LinearLayout) context.findViewById(R.id.main);
Drawable picture = new BitmapDrawable(context.getResources(), bitmap);
Display display = context.getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
picture.setBounds(0, 0, size.x, size.y);
layout.setBackgroundDrawable(picture);
I think you need something like this?
setScaleType(ScaleType.CENTER_CROP);
See http://developer.android.com/reference/android/widget/ImageView.ScaleType.html
I think,It is not advisable use scaled images on an app. It's a best practice use a repeated pattern instead. So, I would try something like that:
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="#drawable/background-image-repeatable-pattern.png"
android:tileMode="repeat" />
Save this to drawable/background.xml file (for example)
Related
Linked questions
The below questions couldn't finally solve my problem, described below.
Android: Is it possible to repeat an (SVG!) drawable inside an ImageView?
Android: Keep ratio for a full-width and undefined height ImageView in a ConstraintLayout?
Showing a full-width ImageView containing a SVG distorts it
Context
I use a ConstraintLayout. My aim is to show an SVG image which contains a button:
Its width is 100% the screen's width - it must be repeated
Its height is defined to be the space between the bottom side of a widget and the bottom side of the button - it must be repeated
The problem
Each time I tried to show this image, either the drawable was badly scaled, badly cropped or blurred.
An exemple is:
It should look like this:
Many tests
I have tried to use an ImageView with the attribute src: I used every scale type, with and without the attribute that allows to set a custom ratio
I have tried to use an ImageView with a background instead of src
I have tried to use a RelativeLayout with a background drawable file that is repeated: so I didn't use an SVG image but its JPEG version, and even this way has resulted in bad results
Nota for 3.: I'd really want to use an SVG image instead of a bitmap one, because it will be resolutions-compliant.
My question
So, given all these explanations (cf.: part Context) and given the above illustrations, how would you proceed to show this image?
use java code
ColorDrawable colorDrawable = new ColorDrawable(Color.parseColor("#888888")); // bg color
Drawable vDrawable = AppCompatResources.getDrawable(this, R.drawable.ic_vector_star); // vector drawable
if (vDrawable != null) {
Bitmap bitmap = Bitmap.createBitmap(vDrawable.getIntrinsicWidth(), vDrawable.getIntrinsicHeight(),
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
vDrawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
vDrawable.draw(canvas);
BitmapDrawable bitmapDrawable = new BitmapDrawable(getResources(), bitmap);
bitmapDrawable.setTileModeXY(Shader.TileMode.REPEAT, Shader.TileMode.REPEAT); // set repeat
LayerDrawable drawable = new LayerDrawable(new Drawable[]{colorDrawable, bitmapDrawable});
findViewById(R.id.frameLayout).setBackground(drawable);
}
I'm trying to set a Bitmap Drawable as the background like this, root.setBackground(bitmapDrawable);, I've set its bounds to be 1080 wide by 300 high, but it keeps stretching to fit the entire background. Is there any way to avoid this? This is how i created the BitmapDrawable BitmapDrawable bitmapDrawable= new BitmapDrawable(getResources(), bmp1);
I believe the default Gravity of a BitmapDrawable is FILL. Try setting the Gravity to CENTER:
bitmapDrawable.setGravity(Gravity.CENTER);
I'm trying to scale an image in an ImageView on Android, but no matter what settings I try, the scaled-down image always looks ugly. Here is an image produced by my code:
http://i.imgur.com/4yubR.png?1
The image on the left is pre-scaled using ImageMagick on my desktop computer. ImageView has no problem showing this image. The image on the right is the one that is actually scaled by the ImageView, and as you can clearly see, it looks quite ugly :/
The code that produces both of the above images is as follows:
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
RelativeLayout body = new RelativeLayout(this);
for(int i = 0; i < 2; ++i)
{
ImageView iv;
iv = new ImageView(this);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(34, 34);
params.leftMargin = i*50;
body.addView(iv, params);
AssetManager am = this.getAssets();
try
{
BufferedInputStream buf;
if(i == 0)
buf = new BufferedInputStream(am.open("images/search_34x34.png"));
else
buf = new BufferedInputStream(am.open("images/search.png"));
Bitmap bitmap = BitmapFactory.decodeStream(buf);
BitmapDrawable bd = new BitmapDrawable(bitmap);
bd.setAntiAlias(true);
iv.setImageDrawable(bd);
buf.close();
}
catch(java.io.IOException e)
{
}
}
setContentView(body);
}
Please tell me if I am missing something. I just cannot believe that Android scales images this badly (actually, I find it hard to believe that this is the default behavior).
Also note that I do NOT want to pre-scale the images, as my app has to deal with images from unknown origin, so I have to scale on the fly.
I don't see where you are scaling down your bitmap. I think you are trying to jam the high resolution bitmap in to a ImageView with smaller dimensions.
Here is a document on scaling the bitmaps. The technique described works well with scaling the bitmaps on the fly also.
Maybe You have to set the scaleType inside Your xml Layout. For example
<ImageView
android:scaleType="center"
</ImageView>
There are following scaleTypes:
CENTER
CENTER_CROP
CENTER_INSIDE
FIT_CENTER
FIT_END
FIT_START
FIT_XY
MATRIX
You could see about here:
http://developer.android.com/reference/android/widget/ImageView.ScaleType.html
EDIT
Tried some stuff and now I get the same result even with other pics. I recognized, that when I am scaling down an image inside a mobile phone, all looks good. I used for example an imageView with 120x120 dp and a resource with 300x300px. If I use the same imageView on an tablet, even 120x120, and the same resource image with the same size, it looks very bad. I think the only way to get rid of this is to scale the image outside your app to the needed sizes before setting it to Your project. For Example, if You use an imageView with 200x200dp, scale the image near to this size. If You support multiple screen sizes, and you set the sizes of this imageView for a tablet to 500x500dp, scale Your image near to this size. Sure, this only will work good, if You got an Image that has a higher resolution than the biggest imageView.
I Know this no satisfying answer, but this is the only way I see for this problem.
I am trying to draw multiple ImageViews inside a single LinearLayout.
All the ImageViews need to have a single bitmap.
The ImageViews will only vary in size.
The single bitmap will not be resized.
The simple way is to create one Bitmap per ImageView. But, this runs out of memory quickly.
final Bitmap placeholderBitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
final Canvas canvas = new Canvas(placeholderBitmap);
canvas.drawBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.placeholder_image), 0, 0, null);
imageView.setImageBitmap(placeholderBitmap);
linearLayout.addView(imageView);
I also tried setting the max and min height and width, no effect. The images remain the same size.
imageView.setImageResource(R.drawable.ic_no_image);
imageView.setMaxHeight(imageViewInfo.height);
imageView.setMaxWidth(imageViewInfo.width);
I believe working with Drawables is the right "Android" way to do it, but I can't find a way to dynamically create a Drawable with the right side and layering the shared bitmap into it.
Just use one Bitmap -- as you say they will all use the same Bitmap, so no duplication is necessary.
If you want the ImageViews to have different sizes and have the Bitmap scale itself to the size of the ImageView then use the setScaleType or android:scaleType attribute to set the scaling of the ImageView. For instance FIT_START maintains the aspect ratio of your image and tries to fill the ImageView starting from the top-left corner.
I don't see any need to create a Drawable, though if you need to you can just create one from a Bitmap using:
Drawable d = new BitmapDrawable(bitmap);
ImageView actually does this automatically when you call setImageBitmap(...).
ImageView will always resize the bitmap to it need proportions.
If you want to save memory, resize the bitmaps manually and set them into the ImageViews this should stop the ImageView from resizing it internally - to make sure, you can set the layout_width and layout_hieght of the image view to 'wrap_content'.
I think may be looking for a ClipDrawable.
You would set the android:drawable property of the clip XML to your bitmap
That or you can do it with the Java code also given in the example
I updated my build to build against Android 1.6, and now my bitmaps are scaled down on high density screens. I do NOT want this behavior. I gave this a shot:
http://blog.tomgibara.com/post/190539066/android-unscaled-bitmaps
but the images are STILL scaling, that is UNLESS I set them to a specific height & width. If I use wrap_content they are scaled down.
I have an image loader using the unscaled bitmap loader to create a drawable like so:
Bitmap bm = UnscaledBitmapLoader.loadFromResource(imageBufferInputStream);
drawable = new BitmapDrawable(bm);
which I later assign to an ImageView like so:
imageView.setImageDrawable( copyBitmapDrawable( (BitmapDrawable) drawable) );
In order to have an image not scaled when loading it from a resource (e.g. with BitmapFactory.decodeResource) you have to locate it in res/drawable-nodpi instead of the usual drawable, drawable-ldpi and so on.
Using
new BitmapDrawable(this.getResources(), bmp);
instead of
new BitmapDrawable(bmp);
should solve the issue.
Wrapping the bitmap with a Drawable is the problem. The Drawable scales the Bitmap. Instead of using a Drawable, assign the Bitmap to the ImageView directly using imageView.setImageBitmap(Bitmap).
Use ImageView.ScaleType. The CENTER constant preforms no scaling, so I guess that's what you are looking for.
By the way, do you use pixels or dips as size units? Using dips (density-independent-pixels) is a means of standardizing display on multiple resolutions. You'll find a couple of tips here.