이미지를 ImageView에 맞추고 종횡비를 유지 한 다음 ImageView의 크기를 이미지 크기로 조정 하시겠습니까?


164

임의의 크기의 이미지를에 맞추는 방법은 ImageView무엇입니까?
언제:

  • 초기 ImageView크기는 250dp * 250dp입니다
  • 이미지의 더 큰 치수는 250dp로 확대 / 축소되어야합니다
  • 이미지의 가로 세로 비율을 유지해야합니다
  • ImageView차원은 스케일링 후 스케일 이미지의 크기와 일치해야

예를 들어 100 * 150 이미지의 경우 이미지와 ImageView166 * 250이어야합니다.
예를 들어 150 * 100 이미지의 경우 이미지와 ImageView250 * 166이어야합니다.

경계를 다음과 같이 설정하면

<ImageView
    android:id="@+id/picture"
    android:layout_width="250dp"
    android:layout_height="250dp"
    android:layout_gravity="center_horizontal"
    android:layout_marginTop="20dp"
    android:adjustViewBounds="true" />

이미지가 제대로 맞지 ImageView하지만은 ImageView항상 250dp * 250dp입니다.


어, 크기를 ImageView이미지 크기로 변경 하시겠습니까? 예를 들어 100dp x 150dp의 이미지가 ImageView동일한 측정 값으로 확장 됩니까? 또는 이미지를 ImageView경계 에 맞게 스케일링하는 방법을 의미합니까? 예를 들어 1000dp x 875dp의 이미지는 250dp x 250dp로 크기가 조정됩니다. 종횡비를 유지해야합니까?
Jarno Argillander

ImageView에 이미지의 크기가 있고 이미지의 최대 크기가 250dp와 같고 가로 세로 비율을 유지하기를 원합니다. 예를 들어 100 * 150의 이미지의 경우 이미지와 ImageView가 166 * 250이되기를 원합니다. 질문을 업데이트하겠습니다.
jul

활동을 표시 할 때 (한 번만) 또는 갤러리 / 웹에서 사진을 선택하는 것과 같은 활동 (로드 할 때가 아닌) 또는 둘 다에서 활동을 수행 할 때만 스케일링 / 조정을 하시겠습니까?
Jarno Argillander

원하는대로 정확하게 해야하는 수정 된 답변을보십시오 :)
Jarno Argillander

답변:


137

(원래 질문에 대한 설명을 한 후 답변이 크게 수정되었습니다)

해명 후 :
이것은 단지 XML로 수행 할 수 없습니다 . ImageView이미지의 한 치수가 항상 250dp이고 ImageView이미지와 치수가 동일 하도록 이미지와 크기를 모두 조정할 수는 없습니다 .

이 코드는 크기 DrawableImageView250dp x 250dp와 같은 정사각형에 정확히 250dp로 유지되고 종횡비를 유지하도록 확장됩니다. 그런 다음 ImageView크기가 조정 된 이미지의 크기와 일치하도록 크기가 조정됩니다. 코드는 활동에 사용됩니다. 버튼 클릭 핸들러를 통해 테스트했습니다.

즐겨. :)

