My issue is this:
I use the android emulator, targeting android 2.2.
I created a custom view which I want to handle the background of my application, in this view I only want to display an image but I want it to fill the entire screen.
I initialize the view from my "Activity" like this:
BackgroundView bw = new BackgroundView(this);
The problem:
On my HDD, the resource image I'm using is 500x375 pixels. After calling:
Bitmap m_resourceBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.landscape_1);
int nWidth = m_resourceBitmap.getWidth();
int nHeight = m_resourceBitmap.getHeight();
the returned nWidth and nHeight depend on where I placed the resource, if i place it in the "drawable-mdpi" I get the original size, otherwise I get other sizes.
On the other hand if I ask the view for it's width and height via
this.getWidth();
this.getHeight();
I get fixed values, but different from the resolution I expected from the device (I set a 480x800 device and I get 320x533)
and finally if I try to create a scale matrix using view dimensions divided by the image dimensions, the result, on screen, is an image much smaller than the screen...
My question is:
What questions should I ask and from which objects so that inside a View I can draw a resource Bitmap so that it occupies the entire screen?
Cant you do it all in the layout XML file? (Here's an example that I use for my menu background image)
<ImageView android:id="#+id/menuBackground"
android:src="#drawable/imageResource"
android:adjustViewBounds="true"
android:gravity="center_vertical"
android:scaleType="fitXY"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_x="0dp"
android:layout_y="0dp" />
Then if you need to change it in runtime all you have to do is change the drawable.
Related
In my code I want to set a default image for my imageview. All my images are of 174px X 174px. So, I want the default image to be same size. This is my xml for image view
//....code
<ImageView
android:id="#+id/ivCover"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:contentDescription="Default Image"
android:src="#drawable/default_cover" />
//....some other code
Now, my default_cover.jpg is also 174px X 174px. But it shows a smaller image. I've tried all
android:scaleType="centerInside"
android:scaleType="center"
android:scaleType="matrix"
even when most of them were senseless for me but still I tried all of 'em & none of them works. Then I specified the height & width of image by specifying
android:layout_width="174px"
android:layout_height="174px"
(I know using dp is better than px but because this image size is fixed & I was just testing it). So it shows
[default image]
while when loaded from an external url using
Bitmap bitmap = BitmapFactory.decodeStream((InputStream) new URL(url_source_for_image).getContent());
ivCover.setImageBitmap(bitmap);
desired image
[]
The two pictures may not look very different here but the difference is very clear on my android device. And please don't say that I didn't try other solutions..
Here is a list of links of so itself..
ImageView fit without stretching the image
Fit image into ImageView, keep aspect ratio and then resize ImageView to image dimensions?
ImageView one dimension to fit free space and second evaluate to keep aspect ration
Resizing ImageView to fit to aspect ratio
Maximum width and height for ImageView in Android
Image in ImageView is stretched - Android
Android: How to prevent image from being scaled in ImageView or ImageButton?
Sounds like the answer is to use drawable-nodpi. For future reference, if you have the same named image in both the ldpi/hdpi/etc and in no-dpi, I think the no-dpi one will be ignored.
My app has an Activity that displays a vertically scrolling list of ImageButtons. I want each buttons image to (A) come from the assets folder and (B) retain it's aspect ratio as it scales. Unfortunately, my ImageButton doesn't size correctly when it's image comes from the assets folder.
ImageButton src set from drawable
The first screenshot is my test app where the images all come from my apps drawables. That's the "correct" aspect ratio for that image, which is what I want to keep (all of the image buttons have been given scaleType "fitXY" "centerCrop").
ImageButton src set from assets
The second screenshot is my test app where the images all come from my apps "assets" folder — as you can see, the images are stretched out to the full width of the screen as desired, but the original aspect ratio has been lost:
Activity code (MainActivity.java)
LinearLayout buttons = (LinearLayout) findViewById(R.id.buttons);
View button = layoutInflater.inflate(R.layout.snippet_imagebutton, null);
ImageButton imageButton = (ImageButton) button.findViewById(R.id.imageButton);
if (GET_IMAGE_FROM_ASSETS) {
InputStream s = assetManager.open("image.png");
Bitmap bmp = BitmapFactory.decodeStream(s);
imageButton.setImageBitmap(bmp);
} else {
imageButton.setImageResource(R.drawable.image);
}
TextView buttonText = (TextView) button.findViewById(R.id.textView);
buttonText.setText("Button text!");
buttons.addView(button,
new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
Button layout (snippet_imagebutton.xml)
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp">
<ImageButton
android:id="#+id/imageButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="centerCrop"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true" />
<TextView
android:id="#+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:gravity="center"
android:textColor="#FFF"
android:background="#88000000"
android:textAppearance="?android:attr/textAppearanceMedium" />
</RelativeLayout>
Dodgy hack
I've found a dodgy hack which achieves what I want and illustrates the problem — the ImageButton will size correctly to match a scaled up image from the resources, but it won't size correctly to match a scaled up image from the assets. I'd prefer a "real" solution over the dodgy hack if there is one. :)
// to start with, scale the ImageButton based on an image in our
// resources that has the same dimensions as the image in our assets
imageButton.setImageResource(R.drawable.image);
// when we eventually render (we don't have width / height yet)...
imageButton.post(new Runnable() {
public void run() {
int height = imageButton.getHeight();
int width = imageButton.getWidth();
// replace our "resource" image with our "asset" image
imageButton.setImageBitmap(bmp);
// and force the ImageButton to keep the same scale as previously
imageButton.setLayoutParams(
new RelativeLayout.LayoutParams(width, height));
}
});
Summary
I want to get the images for these buttons from my apps "assets" folder. How do I fix my app so that the button images are all scaled properly (i.e. retain their original aspect ratio)?
I'm assuming this has something to do with the framework not actually knowing the width / height of the image before it renders the ImageButton to screen — so how do I fix that? I tried setting adjustViewBounds to "true" on both the RelativeLayout and the ImageButton itself, but that didn't seem to have any effect.
The aspect ratio is not kept when you give the scale type attribute as "fitXY". Try "center", "center_crop" or "center_inside" according to your needs. Check ImageViewScaleType as well.
From what I gather, AdjustViewBounds is actually the method that provides the exact functionality you need. However, as Roman Nurik explains here, AdjustViewBounds does NOT increase the ViewBounds beyond the natural dimensions of the drawable.
Without seeing how you allocated resources/assets, my suspicion would be that this is why you see a difference when loading from Resources and when loading from Assets. Your resource file is - presumably - being scaled up when you load it (since that is the default behavior for resources), so that the actual size of the drawable returned from /res is significantly larger than the bitmap you decode from /assets.
Overriding ImageButton (as Nurik suggests), is of course one option, but probably overkill.
Assuming I am correct about the problem, you should be able to fix it simply by setting your BitmapFactory.options correctly when you load the Assets file. You need to set inDensity and inTargetDensity correctly according to your device (get DisplayMetrics), and set inScaled to true.
Alternatively, you can always rescale the bitmap manually before loading it on the ImageButton. Just grab the screen width to determine how large you need to make it.
P.S.
Auto-scaling is obviously the elegant solution, but it does have a weakness (which applies equally to both resources and assets) - if the width of your display > bitmap witdh when scaled up, you'll likely still have the aspect ratio messed up. You can check this pretty easily by going to landscape mode and seeing whether the resource file still result in the right aspect ratio. If you have a large enough base image (or use different layouts according to the screen size/orientation), then this should not be a problem though. Just something to keep in mind.
I have a normal "read an article" type page with a single large photo at the top.
I'd like it to:
not scale larger than the source imgae
not be larger than the screen
not be CRAZY long vertically
side things I already have working
border (via padding), center crop (would rather top crop, but seems not avail)
The main issue I'm having is - I can either have it fill_parent (ie full width) OR wrap_content (ie as large as the original image). And nothing I have done so far allows the image to be normal size (ie keep from enlarging).
Is there a "norm" for this kind of thing? I'm sure there's some kind of sweet spot or combination of attributes for this that works - I just can't find them.
My current attempt:
<ImageView
android:id="#+id/article_photo"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#color/super_light_gray"
android:scaleType="centerCrop"
android:contentDescription="#string/articlePhoto"
android:cropToPadding="true"
android:layout_marginBottom="20dp"
android:padding="1dp"/>
You can write some code in the Activity to get the image size and display size.
If the image size exceeds display size set width to display, if not set to image size. If you want to be fancy you can find the ratio between the x and y and scale vertically also.
Situtation:
I am working on a small application which should enable user to trigger something depending on which part of the screen they clicked. Imagine a picture of a teddy bear and if you click a nose it says "nose". What I have done is put in layout xml a LinearLayout. Because I have to cover different screen sizes I didn't set background in a xml layout file.
snippet form xml:
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/viewMain"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:visibility="visible" >
<LinearLayout
android:id="#+id/viewThouShaltRespondToClicks"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clickable="true"
android:orientation="vertical"
android:longClickable="true"
android:visibility="visible" />
<!-- mask -->
<LinearLayout
android:id="#+id/viewInvisibleMask"
android:visibility="invisible"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
</LinearLayout>
</FrameLayout>
And then in onCreate event of activity I check the display resolution and via setBackgroundResource() set the appropriate background. I have prepared background images for each resolution.
final Point QVGA = new Point(240,320); // portrait
// Obtain the screen resolution if the device
Display defaultDisplay = ((WindowManager)this.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
Point displayResolution = new Point(defaultDisplay.getWidth(), defaultDisplay.getHeight());
if (displayResolution.equals(QVGA))
{
viewThouShaltRespondToClicks.setBackgroundResource(R.drawable.image_to_be_clicked_upon_240x320);
viewInvisibleMask.setBackgroundResource(R.drawable.mask_240x320);
}
else if ... // check for another resolution
Even if the image in the resources is not in the correct dimension it is stretched/shrinked to the screen size. This would be OK as long as the width-height ratio of background image is similar to ratio of display and the resulting image is not kewed to much. But there is a problem, explained below.
To detect which region was clicked, the region itself might be irregular shaped I have taken the following approach. I create an image – mask (bmp) with same dimensions as background image only that it has a white background and the clickable areas are in different colors. The color identifies the area. All I have to is get a coordinate of a click event (no problem here), go to the mask image and read the color of pixel on this coordinates. The problem is that the mask image is not of the correct size. On my device it is set to 1200x700, but I guess it takes on some arbitrary size on other devices.
First question: Is there a way to somehow convince the invisible layout to load background image and then stretch/shrink it to display size as it happens for visible layout by itself?
Another approach would be to load mask image (bmp, png) into some memory structure and resize it to display size.
I have tried with something like:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false; // do not scale
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
bitmapMask = BitmapFactory.decodeResource(this.getResources(), R.drawable.mask, options);
// on this place stretch shrink should follow but I have no idea how
But I don’t know how to scale Bitmap to proper size.
Any suggestions?
First question: yes, you can have a separate View in your layout containing the mask image, and set it to be invisible with android:visibility=invisible.
Second question: you can read a pixel value from the bitmap with Bitmap.getPixel(). Docs are here.
Just a simple suggestion. You could have the reference image in an imageview behind the real image. So both images are loaded in the exact same way, placed in ImageViews, and then inserted into a relativelayout. That way they should be equal size, and only one of them is visible.
This might not be a very pretty way of doing it, and i'm not sure if it will work, but you can try it out.
New to Android, bad with layouts so this is probably a simple solution but I can't find it. I am adding an image to a ListView, the ListView is defined like this:
<ListView
android:id="#+id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"/>
Image is added like this:
ImageView image = new ImageView(context);
image.setScaleType(ImageView.ScaleType.FIT_CENTER);
image.setAdjustViewBounds(true);
image.setImageDrawable(drawable);
return image;
in the ListAdapter. I want the Image to scale so the width fills the screen and the height adjust proportionally. What is happening is the image is scaling down so the height fills the list row but there is plenty of room for the width to be bigger. I had this working earlier but can't figure out what changed. Why is the image shrinking to some seemingly arbitrary height and how do I get it to fill the screen by width?
Edit:
So this happened when I started building for 1.6 instead of 1.5, probably a resolution thing. I guess the image is a bit sharper when it's small but I want it larger, it's almost unusable smaller and I am not able to get a larger image, it's from the web.
I think there is no really "simple" solution, but it's already answered here (without list's, but i don't think it matters):
Android: How to stretch an image to the screen width while maintaining aspect ratio?
Have you tried ImageView.ScaleType.FIT_XY ?
Scale Types