How to align ImageView to the bottom, fill its width and height, and keep its aspect ratio?

后端 未结 6 1946
攒了一身酷
攒了一身酷 2021-02-05 11:36

Background

There are various XML attributes for ImageView to scale its content , and various layout views that allow to place views and set their sizes.

Howeve

相关标签:
6条回答
  • 2021-02-05 12:29

    Try using android:scaleType="fitCenter"

    Edit

    Hm, I saw what you mean, another option is to have it fitEnd on the portrait xml and create an identical xml on layout-land folder (create it if needed) with android:scaleType="fitCenter" which will be used on landscape only

    0 讨论(0)
  • 2021-02-05 12:32

    this is a proof-om-concept custom ImageView, you will need to add missing constructors and perform the Matrix setting whenever ImageView's Drawable changes:

    class V extends ImageView {
        public V(Context context) {
            super(context);
            setScaleType(ScaleType.MATRIX);
        }
        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);
            Drawable d = getDrawable();
            if (d != null) {
                Matrix matrix = new Matrix();
                RectF src = new RectF(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
                RectF dst = new RectF(0, 0, w, h);
                matrix.setRectToRect(src, dst, Matrix.ScaleToFit.CENTER);
                float[] points = {
                        0, d.getIntrinsicHeight()
                };
                matrix.mapPoints(points);
                matrix.postTranslate(0, h - points[1]);
                setImageMatrix(matrix);
            }
        }
    }
    

    how it works in short:

    • first the Matrix is set by calling Matrix.setRectToRect() with stf == Matrix.ScaleToFit.CENTER, the result is the same as ImageView.ScaleType.FIT_CENTER

    • then in order to align the Drawable to the bottom Matrix.mapPoints() is called, it maps the Drawable's left/bottom corner and the result is transformed point as would be seen in the ImageView

    • and finally Matrix.postTranslate() translates the MAtrix in Y axis to the ImageView's bottom

    0 讨论(0)
  • 2021-02-05 12:36

    You need a combination of three attributes:

    android:layout_height="wrap_content"
    android:scaleType="fitCenter"
    android:adjustViewBounds="true"
    

    The adjustViewBounds attribute is needed because ImageView measures itself to match the original dimensions of the drawable by default, without regard to any scaling performed according to the scale type.

    0 讨论(0)
  • 2021-02-05 12:36

    I used android:scaleType="fitXY" but it got me trying it so many times until the image did get fit the XY of the whole screen,,, what I mean there is a wierd bug in scaleType and fitEnd will work fine but you'll need to delete it and write again until it fit the end of any screen without corpping. Bottom line scaleType has bugs and bugs you until it gives you what you need.

    0 讨论(0)
  • 2021-02-05 12:36

    Fist of all, I don't really understand what you really want for align image to the bottom from what I read your layout. My layout will make the image center, and scale you can modify the high of the bottom view to see how image will look like. Change the high of the top or bottom view the image size will scale up or down depend on the space available for imageView.

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    
        <View
            android:id="@+id/topView"
            android:layout_width="match_parent"
            android:layout_height="100dp"
            android:layout_alignParentTop="true"
            android:background="#FF00ff00" />
    
    
        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_above="@+id/bottomView"
            android:layout_below="@+id/topView">
    
            <ImageView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_gravity="center_horizontal"
                android:background="#FFffff00"
                android:scaleType="fitCenter"
                android:src="@android:drawable/sym_def_app_icon" />
        </FrameLayout>
    
        <View
            android:id="@+id/bottomView"
            android:layout_width="match_parent"
            android:layout_height="100dp"
            android:layout_alignParentBottom="true"
            android:layout_centerHorizontal="true"
            android:background="#FFff0000" />
    </RelativeLayout>
    

    Hope this will fix your problem.

    0 讨论(0)
  • 2021-02-05 12:37

    You can use is custom FitWidthAtBottomImageView to achieve this code:

    public class FitWidthAtBottomImageView extends ImageView {
        public FitWidthAtBottomImageView(Context context) {
            super(context);
        }
    
        public FitWidthAtBottomImageView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public FitWidthAtBottomImageView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
        public FitWidthAtBottomImageView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
            super(context, attrs, defStyleAttr, defStyleRes);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            int i = getWidth() - getPaddingLeft() - getPaddingRight();
            int j = getHeight() - getPaddingTop() - getPaddingBottom();
            if (getBackground() != null) {
                getBackground().draw(canvas);
            }
            if (getDrawable() != null && getDrawable() instanceof BitmapDrawable) {
                Bitmap bitmap = ((BitmapDrawable) getDrawable()).getBitmap();
                int h = bitmap.getHeight() * i / bitmap.getWidth();
                canvas.drawBitmap(bitmap, null, new RectF(getPaddingLeft(), getPaddingTop() + j - h, getPaddingLeft() + i, getHeight() - getPaddingBottom()), null);
            } else {
                super.onDraw(canvas);
            }
    
        }
    }
    

    by manually draw the bottom aligned image that you want.

    0 讨论(0)
提交回复
热议问题