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


79

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

보기 보다 작은 이미지가있는 이미지보기가 있습니다. 이미지를 화면 너비에 맞게 조정하고 비례 적으로 올바른 이미지 높이를 반영하도록 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. 뷰 높이에 따라 이미지가 수직으로 왜곡됩니다.


시도해 보셨습니까 android:scaleType="fitCenter"?
Michael Celey

1
@ BrainSlugs83 나는 가지고 있고 여전히 나를 위해 작동합니다. 또한 질문자는 질문자가 무엇을 시도했는지 결정하기 위해 제기되었습니다. 특히 게시물이 게시 된 지 7 개월이 지나지 않은 경우에는 우스꽝 스러울 필요가 없습니다.
Michael Celey

작동하지 않습니다. -아래를 참조하십시오. 또한 시도해 보았지만 작동하지 않는지 확인할 수 있습니다 (해본 결과 다른 결과가 표시되는 경우 아래에서 논의하여 우리가 무엇을 잘못하고 있는지 보여주십시오.) 내가 올 수있는 유일한 결론은 질문하거나 시도하지 않았습니다).
BrainSlugs83 2013-08-02

답변:


110

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

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>

4
+1 훌륭한 솔루션은 Nexus 7에서도 완벽하게 작동합니다. 그리고 가장 좋은 점은 Eclipse의 Layout Editor에서도 올바르게 작동한다는 것입니다.
Ridcully

Galaxy S4에서 작동합니다. 왜 안돼 :)
THx

감사. 훌륭한 솔루션. heightMeasureSpec을 기반으로 동일한 작업을 수행하도록 쉽게 수정할 수 있습니다.
speedynomads 2011

1
예,하지만 아닙니다 ...이 솔루션은 이미지를 흐리게합니다. ImageView와 fitCenter를 고정 높이로 사용하면 이미지가 흐려지지 않습니다 (그러나 고정 높이는 저에게 해결책이 아닙니다). 블러 링을 방지하는 방법?
Geltrude

몇 주 동안이 솔루션을 찾고있었습니다. 그래도 고급의 하나의 이미지에 원하는하지만이 완벽하게 작동
소코

36

당신과 같은 문제가있었습니다. 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" />

4
여기서 핵심은 adjustViewBounds를 사용하는 것입니다.
user3690202 2017

@ user3690202 당신이 맞습니다, 그것은 내 문제도 해결했습니다. 감사합니다
Parth Patel

22

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

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

실망 스럽습니다.


8
  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" />

2
그 결과 이미지의 첫 번째 버전이 생성됩니다. 가로로 확장되지 않고 가운데에 양쪽에 여백이 있습니다. 좋지 않다.
Mundi

2
작동하지 않습니다. 정확한 높이의 이미지가 생성되지만 가로로 확장되지는 않습니다. 좋지 않다. 또한 질문에서 내 편집을 참조하십시오.
Mundi

1
nasa.gov/images/content/715945main__NOB0093_4x3_516-387.jpg 중요한 부분은 Nexus 7의 화면보다 작게 보인다는 것입니다.
Mundi

2
좋지 않다. 나는 높이를 모른다-그것은 역동적이다. 예측할 수없는 왜곡이 발생합니다. 내 질문의 편집은 이미 이것을 다루고 있습니다. 죄송합니다. 노력해 주셔서 감사합니다! Google에 수치심!
Mundi

1
이것이 옵션이라는 것을 알고 있었지만 XML 솔루션을 찾고있었습니다 . 그래도 답을 수정해야합니다. 감사!
Mundi

8

이것은 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);
        }
    }
}

이 솔루션은 세로 또는 가로 모드에서 자동으로 작동합니다. Mark의 솔루션에서와 마찬가지로 레이아웃에서 참조합니다. 예 :

<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" />

3

동일한 문제가 발생했지만 고정 된 높이로 이미지의 원래 종횡비를 유지하면서 너비를 조정했습니다. 가중치가 적용된 선형 레이아웃을 통해 해결했습니다. 필요에 따라 수정할 수 있습니다.

<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>

이 솔루션은 저에게 효과적이었습니다. 내 ImageView에 특정 높이를 부여하고 ImageView가 가로 세로 비율을 유지하기 위해 너비를 동적으로 조정하도록 할 수있었습니다.
Luke

0

Mark Martinsson의 답변 Kotlin 버전 :

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)
    }
}

0

Mark Matinsson의 솔루션에 하나 더 추가되었습니다. 내 이미지 중 일부가 다른 이미지보다 확대 된 것을 발견했습니다. 그래서 이미지가 최대 요소로 조정되도록 클래스를 수정했습니다. 이미지가 너무 작아서 흐릿 해지지 않고 최대 너비로 크기를 조정할 수없는 경우 최대 제한을 초과하는 크기 조정이 중지됩니다.

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);
        }
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.