private void scaleImage(ImageView view) throws NoSuchElementException  {
    // Get bitmap from the the ImageView.
    Bitmap bitmap = null;

    try {
        Drawable drawing = view.getDrawable();
        bitmap = ((BitmapDrawable) drawing).getBitmap();
    } catch (NullPointerException e) {
        throw new NoSuchElementException("No drawable on given view");
    } catch (ClassCastException e) {
        // Check bitmap is Ion drawable
        bitmap = Ion.with(view).getBitmap();
    }

    // Get current dimensions AND the desired bounding box
    int width = 0;

    try {
        width = bitmap.getWidth();
    } catch (NullPointerException e) {
        throw new NoSuchElementException("Can't find bitmap on given view/drawable");
    }

    int height = bitmap.getHeight();
    int bounding = dpToPx(250);
    Log.i("Test", "original width = " + Integer.toString(width));
    Log.i("Test", "original height = " + Integer.toString(height));
    Log.i("Test", "bounding = " + Integer.toString(bounding));

    // Determine how much to scale: the dimension requiring less scaling is
    // closer to the its side. This way the image always stays inside your
    // bounding box AND either x/y axis touches it.  
    float xScale = ((float) bounding) / width;
    float yScale = ((float) bounding) / height;
    float scale = (xScale <= yScale) ? xScale : yScale;
    Log.i("Test", "xScale = " + Float.toString(xScale));
    Log.i("Test", "yScale = " + Float.toString(yScale));
    Log.i("Test", "scale = " + Float.toString(scale));

    // Create a matrix for the scaling and add the scaling data
    Matrix matrix = new Matrix();
    matrix.postScale(scale, scale);

    // Create a new bitmap and convert it to a format understood by the ImageView 
    Bitmap scaledBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
    width = scaledBitmap.getWidth(); // re-use
    height = scaledBitmap.getHeight(); // re-use
    BitmapDrawable result = new BitmapDrawable(scaledBitmap);
    Log.i("Test", "scaled width = " + Integer.toString(width));
    Log.i("Test", "scaled height = " + Integer.toString(height));

    // Apply the scaled bitmap
    view.setImageDrawable(result);

    // Now change ImageView's dimensions to match the scaled image
    LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) view.getLayoutParams(); 
    params.width = width;
    params.height = height;
    view.setLayoutParams(params);

    Log.i("Test", "done");
}

private int dpToPx(int dp) {
    float density = getApplicationContext().getResources().getDisplayMetrics().density;
    return Math.round((float)dp * density);
}

의 XML 코드 ImageView:

<ImageView a:id="@+id/image_box"
    a:background="#ff0000"
    a:src="@drawable/star"
    a:layout_width="wrap_content"
    a:layout_height="wrap_content"
    a:layout_marginTop="20dp"
    a:layout_gravity="center_horizontal"/>


스케일링 코드에 대한 다음 토론 덕분에
http://www.anddev.org/resize_and_rotate_image_-_example-t621.html


2012 년 11 월 7 일 업데이트 :
의견에서 제안한대로 널 포인터 검사가 추가되었습니다.


1
ImageView는 항상 250 * 250입니다.
jul

2
확인. xml에서만 수행 할 수 없습니다. 자바 코드가 필요합니다. xml을 사용하면 이미지 또는 크기를 모두 조정할 수 있습니다 ImageView.
Jarno Argillander

93
몰랐어요 당신은 안드로이드 대체 할 수있다 : A를 :
StackOverflowed

2
이온은 비동기 네트워킹 및 이미지 로딩을위한 프레임 워크입니다 : github.com/koush/ion
Thomas

1
Java는 간단한 작업을 위해 너무 많은 코드를 작성해야하기 때문에 매우 못생긴 언어입니다.
Dmitry

245

이 특정 질문에 대한 답은 아니지만 누군가가 나와 같은 경우 maxWidth가로 세로 비율을 유지하면서 ImageView에서 이미지를 경계 크기 (예 :)로 맞추고 ImageView가 차지하는 과도한 공간을 제거 하는 방법에 대한 답변을 검색하는 경우 가장 간단한 해결책은 XML에서 다음 속성을 사용하는 것입니다.

    android:scaleType="centerInside"
    android:adjustViewBounds="true"

13
이미지가 너무 작 으면 이미지를 확대하지 않으려는 경우 작동합니다.
Janusz

너무 작 으면 어떻게 확대하고 종횡비를 유지합니까?
Kaustubh Bhagwat

누군가 필요로하는 경우, "fitCenter는"scaleType에 대한 다른 속성이며, 이미지를 확장하지 않지만 어떤 큰 이미지, 그것은 가로 세로 비율 유지 뷰 상자 안에 이미지의 최대 크기에 맞는
인 Yogesh prajapati을

작은 이미지를 확대하려면 scaleType = "centerCrop"을 대신 사용하십시오.
Eaweb

이 솔루션으로 작업 할 수있는 또 하나의 방법은 "android : background"가 아닌 "android : src"를 사용하여 이미지를 참조하는 것입니다.
Codingpan

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

