Setting ImageView width and height relative to text height

2k views Asked by At

I have a ListView. On each row is an image and text. I want to scale image so it fits the row height i.e.

  • image shouldn't cause the row height is bigger
  • image height should be the same as the row height
  • image width should be calculated so the original width height ratio is maintained

All solutions that I figured out seem too complex for which I'd assume is a relatively common requirement so I'd like to check if I'm missing something - do you have an idea how to achieve this in a simpler way ?

The following are solutions I considered.

Solution 1:

Nested views for ListView item and set android:layout_height="match_parent". Image is resized correctly but ImageView occupies the width as if it was not resized. (See the following picture. I added black background to see how much space occupies ImageView.)

enter image description here

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <ImageView android:id="@+id/Image"
            android:layout_height="match_parent"
            android:layout_width="wrap_content"
            android:adjustViewBounds="true"
            android:scaleType="fitStart"

            android:background="#000000"
            android:padding="1dp"/>
        <TextView
            android:id="@+id/Text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_above="@id/Image" />
    </LinearLayout>
</RelativeLayout>

Solution 2: Using

ViewTreeObserver observer = MyTextView.getViewTreeObserver() observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {

public boolean onPreDraw(){
    observer.removeOnPreDrawListener(this);
    // Finding out height of TextView and then calculating width and height of image and setting size of ImageView. Of course, I could also get observer from ImageView and then just set width as height is correct
}

}

This seems like too complicated.

Solution 3:

Use, e.g., Paint.FontMetrics to calculate height but I'd also need to find out the font used (e.g., system one ...) Also ListView probably has some padding, etc. so kind of lots of things to retrieve.

Any other simpler solution please ?

Edit - clarification

The image has the max. size, which if reached, stops any further increasing of the size of ImageView.

2

There are 2 answers

5
Matthew Vanlandingham On

If you are wanting to set the width and height of the ImageView based on the width and height, you can always get the width and height of the TextView programmatically, then implement your own algorithm to scale the ImageView accordingly.

To get the width and height from a textView, let's call it item_textView, it's fairly simple:

TextView item_textView = findViewById(R.id.item_textView);
int text_width = item_textView.getWidth();
int text_height  = item_textView.getHeight();

At this point, you can perform whatever math you need to perform to scale the imageView down to the correct size. To set the size of the imageView:

my_imageView.getLayoutParams().width = text_width/2;
my_imageView.getLayoutParams().height = text_height/2;
1
Hemant On

Since you defined the parent linear layout height as wrap content it will take the size of its content and may vary based on its children element dimensions.

Try to define exact size for the image in your row layout. If you can define its width and height as 40dp or 48dp you might be able to achieve your goal.

If all elements depend on each other's size you might be able to see variations. Try to define the avatar/image sizes in specific dp.

I tried to tweak your layout and got some results. Check out the following code.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:padding="16dp">
    <ImageView
        android:id="@+id/earthquake_magnitude"
        android:layout_width="36dp"
        android:layout_height="36dp"
        android:background="@android:color/black"
        android:fontFamily="sans-serif-medium"
        android:src="@mipmap/ic_launcher" />

    <TextView
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:layout_marginLeft="16dp"
        android:layout_marginStart="16dp"
        android:layout_weight="1"
        android:text="CHROME" />
</LinearLayout>