Development Tip

Android ImageView는 자르기 또는 왜곡없이 유연한 높이로 더 작은 이미지를 너비로 조정합니다.

yourdevel 2020. 10. 13. 19:30
반응형

Android ImageView는 자르기 또는 왜곡없이 유연한 높이로 더 작은 이미지를 너비로 조정합니다.


자주 묻고 대답하지 않았습니다 (적어도 재현 가능한 방식은 아닙니다).

보기 보다 작은 이미지가있는 이미지보기가 있습니다. 이미지를 화면 너비에 맞게 조정하고 비례 적으로 올바른 이미지 높이를 반영하도록 ImageView의 높이를 조정하고 싶습니다.

<ImageView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
/>

이로 인해 이미지가 원래 크기 (화면 너비보다 작음)에 중앙에 위치하며 측면에 여백이 있습니다. 좋지 않다.

그래서 추가했습니다

android:adjustViewBounds="true" 

같은 효과, 좋지 않습니다. 나는 추가했다

android:scaleType="centerInside"

같은 효과, 좋지 않습니다. 로 변경 centerInside했습니다 fitCenter. 같은 효과, 좋지 않습니다. 로 변경 centerInside했습니다 centerCrop.

android:scaleType="centerCrop"

이제 마지막으로 이미지가 화면 너비에 맞게 조정 되지만 상단과 하단이 잘립니다 ! 그래서 변화 centerCropfitXY.

android:scaleType="fitXY"

이제 이미지가 화면 너비에 맞게 조정 되지만 y 축에서는 조정 되지 않아 이미지 왜곡 됩니다.

제거해 android:adjustViewBounds="true"도 효과가 없습니다. android:layout_gravity다른 곳에서 제안한대로를 추가해도 다시 효과가 없습니다.

나는 다른 조합을 시도했지만 아무 소용이 없습니다. 그래서, 누구든지 알고 있습니까?

화면 너비를 채우고, 전체보기를 채우기 위해 더 작은 이미지의 크기를 조정하고, 왜곡이나 자르기없이 종횡비로 이미지를 표시하도록 ImageView의 XML을 어떻게 설정합니까?

편집 : 또한 임의의 숫자 높이 설정을 시도했습니다. 이것은 설정에만 영향을 미칩니다 centerCrop. 뷰 높이에 따라 이미지가 수직으로 왜곡됩니다.


레이아웃 파일에 포함하는 자바 클래스를 만들어이 문제를 해결했습니다.

public class DynamicImageView extends ImageView {

    public DynamicImageView(final Context context, final AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
        final Drawable d = this.getDrawable();

        if (d != null) {
            // ceil not round - avoid thin vertical gaps along the left/right edges
        final int width = MeasureSpec.getSize(widthMeasureSpec);
        final int height = (int) Math.ceil(width * (float) d.getIntrinsicHeight() / d.getIntrinsicWidth());
            this.setMeasuredDimension(width, height);
        } else {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    }
}

이제 레이아웃 파일에 클래스를 추가하여 이것을 사용합니다.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <my.package.name.DynamicImageView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:scaleType="centerCrop"
        android:src="@drawable/about_image" />
</RelativeLayout>

당신과 같은 문제가있었습니다. 30 분 동안 다양한 변형을 시도한 후 이러한 방식으로 문제를 해결했습니다. 그것은 당신에게 제공 유연한 높이폭은 부모 폭으로 조정

<ImageView
            android:id="@+id/imageview_company_logo"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:adjustViewBounds="true"
            android:scaleType="fitCenter"
            android:src="@drawable/appicon" />

XML 레이아웃 표준에는 실행 가능한 솔루션이 없습니다.

동적 이미지 크기에 반응하는 신뢰할 수있는 유일한 방법 LayoutParams은 코드 에서 사용하는 것 입니다.

실망 스럽습니다.


  android:scaleType="fitCenter"

원래의 src 종횡비를 유지하면서 src가 dst 안에 완전히 들어가도록하는 스케일을 계산합니다. 하나 이상의 축 (X 또는 Y)이 정확히 맞습니다. 결과는 dst의 중앙에 있습니다.

편집하다:

여기서 문제는이 layout_height="wrap_content"이미지가 확장되는 것을 "허용"하지 않는다는 것입니다. 변경 사항에 대한 크기를 설정해야합니다.

  android:layout_height="wrap_content"

...에

