M. le Rutte
M. le Rutte

Reputation: 3563

Equivalent of ImageView scaleType 'centerCrop' to bitmap drawable gravity

I have created an activity with a header image. This header image is originally created int the Activity's layout xml using an ImageView where the scaleType is set to centerCrop. This does what I want, it centers the image, clipping it left and right in portrait mode, showing all in landscape mode.

<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="match_parent"
    android:paddingTop="30dp"
    android:paddingBottom="6dp"
    android:paddingLeft="6dp"
    android:paddingRight="6dp"
    android:background="#919EAC"
    android:orientation="vertical" >

<ImageView
    android:id="@+id/header_image"
    android:layout_width="match_parent"
    android:layout_height="120dp"
    android:contentDescription="@string/header_description"
    android:scaleType="centerCrop"
    android:src="@drawable/header" />

    .... <other views> ...

I'd like to replace this with a background drawable so that I can use the header image space to display data, and it saves me repeating the same layout in the different activities.

For this reason I have created a drawable that I can refer to in the android:background attribute:

    <layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
        <item>
            <shape android:shape="rectangle" >
                <solid android:color="#919EAC" />
            </shape>
        </item>
        <item>
            <bitmap 
                android:antialias="true"
                android:gravity="top|center_horizontal"
                android:src="@drawable/header" />
        </item>
    </layer-list>

This drawable defines the colored background that otherwise the layout would define and it defines a header image that otherwise would be included in the layout as an ImageView.

However now my image is scaled, while I would like it to be cropped.

Checking the Android documentation I tried other gravity modes such as

    android:gravity="top|clip_horizontal"

But it still seems to display/scale differently than the image view.

What would be the correct definition of the background drawable?

Upvotes: 42

Views: 14737

Answers (4)

Sergii Rudchenko
Sergii Rudchenko

Reputation: 5190

I solved this problem with a decorator which maintains the aspect ratio of the underlying drawable: https://gist.github.com/rudchenkos/e33dc0d6669a61dde9d6548f6c3e0e7e

Unfortunately, there is no way to apply it from XML so I do that at the very beginning of my splash Activity:

public class SplashActivity extends AppCompatActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        final Drawable bg = getResources().getDrawable(R.drawable.screen);
        getWindow().setBackgroundDrawable(new CenterCropDrawable(bg));

        ...
    }
}

That is roughly equivalent to specifying the drawable as android:windowBackground in the Activity theme

Upvotes: 3

Arnold Balliu
Arnold Balliu

Reputation: 1119

To center crop a bitmap in code do this:

public static Bitmap cropCenter(Bitmap bmp) {
    int dimension = Math.min(bmp.getWidth(), bmp.getHeight());
    return ThumbnailUtils.extractThumbnail(bmp, dimension, dimension);
}

I don't know of any other way to centerCrop a bitmap xml wise.

Hope it helps anyone.

I found this solution from this post: Android Crop Center of Bitmap

Upvotes: 3

Raghubansh Mani
Raghubansh Mani

Reputation: 305

I don't know how to do it with the background. You can try other solutions though:

1) Easiest solution to displaying something on top of image is to put them both in some layout so that they overlap. For example, you can use a RelativeLayout with the dimensions of the ImageView, the ImageView is match_parent in both dimensions and a TextView in center.

2) You can save the Imageview in a different layout, say, header.xml, and use it by include header.xml everywhere you need it.

3) If the layout to be displayed on top of ImageView is same everywhere then you can create a custom layout with an ImageView and say, a TextView in center, and use that layout everywhere. You can set the TextView string on this custom layout then. You can read more on custom layouts, they are easy.

Upvotes: -1

MKJParekh
MKJParekh

Reputation: 34301

Using scaleType = "centerCrop" you were achieving a result which you desired, cropping the edges of image and show center portion whichever fits to that size.

For ImageView :

ImageView have scaleType attribute which works only for the Image that is set to it as source to display. i.e. as if it were TextView then Text is it's source.

Even you might have noticed that scaleType doesn't work for image that's set as background that only works with image that's supplied as source either in XML of at runtime.

For Layout

Layout can show background images, but there is no any attribute given for layout which can process the background images and scale it as per the attribute's value.

So you should stop asking the facility of ImageView from Layout, because It doesn't have it.

2 different Solutions to Your Problem

1) Keep proper Images for background header in different drawable folder and use it, this way you don't require to scale it runtime as you already developed image for the size differently.

2) You need to just redesign your XML, like below sample

<RelativeLayout 
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    >

    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="wrap_content"
        android:layout_height="50dp"
        android:background="@drawable/subway"
        android:scaleType="centerCrop" />

    <Button
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_alignParentLeft="true"
         />

    <EditText
        android:id="@+id/editText1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        />
</RelativeLayout> 

Upvotes: -6

Related Questions