ImageView 너비를 채우고 가로 세로 비율을 유지하도록 이미지 크기 조정


200

있습니다 GridView. 의 데이터 GridView는 서버의 요청입니다.

항목 레이아웃은 다음과 같습니다 GridView.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/analysis_micon_bg"
    android:gravity="center_horizontal"
    android:orientation="vertical"
    android:paddingBottom="@dimen/half_activity_vertical_margin"
    android:paddingLeft="@dimen/half_activity_horizontal_margin"
    android:paddingRight="@dimen/half_activity_horizontal_margin"
    android:paddingTop="@dimen/half_activity_vertical_margin" >

    <ImageView
        android:id="@+id/ranking_prod_pic"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"
        android:contentDescription="@string/app_name"
        android:scaleType="centerCrop" />

    <TextView
        android:id="@+id/ranking_rank_num"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/ranking_prod_num"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/ranking_prod_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>

서버에서 데이터를 요청하고 이미지 URL을 가져 와서 이미지를로드합니다. Bitmap

public static Bitmap loadBitmapFromInputStream(InputStream is) {
    return BitmapFactory.decodeStream(is);
}

public static Bitmap loadBitmapFromHttpUrl(String url) {
    try {
        return loadBitmapFromInputStream((InputStream) (new URL(url).getContent()));
    } catch (Exception e) {
        Log.e(TAG, e.getMessage());
        return null;
    }
}

getView(int position, View convertView, ViewGroup parent)어댑터 에 메소드 코드가 있습니다.

Bitmap bitmap = BitmapUtil.loadBitmapFromHttpUrl(product.getHttpUrl());
prodImg.setImageBitmap(bitmap);

이미지 크기는 210*210입니다. Nexus 4에서 애플리케이션을 실행합니다. 이미지는 ImageView너비를 채우지 만 ImageView높이는 조정되지 않습니다. ImageView전체 이미지를 표시하지 않습니다.

이 문제를 어떻게 해결합니까?

답변:


548

사용자 정의 클래스 또는 라이브러리를 사용하지 않는 경우 :

<ImageView
    android:id="@id/img"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:adjustViewBounds="true"
    android:scaleType="fitCenter" />

scaleType="fitCenter" (생략시 기본값)

  • 가로 세로 비율을 유지하면서 필요에 따라 부모가 허용하는 한도에서 확대 / 축소 할 수 있습니다.

scaleType="centerInside"

  • 기본 src너비
    가 부모 너비보다 작은 경우 이미지를 가로로 가운데에 배치합니다
  • 기본 src너비
    가 부모 너비보다 큰 경우 부모 너비 가 허용하고 축소 비율을 유지하는 가로 세로 비율만큼 너비 가 넓어집니다.

사용 android:src하거나 ImageView.setImage*메소드 를 사용하는지 여부는 중요하지 않으며 키는 아마도입니다 adjustViewBounds.


5
android : layout_height = "wrap_content"android : adjustViewBounds = "true"android : scaleType = "fitCenter"는 트릭을 수행합니다
James Tan

너비에 fill_parent대한 @JamesTan 은 좋은 습관이며 고정 크기도 작동합니다.
TWiStErRob

@TWiStErRob 나는 android : adjustViewBounds = "true"가 필요하다는 것을 알고 있습니다. 그렇지 않으면 높이에 따라 맞지 않습니다. 그리고 맞습니다. 부모님에게 맞는 너비는 완전한 버전입니다
James Tan

9
API 19 이상에서는 매력처럼 작동하지만 API 16에서는 테스트되지 않았습니다. Alex Semeniuk의 커스텀 뷰는 API 16에서도 작동합니다.
Ashkan Sarlak

1
@ F.Mysir whops 😅, 그렇습니다. 문제에 대해서는 어느 것이 중요하지 않지만 모범 사례를 전파하는 데 전적으로 동의합니다.
TWiStErRob

42

나는 arnefm의 대답을 좋아하지만 작은 실수를 했으므로 (댓글 참조) 수정하려고합니다.

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

