22

I'm coding android and I have a imageview. I want to set scaletype of this to topcrop. I could find centercrop in options, but it's not my request. How do I do?

Javad Abedi
  • 396
  • 1
  • 3
  • 11

4 Answers4

32

Custom Android ImageView for top-crop scaling of the contained drawable.

import android.content.Context;
import android.graphics.Matrix;
import android.widget.ImageView;

/**
* ImageView to display top-crop scale of an image view.
*
* @author Chris Arriola
*/
public class TopCropImageView extends ImageView {

public TopCropImageView(Context context) {
    super(context);
    setScaleType(ScaleType.MATRIX);
}

@Override
protected boolean setFrame(int l, int t, int r, int b) {
    final Matrix matrix = getImageMatrix();

    float scale;
    final int viewWidth = getWidth() - getPaddingLeft() - getPaddingRight();
    final int viewHeight = getHeight() - getPaddingTop() - getPaddingBottom();
    final int drawableWidth = getDrawable().getIntrinsicWidth();
    final int drawableHeight = getDrawable().getIntrinsicHeight();

    if (drawableWidth * viewHeight > drawableHeight * viewWidth) {
        scale = (float) viewHeight / (float) drawableHeight;
    } else {
        scale = (float) viewWidth / (float) drawableWidth;
    }

    matrix.setScale(scale, scale);
    setImageMatrix(matrix);

    return super.setFrame(l, t, r, b);
}        
}

https://gist.github.com/arriolac/3843346

Jay
  • 1,474
  • 9
  • 13
  • how to implement this. i asked a question regarding this http://stackoverflow.com/questions/32359213/trying-to-use-custom-imageview-topcrop-in-android-but-the-the-app-stops. – Santhosh Sep 02 '15 at 17:33
  • @Jay it works great. Im making matrix computations in onLayout() method, which gets called in on rotation also, where setFrame doesn't. – box Jul 29 '16 at 12:00
  • 2
    I call super.setFrame(l, t, r, b); in the beginning or getWidth() will return 0 – JackWu Mar 07 '18 at 14:06
14

I just wanted a temporary solution without excess work . Try this

<ImageView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:scaleType="centerCrop"
    android:scrollY="-100dp"
    android:id="@+id/poster"
   />

scrollY pulls your image up or down. Try it with different dp's and you 'll find the right size.

rahulxyz
  • 437
  • 4
  • 12
  • 8
    While this achieves the task at hand, it does not work for different screen resolutions or parent view sizes. Probably not recommended for production, as you will get unexpected results in the wild. :) – DoctorD Jun 10 '17 at 17:14
  • Yes, that's true i learned it the hard way. It behaves differently on various screens. – rahulxyz Jun 10 '17 at 19:03
  • I only needed to move the image slightly and this worked perfectly, thanks. – HB. Jul 06 '18 at 08:28
4

I don't believe you need a custom Image View for this. All you have to do is set the scaleType to matrix and set a custom matrix to the ImageView.

Refer: https://stackoverflow.com/a/38049348/4747587

Community
  • 1
  • 1
Henry
  • 17,490
  • 7
  • 63
  • 98
1

Fixed version:

  • setFrame calling asap
  • not reusing Matrix -> it caused issue that when image realoaded too soon (with Picasso), the image was scaled too much
import android.content.Context
import android.graphics.Matrix
import android.util.AttributeSet
import androidx.appcompat.widget.AppCompatImageView

class TopCropImageView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0,
) : AppCompatImageView(context, attrs, defStyleAttr) {

    init {
        scaleType = ScaleType.MATRIX
    }

    override fun setFrame(l: Int, t: Int, r: Int, b: Int): Boolean {
        super.setFrame(l, t, r, b)
        val matrix = Matrix()
        val scale: Float
        val viewWidth: Int = width - paddingLeft - paddingRight
        val viewHeight: Int = height - paddingTop - paddingBottom
        val drawableWidth: Int = drawable.intrinsicWidth
        val drawableHeight: Int = drawable.intrinsicHeight
        scale = if (drawableWidth * viewHeight > drawableHeight * viewWidth) {
            viewHeight.toFloat() / drawableHeight.toFloat()
        } else {
            viewWidth.toFloat() / drawableWidth.toFloat()
        }
        matrix.setScale(scale, scale)
        imageMatrix = matrix
        return true
    }
}
hrach
  • 2,443
  • 2
  • 26
  • 37