  android:layout_height="100dp"  // or whatever size you want it to be

edit2 :

잘 작동합니다.

<ImageView
    android:id="@+id/imageView1"
    android:layout_width="match_parent"
    android:layout_height="300dp"
    android:scaleType="fitCenter"
    android:src="@drawable/img715945m" />

이것은 Mark Martinsson의 우수한 솔루션에 대한 작은 추가 사항입니다.

이미지의 너비가 높이보다 큰 경우 Mark의 솔루션은 화면의 상단과 하단에 공간을 남깁니다.

아래는 먼저 너비와 높이를 비교하여이 문제를 해결합니다. 이미지 너비가> = 높이이면 화면 높이와 일치하도록 높이를 조정 한 다음 가로 세로 비율을 유지하기 위해 너비를 조정합니다. 마찬가지로 이미지 높이> 너비 인 경우 화면 너비와 일치하도록 너비를 조정 한 다음 가로 세로 비율을 유지하기 위해 높이를 조정합니다.

즉, 다음의 정의를 적절하게 충족합니다 scaleType="centerCrop".

http://developer.android.com/reference/android/widget/ImageView.ScaleType.html

이미지의 크기 (너비 및 높이)뷰의 해당 크기 (여백 제외) 보다 크 거나 같 도록 이미지의 크기를 균일하게 조정합니다 (이미지의 가로 세로 비율 유지 ).

package com.mypackage;

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.ImageView;

public class FixedCenterCrop extends ImageView
{
    public FixedCenterCrop(final Context context, final AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec)
    {
        final Drawable d = this.getDrawable();

        if(d != null) {
            int height = MeasureSpec.getSize(heightMeasureSpec);
            int width = MeasureSpec.getSize(widthMeasureSpec);

            if(width >= height)
                height = (int) Math.ceil(width * (float) d.getIntrinsicHeight() / d.getIntrinsicWidth());
            else
                width = (int) Math.ceil(height * (float) d.getIntrinsicWidth() / d.getIntrinsicHeight());

            this.setMeasuredDimension(width, height);

        } else {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    }
}

This solution automatically works in either portrait or landscape mode. You reference it in your layout just as you do in Mark's solution. E.g.:

<com.mypackage.FixedCenterCrop
    android:id="@+id/imgLoginBackground"
    android:src="@drawable/mybackground"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:scaleType="centerCrop" />

I ran into the same problem, but with a fixed height, scaled width keeping the image's original aspect ratio. I solved it via a weighted linear layout. You can hopefully modify it for your needs.

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

    <ImageView
        android:id="@+id/image"
        android:layout_width="0px"
        android:layout_height="180dip"
        android:layout_weight="1.0"
        android:adjustViewBounds="true"
        android:scaleType="fitStart" />

</LinearLayout>

Kotlin version of Mark Martinsson's answer:

class DynamicImageView(context: Context, attrs: AttributeSet) : AppCompatImageView(context, attrs) {
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
    val drawable = this.drawable

    if (drawable != null) {
        //Ceil not round - avoid thin vertical gaps along the left/right edges
        val width = View.MeasureSpec.getSize(widthMeasureSpec)
        val height = Math.ceil((width * drawable.intrinsicHeight.toFloat() / drawable.intrinsicWidth).toDouble()).toInt()
        this.setMeasuredDimension(width, height)
    } else {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
    }
}

One more addition to Mark Matinsson's solution. I found that some of my images were over scaled than others. So I modified the class so that the image is scaled by a maximum factor. If the image is too small to be scaled at max width without becoming blurry, it stops scaling beyond the max limit.

public class DynamicImageView extends ImageView {

    final int MAX_SCALE_FACTOR = 2;
    public DynamicImageView(final Context context) {
        super(context);
    }

    @Override
    protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
        final Drawable d = this.getDrawable();

        if (d != null) {
            // ceil not round - avoid thin vertical gaps along the left/right edges
            int width = View.MeasureSpec.getSize(widthMeasureSpec);
            if (width > (d.getIntrinsicWidth()*MAX_SCALE_FACTOR)) width = d.getIntrinsicWidth()*MAX_SCALE_FACTOR;
            final int height = (int) Math.ceil(width * (float) d.getIntrinsicHeight() / d.getIntrinsicWidth());
            this.setMeasuredDimension(width, height);
        } else {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    }
}

참고URL : https://stackoverflow.com/questions/13992535/android-imageview-scale-smaller-image-to-width-with-flexible-height-without-crop

반응형