/**
 * ImageView that keeps aspect ratio when scaled
 */
public class ScaleImageView extends ImageView {

  public ScaleImageView(Context context) {
    super(context);
  }

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

  public ScaleImageView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
  }

  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    try {
      Drawable drawable = getDrawable();
      if (drawable == null) {
        setMeasuredDimension(0, 0);
      } else {
        int measuredWidth = MeasureSpec.getSize(widthMeasureSpec);
        int measuredHeight = MeasureSpec.getSize(heightMeasureSpec);
        if (measuredHeight == 0 && measuredWidth == 0) { //Height and width set to wrap_content
          setMeasuredDimension(measuredWidth, measuredHeight);
        } else if (measuredHeight == 0) { //Height set to wrap_content
          int width = measuredWidth;
          int height = width *  drawable.getIntrinsicHeight() / drawable.getIntrinsicWidth();
          setMeasuredDimension(width, height);
        } else if (measuredWidth == 0){ //Width set to wrap_content
          int height = measuredHeight;
          int width = height * drawable.getIntrinsicWidth() / drawable.getIntrinsicHeight();
          setMeasuredDimension(width, height);
        } else { //Width and height are explicitly set (either to match_parent or to exact value)
          setMeasuredDimension(measuredWidth, measuredHeight);
        }
      }
    } catch (Exception e) {
      super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
  }

}

따라서 ImageView(예를 들어) 안에 넣으면 치수가 올바르게 조정되고 치수 문제가 없습니다.ScrollView


thx, arnefm의 답변 바로 아래에 솔루션을 찾았습니다. 그것은 there링크입니다
Joe

36

비슷한 문제가 한 번있었습니다. 커스텀 ImageView를 만들어서 해결했습니다.

public class CustomImageView extends ImageView

그런 다음 imageview의 onMeasure 메소드를 대체하십시오. 나는 내가 믿는 것과 같은 것을했다 :

    @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    try {
        Drawable drawable = getDrawable();

        if (drawable == null) {
            setMeasuredDimension(0, 0);
        } else {
            float imageSideRatio = (float)drawable.getIntrinsicWidth() / (float)drawable.getIntrinsicHeight();
            float viewSideRatio = (float)MeasureSpec.getSize(widthMeasureSpec) / (float)MeasureSpec.getSize(heightMeasureSpec);
            if (imageSideRatio >= viewSideRatio) {
                // Image is wider than the display (ratio)
                int width = MeasureSpec.getSize(widthMeasureSpec);
                int height = (int)(width / imageSideRatio);
                setMeasuredDimension(width, height);
            } else {
                // Image is taller than the display (ratio)
                int height = MeasureSpec.getSize(heightMeasureSpec);
                int width = (int)(height * imageSideRatio);
                setMeasuredDimension(width, height);
            }
        }
    } catch (Exception e) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

가로 세로 비율을 유지하면서 이미지를 화면에 맞게 늘릴 수 있습니다.


1
거기를 참조하십시오 . 첫 번째 답변
Joe

이 대답은 정확하지 않습니다. 설정 한 상황을 고려하십시오 android:layout_height="wrap_content". 이 경우 MeasureSpec.getSize(heightMeasureSpec)될 것입니다 0viewSideRatio발생합니다 Infinity(이 경우 궁금해 할 필요없이, 자바 플로트. 같은 값을 허용) 모두 당신 heightwidth할 것이다 0.
Alex Semeniuk

1
채우기 작업을하려면 (imageSideRatio> = viewSideRatio)를 (imageSideRatio <viewSideRatio)로 바꾸어야했습니다. 그렇지 않으면 좋은 대답
Marek Halmo

23

사용하십시오 android:scaleType="centerCrop".


질문이 정확히 무엇을 요구했는지가 아니라 내가 필요한 것을 정확하게 말하십시오!
nickjm

@Jameson을 정교하게 할 수 있습니까? 안드로이드 버전을 의미합니까?
Mick

centerCrop을 사용하면 이미지가 위아래로 약간 잘립니다.
Sreekanth Karumanaghat