23

아래 코드는 비트 맵을 동일한 크기의 이미지 뷰로 완벽하게 만듭니다. 비트 맵 이미지 높이와 너비를 얻은 다음 imageview의 매개 변수를 사용하여 새 높이와 너비를 계산하십시오. 화면비가 가장 좋은 이미지를 얻을 수 있습니다.

int currentBitmapWidth = bitMap.getWidth();
int currentBitmapHeight = bitMap.getHeight();

int ivWidth = imageView.getWidth();
int ivHeight = imageView.getHeight();
int newWidth = ivWidth;

newHeight = (int) Math.floor((double) currentBitmapHeight *( (double) new_width / (double) currentBitmapWidth));

Bitmap newbitMap = Bitmap.createScaledBitmap(bitMap, newWidth, newHeight, true);

imageView.setImageBitmap(newbitMap)

즐겨.


3
이렇게하면 너비를 줄인 것과 같은 요소로 원래 높이를 줄일 수 있습니다. 이것은 newHeight <ivHeight를 보증하지 않습니다. 이상적으로는 어떤 비율이 더 큰지 (currentBitmapHeight / ivHeight, currentBitmapWidth / ivWidth) 확인한 다음이를 바탕으로 추가 결정을 내려야합니다.
Sumit Trehan

1
이것은 실제로 완벽하게 작동하지만 ivHeight 또는 newWidth가 필요하지 않지만 대신 ivWidth를 계산에 넣으십시오.
스튜어트

14

추가하려고 android:scaleType="fitXY"당신에 ImageView.


5
원본 이미지가 사각형이 아닌 경우 가로 세로 비율이 수정됩니다.
jul

1
fitXY거의 항상 이미지의 종횡비를 변경합니다. OP는 종횡비가 반드시 유지되어야한다고 분명히 언급합니다.
IcyFlame

7

하루를 검색 한 후 이것이 가장 쉬운 해결책이라고 생각합니다.

imageView.getLayoutParams().width = 250;
imageView.getLayoutParams().height = 250;
imageView.setAdjustViewBounds(true);

2
정답에 감사드립니다.하지만 adjustViewBoundsXML 에 추가하는 것이 좋습니다

7

대부분의 경우 가장 적합한 솔루션은

예를 들면 다음과 같습니다.

<ImageView android:id="@+id/avatar"
           android:layout_width="match_parent"
           android:layout_height="match_parent"
           android:scaleType="fitXY"/>

1
더 이상 사용되지 않는 API (fill_parent)에 의존하지 마십시오
fdermishin

이것이 OP의 질문에 어떻게 대답합니까? 이것은 aspet 비율을 유지하지 않습니다
Alex

6

이것은 모두 XML을 사용하여 수행 할 수 있습니다 ... 다른 방법은 꽤 복잡해 보입니다. 어쨌든 dp에서 원하는 높이를 설정 한 다음 내용을 감싸거나 너비를 줄이려면 너비를 설정하십시오. scaleType fitCenter를 사용하여 이미지 크기를 조정하십시오.

<ImageView
    android:layout_height="200dp"
    android:layout_width="wrap_content"
    android:scaleType="fitCenter"
    android:adjustViewBounds="true"
    android:src="@mipmap/ic_launcher"
    android:layout_below="@+id/title"
    android:layout_margin="5dip"
    android:id="@+id/imageView1">

4

이 코드를 사용하십시오 :

<ImageView android:id="@+id/avatar"
           android:layout_width="fill_parent"
           android:layout_height="match_parent"
           android:scaleType="fitXY" />

4

편집 된 Jarno Argillanders 답변 :

너비와 높이에 이미지를 맞추는 방법 :

1) ImageView를 초기화하고 이미지를 설정하십시오.

iv = (ImageView) findViewById(R.id.iv_image);
iv.setImageBitmap(image);

2) 이제 크기를 조정하십시오.

scaleImage(iv);

편집 된 scaleImage방법 : ( EXPECTED 경계 값을 대체 할 수 있음 )

