ImageView expanding container despite adjustViewBounds

432 Views Asked by At

I want to wrap an ImageView inside a LinearLayout so that I can center a group of views. However, the original image needs to be scaled down to fit in the ImageView, and the original size expands the LinearLayout, despite my use of adjustViewBounds="true" and an enclosing FrameLayout as suggested by previous questions on SO.

The desired layout should look like this,

but the observed layout looks like this,

as produced by the XML below:

<android.support.percent.PercentRelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="project.MainActivity">

        <LinearLayout
            android:layout_width="wrap_content"
            app:layout_heightPercent="32%"
            android:orientation="horizontal"
            android:background="#b44343"
            android:layout_centerHorizontal="true"
            android:layout_alignParentTop="true">
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Sample Text"/>
            <FrameLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="#5555ae">
                <ImageView
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent"
                    android:background="#2c8c4c"
                    android:src="@drawable/spades_icon"
                    android:adjustViewBounds="true"
                    android:scaleType="centerInside"/>
            </FrameLayout>
        </LinearLayout>
    </android.support.percent.PercentRelativeLayout>

I can't use the other suggestion of setting android:maxHeight="100dp" because I need the height to be relative to that of the screen.

3

There are 3 best solutions below

0
On BEST ANSWER

Based on this answer to another question, a solution that removes the whitespace in the LinearLayout while preserving the height and aspect ratio of the image is:

@Override
public void onWindowFocusChanged(boolean hasFocus) {
    LinearLayout layout = (LinearLayout) findViewById(R.id.mLinearLayout);
    ImageView imageView = (ImageView) findViewById(R.id.mImageView);
    TextView textView = (TextView) findViewById(R.id.mTextView);

    layout.getLayoutParams().width = textView.getWidth()+imageView.getWidth();
    layout.requestLayout();
}

EDIT:
Based on @Juan's answer and these instructions, the following code also achieves the desired result:

@Override
protected void onResume() {
    DisplayMetrics displayMetrics = new DisplayMetrics();
    this.getWindowManager()
        .getDefaultDisplay()
        .getMetrics(displayMetrics);

    ViewGroup.LayoutParams params = imgView.getLayoutParams();
    params.height = (int)Math.floor(displayMetrics.heightPixels * 0.32);
}
1
On

I see that you have added android:adjustViewBounds="true".

You can combine that with android:maxWidth="60dp"

So your imageView should look like this.

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:background="#2c8c4c"
                android:src="@drawable/spades_icon"
                android:adjustViewBounds="true"
                android:maxWidth="60dp"
                android:scaleType="centerInside"/>

You can change the max width to any number you want.

5
On

Things you can do:

1) Set a specific width / height to the FrameLayout enclosing the ImageView and set android:scaleType to centerInside, fitCenter, or fitXY for the ImageViwe.

2) Programatically, in your activity, after onCreate, in onResume for example, you can get the LayoutParams and change the width and height of the ImageView doing you own scaleing. I take this aproach when I scale against the screen widht or height at run time.

EDIT 1

Example of second alternative:

public class TestActivity extends AppCompatActivity {

    ImageView imgView;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.testactivity_layout);

        imgView = (ImageView) findViewById(R.id.imgview);

    }

    @Override
    protected void onResume() {
        super.onResume();
        ViewGroup.LayoutParams params = imgView.getLayoutParams();
        params.width = 100;
    }
}

Notes: The width is expressed in pixel. To get the display metrics: How to get screen display metrics in application class

To establish a relative width for the ImageView, get the width of the display and calculate the desireed % as the width of the image.