9

나는 위와 비슷한 것을 한 다음 내부에서 작동하지 않기 때문에 몇 시간 동안 벽에 머리를 부딪쳤다 RelativeLayout. 나는 다음 코드로 끝났다.

package com.example;

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

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

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

        if (d != null) {
            int width;
            int height;
            if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY) {
                height = MeasureSpec.getSize(heightMeasureSpec);
                width = (int) Math.ceil(height * (float) d.getIntrinsicWidth() / d.getIntrinsicHeight());
            } else {
                width = MeasureSpec.getSize(widthMeasureSpec);
                height = (int) Math.ceil(width * (float) d.getIntrinsicHeight() / d.getIntrinsicWidth());
            }
            setMeasuredDimension(width, height);
        } else {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    }
}

그리고 RelativeLayout측정 된 치수를 무시 하지 않도록하기 위해 다음과 같이했습니다 .

    <FrameLayout
        android:id="@+id/image_frame"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_below="@+id/something">

        <com.example.ScaledImageView
            android:id="@+id/image"
            android:layout_width="wrap_content"
            android:layout_height="150dp"/>
    </FrameLayout>

5

가로 세로 비율을 유지하려면 ImageView에서 다음 속성을 사용하십시오.

android:adjustViewBounds="true"
android:scaleType="fitXY"

9
fitXY는 종횡비를 유지하지 않습니다. 레이아웃의 너비와 높이에 정확히 맞게 이미지를 늘립니다.
버려진 카트

5

ImageView에서 이미지를 배경으로 설정하면 src (android : src)에서 설정해야합니다.

감사.


5

너비가 화면 너비와 같고 화면비에 따라 높이가 비례하여 이미지를 만들려면 다음을 수행하십시오.

Glide.with(context).load(url).asBitmap().into(new SimpleTarget<Bitmap>() {
                    @Override
                    public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {

                        // creating the image that maintain aspect ratio with width of image is set to screenwidth.
                        int width = imageView.getMeasuredWidth();
                        int diw = resource.getWidth();
                        if (diw > 0) {
                            int height = 0;
                            height = width * resource.getHeight() / diw;
                            resource = Bitmap.createScaledBitmap(resource, width, height, false);
                        }
                                              imageView.setImageBitmap(resource);
                    }
                });

도움이 되었기를 바랍니다.


이것은 내가 찾은 최고의 답변입니다, 2 일간 검색했습니다, 감사합니다 fathima
Karthick Ramanathan

4

이것을 시도하십시오 : 그것은 나를 위해 문제를 해결했습니다.

   android:adjustViewBounds="true"
    android:scaleType="fitXY"

4

자바 코드가 필요하지 않습니다. 당신은 단지해야합니다 :

<ImageView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:adjustViewBounds="true"
    android:scaleType="centerCrop" />

키는 너비와 높이의 부모 일치에 있습니다.


centerCrop은 실제로 이미지의 일부를 잘라냅니다.
Sreekanth Karumanaghat

2

이 간단한 라인을 사용해보십시오 ... 의존성을 추가하지 않고 이미지보기 태그의 XML 코드 에이 라인을 추가하십시오 android : scaleType = "fitXY"


fitXY는 가로 세로 비율을 유지하지 않으므로 이미지가 늘어날 수 있습니다
ProjectDelta

2

android : ScaleType = "fitXY"im ImageView xml 사용


fitXY는 가로 세로 비율을 유지하지 않으므로 이미지가 늘어날 수 있습니다
ProjectDelta

1

이미지를 수동으로로드하여 수행중인 작업을 시도 할 수 있지만 Universal Image Loader를 살펴 보는 것이 좋습니다 .

나는 최근에 그것을 프로젝트에 통합했으며 환상적인 말을해야합니다. 비 동기화, 크기 조정, 이미지 캐싱에 대한 모든 걱정을 해결합니다. 통합 및 설정이 정말 쉽습니다. 5 분 안에 당신이 원하는 것을 해낼 수있을 것입니다.