private void scaleImage(ImageView view) {
    Drawable drawing = view.getDrawable();
    if (drawing == null) {
        return;
    }
    Bitmap bitmap = ((BitmapDrawable) drawing).getBitmap();

    int width = bitmap.getWidth();
    int height = bitmap.getHeight();
    int xBounding = ((View) view.getParent()).getWidth();//EXPECTED WIDTH
    int yBounding = ((View) view.getParent()).getHeight();//EXPECTED HEIGHT

    float xScale = ((float) xBounding) / width;
    float yScale = ((float) yBounding) / height;

    Matrix matrix = new Matrix();
    matrix.postScale(xScale, yScale);

    Bitmap scaledBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
    width = scaledBitmap.getWidth();
    height = scaledBitmap.getHeight();
    BitmapDrawable result = new BitmapDrawable(context.getResources(), scaledBitmap);

    view.setImageDrawable(result);

    LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) view.getLayoutParams(); 
    params.width = width;
    params.height = height;
    view.setLayoutParams(params);
}

그리고 .xml :

<ImageView
    android:id="@+id/iv_image"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal" />

이 캐스트는 다음과 같습니다. LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) view.getLayoutParams (); MarginLayoutParams는 ViewGroup.LayoutParams에서 상속하므로 다른 방법으로 가야합니다.
Jay Jacobs

3

이것은 나의 경우를 위해 그것을했다.

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

2

그것이 작동하지 않으면 android : background를 android : src로 바꾸십시오.

android : src는 주요 트릭을 재생합니다

    <ImageView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:adjustViewBounds="true"
    android:scaleType="fitCenter"
    android:src="@drawable/bg_hc" />

그것은 매력처럼 잘 작동합니다

여기에 이미지 설명을 입력하십시오


1

ImageView와 Bitmap이 필요했기 때문에 Bitmap은 ImageView 크기로 조정되고 ImageView의 크기는 조정 된 Bitmap과 동일합니다 :).

나는이 게시물을 통해 그것을 수행하는 방법을 찾고 있었고 마침내 여기에 설명 된 방식이 아니라 내가 원하는 것을했습니다.

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/acpt_frag_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/imageBackground"
android:orientation="vertical">

<ImageView
    android:id="@+id/acpt_image"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:adjustViewBounds="true"
    android:layout_margin="@dimen/document_editor_image_margin"
    android:background="@color/imageBackground"
    android:elevation="@dimen/document_image_elevation" />

그런 다음 onCreateView 메소드에서

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

    View view = inflater.inflate(R.layout.fragment_scanner_acpt, null);

    progress = view.findViewById(R.id.progress);

    imageView = view.findViewById(R.id.acpt_image);
    imageView.setImageBitmap( bitmap );

    imageView.getViewTreeObserver().addOnGlobalLayoutListener(()->
        layoutImageView()
    );

    return view;
}

그런 다음 layoutImageView () 코드

private void layoutImageView(){

    float[] matrixv = new float[ 9 ];

    imageView.getImageMatrix().getValues(matrixv);

    int w = (int) ( matrixv[Matrix.MSCALE_X] * bitmap.getWidth() );
    int h = (int) ( matrixv[Matrix.MSCALE_Y] * bitmap.getHeight() );

    imageView.setMaxHeight(h);
    imageView.setMaxWidth(w);

}

결과적으로 이미지는 종횡비를 유지하면서 완벽하게 들어가고 비트 맵이있을 때 ImageView에서 남은 픽셀이 없습니다.

결과

ImageView가 wrap_content 및 adjustViewBounds를 true로 설정하는 것이 중요합니다. 그러면 setMaxWidth 및 setMaxHeight가 작동합니다. 이는 ImageView의 소스 코드로 작성됩니다.

/*An optional argument to supply a maximum height for this view. Only valid if
 * {@link #setAdjustViewBounds(boolean)} has been set to true. To set an image to be a
 * maximum of 100 x 100 while preserving the original aspect ratio, do the following: 1) set
 * adjustViewBounds to true 2) set maxWidth and maxHeight to 100 3) set the height and width
 * layout params to WRAP_CONTENT. */

