2
votes

Assuming portrait mode, I have an ImageView who's image will be of variable size (yet always square). I would like the ImageView's width to always be equal to the layout's width (fill_parent) and as you can see the scaleType is "centerCrop" which will scale.

The problem is that if I set the *layout_height* also to "fill_parent" then, being that centerCrop retains the original aspect ratio, the height takes precedence and the image is cropped on the left and right. (this of course assumes a screen that is taller than it is wide). However, if I set the layout_height to "wrap_content", then the height is no longer scaled and I end up with a cropped rectangle. It does this because it respects the original height of the image.

Is there a layout_height setting that will give precedence to a layout_width of "fill_parent"?

<ImageView
    android:id="@+id/iv_image"
    android:layout_width="fill_parent"
    android:layout_height="?"
    android:layout_below="@id/header"
    android:layout_centerHorizontal="true"
    android:contentDescription="@string/cd_image"
    android:padding="0dp"
    android:scaleType="centerCrop"
    android:src="@drawable/blank_album" />

Removing the android:layout_height attribute causes a crash: java.lang.RuntimeException: Binary XML file line #16: You must supply a layout_height attribute.

Setting android:layout_height="0dp" crushes the image vertically.

Answer: Using a combination of responses from other users, I was able to find a simple solution that works well for me.

First, the image view has this configuration (note the fitStart):

<ImageView
    android:id="@+id/iv_album"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_below="@id/header"
    android:layout_gravity="top"
    android:background="#FF00FF00"
    android:contentDescription="@string/app_name"
    android:padding="0dp"
    android:scaleType="fitStart"
    android:src="@drawable/blank_album" />

Then programmatically, a small modification to the height of the image to match the width (within Activity.onResume())

        ImageView iv = (ImageView)findViewById(R.id.iv_album);
        boolean bPost = iv.post(
                new Runnable()
                {
                    public void run()
                    {
                        ImageView iv = (ImageView)findViewById(R.id.iv_album);
                        RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams)iv.getLayoutParams();
                        params.width = ASong.this.findViewById(R.id.song_view_layout_top).getWidth();
                        params.height = params.width;                           
                        iv.setLayoutParams(params);
                    }
                });

        if (bPost == false)
        {
            throw new RuntimeException("runnable not posted");
        }
2

2 Answers

2
votes

I had to deal with this issue yesterday. This is the XML that solved my problem:

<ImageView
                android:id="@+id/character"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:layout_alignParentBottom="true"
                android:background="@android:color/transparent"
                android:scaleType="fitCenter"
                android:src="@drawable/ma_un1_001" />

see thread here: Center drawable and scale height

To cut a long story short:

android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="fitCenter"
2
votes

Alternatively, you can do it programmatically:

Surround the ImageView with a LinearLayout

<LinearLayout
android:id="@+id/container"
android:layout_below="@id/header"
android:layout_centerHorizontal="true"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
    <ImageView
    android:id="@+id/iv_image"
    android:layout_width="fill_parent"
    android:layout_height="?"
    android:contentDescription="@string/cd_image"
    android:padding="0dp"
    android:scaleType="centerCrop"
    android:src="@drawable/blank_album" />
</LinearLayout>

Then, in your onCreate(), insert

findViewById(R.id.container).post(
    new Runnable() {
    public void run() {
        LinearLayout container = (LinearLayout)findViewById(R.id.container);
        LinearLayout.LayoutParams params = (LinearLayout.LayoutParams)container.getLayoutParams();
        params.height = params.width;
        container.setLayoutParams(params);
    }}
);

The code must be into post() because the main process can't directly modify the layout structure.