问题
I have the following layout for my ImageView
:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:descendantFocusability="blocksDescendants">
<ImageView
android:id="@+id/imageview_icon"
android:layout_width="48dp"
android:layout_height="48dp"
android:scaleType="fitCenter" />
(...)
</LinearLayout>
Those 48dp
equal to 36px, 48px and 72px in ldpi
, mdpi
and hdpi
respectively. All the images that will be used in this ImageView
are basically icons and I've found on the web what I want for my app (free license). But unfortunately, it doesn't come with images bigger than 48px and using different images is out of the question. So I need a new solution...
For now I have 36px and 48px images in the ldpi
and mdpi
folders, respectively. But I'm having trouble with hdpi
. What I want for devices running on hdpi
is for them to use the mdpi
image (the bigger one available) and use it as it is, without scaling. Basically, the ImageView
for hdpi
is 72px, so I want the 48px image to be inside the 72px, in the center, without scaling. For that, I simply tried to change scaleType
in the ImageView
above to just center
, but the image gets scaled anyway.
My ultimate question in here is, what's the proper way to fix the problem described above? How can I have ldpi
and mdpi
images being used in their respective densities, but have devices running hdpi
pick up the biggest image available (which is the mdpi
ones) and prevent any scaling, just fitting the image in the center of the ImageView
?
EDIT:
I answered this question myself, but it might to be the answer others coming here are looking for. But I do provide some insight on what's really happening and the underlying problem. Please take a look and provide a workaround/fix if you can. I dare you :)
回答1:
This question turns out to be a non-question and I apologize to anyone that founds it, hoping the accepted answer will be what they are looking for when it won't be.
To make it clear, scaleType=centerInside
is working as expected. That is, if you have an image smaller than the ImageView
itself, than that image won't be scaled to the bounds of the ImageView
, it will remain in the center and unscaled.
But for the above to work as expected, the drawable must be placed in the nodpi
folder. I understand that this is not always acceptable. So, when that drawable must be placed into one of the density folders instead of the nodpi
folder, the scaleType
attribute will only work in specific situations.
When it will work:
- You are running the app on a device/emulator with
Xdpi
density and there is a drawable in theXdpi
density folder (hereX
means,l
,m
,h
or evenxh
). - You are running the app device/emulator,
for instance, with
hdpi
density, but there isn't a drawable in thehdpi
folder and the system picks the alternative drawable from thenodpi
folder (it's not always known which folder it will pick from).
When it will not work:
- You are running the app device/emulator, for instance, with
hdpi
density, but there isn't a drawable in thehdpi
folder and the system picks the alternative drawable from any other of the density folders (not thenodpi
folder), the drawable will be scaled to theImageView
bounds and thescaleType
attribute will not do anything.
In conclusion, there's no "right" answer to my question, it really depends on what you are trying to achieve. The answer my question though, I just need to do 2 things: a) Set the ImageView
scaleType
to centerInside
and b) Duplicate all drawables from the mdpi
folder into the hdpi
folder (as explained above, the scaleType=centerInside
will make it work).
Of course, duplicating drawables is not optimal, but I can't find any other solution and so far, no one else could either... So, in the time being, I'll mark this one as accepted.
What would be the optimal answer/solution then?
In my opinion, if the device/emulator is running in hdpi
and there isn't a matching drawable in the hdpi
folder it should be pick the drawable from the mdpi
folder without scaling it, allowing the scaleType
attribute to do it's thing. Or maybe force the system to go to the nodpi
folder if it doesn't find a matching drawable in the respective density folder, that could a solution too.
So, if anyone can ever provide a workaround/fix to this issue, that would be the real correct answer. If it ever comes to that, I'll change the accepted status.
回答2:
I solved it in this way:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<!-- Here is where the money is -->
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:gravity="center_horizontal|center_vertical">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
...
</LinearLayout>
</LinearLayout>
回答3:
In my case, I was setting the image as android:background
. when I set it as android:src
, it worked!
回答4:
Try leaving it out of the hdpi folder, and place it in a drawable-nodpi folder. I'm not sure what the hierarchy is (whether the nodpi would then override the ldpi and mdpi folders) but that would be my first try.
回答5:
Try this:
<FrameLayout android:layout_width="48dp" android:layout_height="48dp">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:maxWidth="48px"
android:maxHeight="48px"
android:adjustViewBounds="true"
android:src="..."
/>
</FrameLayout>
And put the images normally in the ldpi/mdpi folders.
Although I do not recommend using pixel values.
回答6:
Try with
imageview.setAdjustViewBounds(false);
回答7:
Create a custom ImageView:
package x;
public class MaxMDPIImageView extends ImageView {
public MaxMDPIImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onDraw(Canvas canvas) {
float density = getResources().getDisplayMetrics().density;
if (density>1) {
canvas.translate(getWidth()/2-getWidth()/density/2, getHeight()/2-getHeight()/density/2);
canvas.scale(1/density, 1/density);
}
super.onDraw(canvas);
}
}
Use it simply as:
<x.MaxMDPIImageView
android:src="@drawable/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
/>
来源:https://stackoverflow.com/questions/7808129/setting-imageview-scaletype-to-center-is-not-working-as-i-expect-it