0

Picasso를 사용하여 제약 조건 레이아웃 에서이 작업을 수행해야 했으므로 위의 답변 중 일부를 정리 하고이 솔루션을 생각해 냈습니다 (로드하는 이미지의 종횡비를 이미 알고 있으므로 도움이됩니다).

setContentView (...) 다음에 어딘가에 내 활동 코드에서 호출되었습니다.

protected void setBoxshotBackgroundImage() {
    ImageView backgroundImageView = (ImageView) findViewById(R.id.background_image_view);

    if(backgroundImageView != null) {
        DisplayMetrics displayMetrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
        int width = displayMetrics.widthPixels;
        int height = (int) Math.round(width * ImageLoader.BOXART_HEIGHT_ASPECT_RATIO);

        // we adjust the height of this element, as the width is already pinned to the parent in xml
        backgroundImageView.getLayoutParams().height = height;

        // implement your Picasso loading code here
    } else {
        // fallback if no element in layout...
    }
}

내 XML에서

<?xml version="1.0" encoding="utf-8"?>

<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout_editor_absoluteY="0dp"
tools:layout_editor_absoluteX="0dp">

    <ImageView
        android:id="@+id/background_image_view"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:scaleType="fitStart"
        app:srcCompat="@color/background"
        android:adjustViewBounds="true"
        tools:layout_editor_absoluteY="0dp"
        android:layout_marginTop="0dp"
        android:layout_marginBottom="0dp"
        android:layout_marginRight="0dp"
        android:layout_marginLeft="0dp"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

    <!-- other elements of this layout here... -->

</android.support.constraint.ConstraintLayout>

constraintBottom_toBottomOf 속성이 부족합니다. ImageLoader 는 이미지 로딩 util 메소드와 상수를위한 제 자신의 정적 클래스입니다.


0

매우 간단한 솔루션을 사용하고 있습니다. 여기 내 코드 :

imageView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT));
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
imageView.getLayoutParams().height = imageView.getLayoutParams().width;
imageView.setMinimumHeight(imageView.getLayoutParams().width);

내 사진은 격자보기에서 동적으로 추가됩니다. 이러한 설정을 이미지보기로 설정하면 사진이 자동으로 1 : 1 비율로 표시 될 수 있습니다.


0

간단한 수학을 사용하여 이미지 크기를 조정하십시오. 에 ImageView설정된 것보다 드로어 블 이미지의 크기를 조정 하거나 크기를 조정할 수 있습니다 ImageView. 설정하려는 비트 맵의 ​​너비와 높이를 찾고 ImageView원하는 메소드를 호출하십시오. 너비 500이 호출 메소드보다 높이보다 크다고 가정하십시오.

//250 is the width you want after resize bitmap
Bitmat bmp = BitmapScaler.scaleToFitWidth(bitmap, 250) ;
ImageView image = (ImageView) findViewById(R.id.picture);
image.setImageBitmap(bmp);

비트 맵 크기 조정에이 클래스를 사용합니다.

public class BitmapScaler{
// Scale and maintain aspect ratio given a desired width
// BitmapScaler.scaleToFitWidth(bitmap, 100);
 public static Bitmap scaleToFitWidth(Bitmap b, int width)
  {
    float factor = width / (float) b.getWidth();
    return Bitmap.createScaledBitmap(b, width, (int) (b.getHeight() * factor), true);
  }


  // Scale and maintain aspect ratio given a desired height
  // BitmapScaler.scaleToFitHeight(bitmap, 100);
  public static Bitmap scaleToFitHeight(Bitmap b, int height)
  {
    float factor = height / (float) b.getHeight();
    return Bitmap.createScaledBitmap(b, (int) (b.getWidth() * factor), height, true);
   }
 }

xml 코드는

<ImageView
android:id="@+id/picture"
android:layout_width="250dp"
android:layout_height="250dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="20dp"
android:adjustViewBounds="true"
android:scaleType="fitcenter" />

0

빠른 답변 :

<ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:scaleType="center"
        android:src="@drawable/yourImage"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.