2

Note: I have checked this question, but none of the answers helped. I'm restating the question to specify my specific problems and needs.

I've made a custom view in my android app that displays data for an upcoming event (title, location, price, description, etc). In addition to this data, there are also icon and cover photos displayed on this view (the icon is displayed in an ImageView in the upper-left corner of the view and the cover is modified to have an alpha of 128, then displayed behind the content of the view. Here's my layout so far:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/eventview_main" android:layout_width="match_parent"
    android:layout_height="wrap_content" android:layout_marginLeft="@dimen/activity_horizontal_margin"
    android:layout_marginRight="@dimen/activity_horizontal_margin"
    android:layout_marginTop="@dimen/activity_vertical_margin"
    android:background="@color/color_black" android:elevation="16dp">

    <!-- OBJECT IN QUESTION -->
    <ImageView
        android:id="@+id/eventview_cover"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:adjustViewBounds="false"
        android:cropToPadding="false"
        android:scaleType="centerCrop" />

    <ImageView android:id="@+id/eventview_icon"
        android:layout_width="100dp" android:layout_height="100dp"
        android:layout_marginLeft="@dimen/half_margin"
        android:layout_marginRight="@dimen/half_margin"
        android:layout_marginTop="@dimen/half_margin" android:elevation="8dp" />

    <TextView android:id="@+id/eventview_title"
        android:layout_width="wrap_content" android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/eventview_price"
        android:layout_alignParentEnd="true" android:layout_alignParentRight="true"
        android:layout_alignParentTop="true" android:layout_marginTop="@dimen/half_margin"
        android:layout_toEndOf="@+id/eventview_icon" android:layout_toRightOf="@+id/eventview_icon"
        android:text="Large Text" android:textAppearance="?android:attr/textAppearanceLarge"
        android:textColor="@color/color_white" />

    <TextView android:id="@+id/eventview_location"
        android:layout_width="wrap_content" android:layout_height="wrap_content"
        android:layout_alignParentEnd="true" android:layout_alignParentRight="true"
        android:layout_below="@+id/eventview_price" android:layout_toEndOf="@+id/eventview_icon"
        android:layout_toRightOf="@+id/eventview_icon" android:text="Small Text"
        android:textAppearance="?android:attr/textAppearanceSmall"
        android:textColor="@color/color_white" />

    <TextView android:id="@+id/eventview_price"
        android:layout_width="wrap_content" android:layout_height="wrap_content"
        android:layout_alignParentEnd="true" android:layout_alignParentRight="true"
        android:layout_below="@+id/eventview_title" android:layout_toEndOf="@+id/eventview_icon"
        android:layout_toRightOf="@+id/eventview_icon" android:text="Small Text"
        android:textAppearance="?android:attr/textAppearanceSmall"
        android:textColor="@color/color_white" />

    <TextView android:id="@+id/eventview_shortdesc"
        android:layout_width="wrap_content" android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/eventview_title"
        android:layout_alignParentEnd="true" android:layout_alignParentLeft="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentStart="true" android:layout_alignStart="@+id/eventview_title"
        android:layout_below="@+id/eventview_icon"
        android:layout_marginBottom="@dimen/half_margin"
        android:layout_marginLeft="@dimen/half_margin" android:text="Medium Text"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:textColor="@color/color_white" android:width="0dip" />

</RelativeLayout>

When an Activity instantiates my view, it must supply a source for the data (a custom class). It is then (under setSource()) that a method updateLayout() is called, which sets the icon image, and the various TextViews. Additionally, it sets the eventview_cover's source to a BitmapDrawable (to modify the original photo's alpha). That, in turn, extends the height of the view (which I want to avoid). The height of the view should only be governed by the heights of the TextViews and the ImageView for the icon. Here's the code for EventView:

public class EventView extends RelativeLayout {

    private MergeEvent src = null;

    public MergeEvent getSource() {
        return src;
    }

    protected void setSource(MergeEvent e) {
        src = e;
        //The data was updated, so we need to update the view!
        updateLayout();
    }

    public EventView(MergeEvent src, Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        setSource(src);
    }

    public EventView(MergeEvent src, Context context, AttributeSet attrs) {
        super(context, attrs);
        setSource(src);
    }

    public EventView(MergeEvent src, Context context) {
        super(context);
        setSource(src);
    }

    protected void updateLayout() {
        if (getSource() != null) {
            //Get source data.
            MergeEvent src = getSource();
            //Set the layout.
            View.inflate(getContext(), R.layout.eventview, this);
            //Get references to the TextViews and ImageViews
            TextView title = (TextView)findViewById(R.id.eventview_title),
                     price = (TextView)findViewById(R.id.eventview_price),
                     location = (TextView)findViewById(R.id.eventview_location),
                     shortdesc = (TextView)findViewById(R.id.eventview_shortdesc);
            ImageView icon = (ImageView)findViewById(R.id.eventview_icon), 
                      cover = (ImageView)findViewById(R.id.eventview_cover);
            icon.setImageBitmap(src.getIcon());
            title.setText(src.getTitle());
            price.setText("$" + src.getPrice());
            location.setText(src.getLocation());
            shortdesc.setText(src.getShortDescription());
            //Create a new BitmapDrawable from the source's cover (a Bitmap)
            BitmapDrawable bd = new BitmapDrawable(getResources(), src.getCover());
            bd.setAlpha(128);
            bkg.setImageDrawable(bd);
            requestLayout();
        }
    }

}

This all works, but it resizes the view to make room for the cover photo, which again, I want to avoid. I tried using getHeight() before I set the drawable, then set the drawable, and set the cover's ImageView's height with bkg.getLayoutParams().height = height, but the call to getHeight() returned 0 because the view is technically not visible at this point, so the cover photo was invisible. The view should look like this, where the background image is cropped and centered:
EventView model

tl;dr/summary:

How can I prevent an ImageView from resizing its parent?

Community
  • 1
  • 1
Greg Whatley
  • 1,020
  • 1
  • 13
  • 32

1 Answers1

0

I found this answer on another question very similar to mine:

This needs to be done using code. You need to call those size APIs a few milliseconds after the screen renders. So, if you call it 100 milliseconds after, using postDelayed method of any view that has been rendered, you will get the sizes.

Using that, I modified my updateLayout() method to this:

protected void updateLayout() {
    if (getSource() != null) {
        MergeEvent src = getSource();
        View.inflate(getContext(), R.layout.eventview, this);
        TextView title = (TextView)findViewById(R.id.eventview_title);
        TextView price = (TextView)findViewById(R.id.eventview_price);
        TextView location = (TextView)findViewById(R.id.eventview_location);
        TextView shortdesc = (TextView)findViewById(R.id.eventview_shortdesc);
        ImageView i = (ImageView)findViewById(R.id.eventview_icon);
        i.setImageBitmap(src.getIcon());
        title.setText(src.getTitle());
        price.setText("$" + src.getPrice());
        location.setText(src.getLocation());
        shortdesc.setText(src.getShortDescription());
        //use postDelay to set the ImageView's source and max size after 100 miliseconds (plenty of time for the UI to be drawn)
        this.postDelayed(new Runnable() {

            @Override
            public void run() {
                BitmapDrawable bd = new BitmapDrawable(getResources(), src.getCover());
                bd.setAlpha(128);
                ImageView bkg = (ImageView)findViewById(R.id.eventview_cover);
                bkg.setMaxHeight(getHeight());
                bkg.setImageDrawable(bd);
            }

        }, 100);
        requestLayout();
    }
}
Community
  • 1
  • 1
Greg Whatley
  • 1,020
  • 1
  • 13
  • 32