예제 코드 :

//ImageLoader config
DisplayImageOptions displayimageOptions = new DisplayImageOptions.Builder().showStubImage(R.drawable.downloadplaceholder).cacheInMemory().cacheOnDisc().showImageOnFail(R.drawable.loading).build();

    ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext()).
            defaultDisplayImageOptions(displayimageOptions).memoryCache(new WeakMemoryCache()).discCache(new UnlimitedDiscCache(cacheDir)).build();

    if (ImageLoader.getInstance().isInited()) {
        ImageLoader.getInstance().destroy();
    }
    ImageLoader.getInstance().init(config);

    imageLoadingListener = new ImageLoadingListener() {
        @Override
        public void onLoadingStarted(String s, View view) {

        }

        @Override
        public void onLoadingFailed(String s, View view, FailReason failReason) {
            ImageView imageView = (ImageView) view;
            imageView.setImageResource(R.drawable.android);
            Log.i("Failed to Load " + s, failReason.toString());
        }

        @Override
        public void onLoadingComplete(String s, View view, Bitmap bitmap) {

        }

        @Override
        public void onLoadingCancelled(String s, View view) {

        }
    };

//Imageloader usage
ImageView imageView = new ImageView(getApplicationContext());
    if (orientation == 1) {
        imageView.setLayoutParams(new LinearLayout.LayoutParams(width / 6, width / 6));
    } else {
        imageView.setLayoutParams(new LinearLayout.LayoutParams(height / 6, height / 6));
    }
    imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
    imageLoader.displayImage(SERVER_HOSTNAME + "demos" + demo.getPathRoot() + demo.getRootName() + ".png", imageView, imageLoadingListener);

이렇게하면 이미지를 느리게로드하고 이미지가로드되는 동안 자리 표시 자 이미지를 표시하고로드에 실패하고 리소스를 캐싱 할 경우 기본 아이콘을 표시하는 imageView 크기에 맞게 맞출 수 있습니다.

-이 현재 설정은 이미지 종횡비를 유지하므로 원래 질문에 적용 할 수 있다고 덧붙여 야합니다.


0

UniversalImageLoader를 사용하고 설정하십시오.

DisplayImageOptions.Builder()
    .imageScaleType(ImageScaleType.EXACTLY_STRETCHED)
    .build();

ImageView에 스케일 설정이 없습니다.


0

비슷한 문제가 발생했습니다.이 이유는를 계산해야하기 때문 dp입니다. Android 스튜디오는 ImageView에서로드 할 때를 계산 drawable하지만 비트 맵 에서 로드하는 것과 같은 다른 방법을 사용 하는 dp경우에는 자동으로 계산되지 않습니다.

여기 내 XML이 있습니다

<ImageView
  android:id="@+id/imageViewer"
  android:layout_width="match_parent"
  android:layout_height="match_parent"//dp is not automaticly updated, when loading from a other source
  android:scaleType="fitCenter"
  tools:srcCompat="@drawable/a8" />

Kotlin을 사용하고 자산 파일에서 드로어 블을로드하고 있습니다.이를 계산하는 방법은 다음과 같습니다.

val d = Drawable.createFromStream(assets.open("imageData/${imageName}.png"), null)
bitHeight = d.minimumHeight//get the image height
imageViewer.layoutParams.height = (bitHeight * resources.displayMetrics.density).toInt()//set the height
imageViewer.setImageDrawable(d)//set the image from the drawable
imageViewer.requestLayout()//here I apply it to the layout

-1

사용하기 쉬운 피카소를 사용하십시오 ..

어댑터에서 ..

@Override
public void getView(int position, View convertView, ViewGroup parent) {

 ImageView view = (ImageView) convertView.findViewById(R.id.ranking_prod_pic);

 Picasso.with(context).load(url).into(view); //url is image url

 //you can resize image if you want

 /* Picasso.with(context) .load(url) .resize(50, 50) .centerCrop() .into(view) */

}

http://square.github.io/picasso/ 여기에 이미지 설명을 입력하십시오

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