안드로이드 : 드로어 블 또는 배경 이미지를 스케일 하시겠습니까?


134

레이아웃에서 배경 이미지를 가로 세로 비율로 유지하여 페이지를 만들 때 할당 된 공간으로 조정하려고합니다. 누구 든지이 작업을 수행하는 방법을 알고 있습니까?

클리핑 및 채우기 를 설정 하기 위해 및를 사용 layout.setBackgroundDrawable()하고 있지만 크기 조정에 대한 옵션이 표시되지 않습니다.BitmapDrawable()gravity


나는이 문제가 있었고 Anke가 제안한 변경 사항으로 Dweebo의 권고를 따랐다 : fitXY를 fitCenter로 변경했다. 잘 작동했습니다.

답변:


90

배경 이미지 스케일링을 사용자 정의하려면 다음과 같은 리소스를 생성하십시오.

<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
    android:gravity="center"
    android:src="@drawable/list_bkgnd" />

그런 다음 배경으로 사용되는 경우 뷰의 중앙에 위치합니다. 다른 플래그도 있습니다 : http://developer.android.com/guide/topics/resources/drawable-resource.html


6
비트 맵을 사용해 보았지만 Sam이 요청하는대로 이미지 크기가 조정되지 않고 단순히 중앙에 배치되었습니다. ImageView를 사용하면 muss / fuss없이 아름답게 작동합니다. (nb : 필자의 경우에도 스크롤하지 않습니다.) 이미지 크기를 조정하기 위해 비트 맵을 어떻게 보강합니까?
Joe D' Andrea

7
가능한 값은 "top"| "하단"| "왼쪽"| "오른쪽"| "center_vertical"| "fill_vertical"| "center_horizontal"| "fill_horizontal"| "센터"| "채우기"| "clip_vertical"| "clip_horizontal"
Aleks N.

30
이러한 매개 변수 중 어느 것도 가로 세로 비율을 유지하여 비트 맵의 ​​크기를 조정하지 않으므로 대답이 잘못되었습니다.
Malachiasz

7
Malachiasz에게, 'center'는 종횡비를 존중합니다. 그러나 이미지 크기가 축소되지 않습니다. 이는 다소 위험한 기능임을 의미합니다. 대상의 해상도에 따라 물체가 얼마나 정확하게 확장되는지 알 수 없습니다. Google의 또 다른 반 해결책.

2
scaleType 속성을 추가하는 방법이 있습니까?
ademar111190

57

정확히 원하는 것을 시도하지는 않았지만 사용하여 ImageView를 확장 할 수 있으며 ImageView에 제공하는 android:scaleType="fitXY"
크기에 맞게 크기가 조정됩니다.

따라서 레이아웃을 위해 FrameLayout을 만들고 ImageView를 넣은 다음 투명한 배경이있는 FrameLayout에 필요한 다른 모든 내용을 넣을 수 있습니다.

<FrameLayout  
android:layout_width="fill_parent" android:layout_height="fill_parent">

  <ImageView 
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:src="@drawable/back" android:scaleType="fitXY" />

  <LinearLayout>your views</LinearLayout>
</FrameLayout>

1
Surface에서이 작업을 수행 할 수 있습니까? 그렇지 않은 경우 FrameLayout을 사용하여 미리보기 (레코더 앱용)를 표시 할 수 있습니까?
Namratha

1
@ dweebo : 이것을 시도 했습니까? 그것은 나를 위해 작동하지 않는 것 같습니다.
speedplane

3
하나 대신 두 개의 UI 구성 요소를 사용하기 때문에 Downvoted는 특히 ListView와 같은 바쁜 구성 요소의 경우 나쁜 생각입니다. 스크롤하는 동안 문제가 발생할 가능성이 큽니다. 적절한 솔루션 : stackoverflow.com/a/9362168/145046
Aleks N.

fitCenter 및 centerCrop의 scaleType을 시도했지만 (다양한 밀도의 드로어 블 / 이미지 변형과 함께) 효과가있었습니다! 이미지에 기반한 개인적인 취향에 따라 스케일 유형이 나에게 적합하다고 생각합니다. FrameLayout 대신 merge를 사용했으며 특정 경우에는 스크롤이 없습니다.
Joe D' Andrea

2
fitXY는 이미지의 종횡비를 유지하지 않기 때문에 centerInside는 fitXY가 아닙니다.
Malachiasz

35

드로어 블에서이를 수행하는 쉬운 방법이 있습니다.

your_drawable.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >

    <item android:drawable="@color/bg_color"/>
    <item>
        <bitmap
            android:gravity="center|bottom|clip_vertical"
            android:src="@drawable/your_image" />
    </item>

</layer-list>

유일한 단점은 공간이 충분하지 않으면 이미지가 완전히 표시되지 않지만 잘려서 드로어 블에서 직접이 작업을 수행 할 수있는 방법을 찾을 수 없다는 것입니다. 그러나 테스트에서 나는 그것이 잘 작동하며 이미지의 많은 부분을 자르지 않습니다. 중력 옵션으로 더 많은 것을 즐길 수 있습니다.

또 다른 방법은 당신이를 사용하는 것 레이아웃을 생성하는 것 ImageView하고 설정 scaleType하는 방법에 대해 fitCenter.


2
이 솔루션은 분명히 테마의 배경 속성을 대체하고 뷰에 탭이 있는지 여부에 따라 이미지 크기를 다르게 피하기 위해 오랫동안 찾고있는 것입니다. 이것을 공유해 주셔서 감사합니다.
Bibu

1
오류 :error: <item> must have a 'name' attribute.
Dmitry

thx @lonutNegru, 내 하루를 저장 +1 :)
라비 바니 야

18

사용 당신이 가지고있는 가로 세로 비율을 유지하기 위해 android:scaleType=fitCenter또는 fitStart사용 등 fitXY이미지의 원래 화면 비율을 유지하지 않습니다!

이것은 src배경 이미지가 아닌 속성 이있는 이미지에만 적용됩니다 .


18

레이아웃 크기의 배경으로 이미지를 사용하십시오.

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >

    <ImageView
        android:id="@+id/imgPlaylistItemBg"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:adjustViewBounds="true"
        android:maxHeight="0dp"
        android:scaleType="fitXY"
        android:src="@drawable/img_dsh" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical" >


    </LinearLayout>

</FrameLayout>

감사! 또한 android:scaleType="centerCrop"작동합니다.
CoolMind

5

setBackgroundDrawable방법 을 사용하여 ImageView의 Drawable을 설정하면 이미지의 크기가 항상 조정됩니다. 동일 adjustViewBounds하거나 다른 매개 변수는 ScaleTypes무시됩니다. 내가 찾은 종횡비를 유지하는 유일한 해결책은 ImageView드로어 블을로드 한 후 크기를 조정하는 것입니다. 내가 사용한 코드 스 니펫은 다음과 같습니다.

// bmp is your Bitmap object
int imgHeight = bmp.getHeight();
int imgWidth = bmp.getWidth();
int containerHeight = imageView.getHeight();
int containerWidth = imageView.getWidth();
boolean ch2cw = containerHeight > containerWidth;
float h2w = (float) imgHeight / (float) imgWidth;
float newContainerHeight, newContainerWidth;

if (h2w > 1) {
    // height is greater than width
    if (ch2cw) {
        newContainerWidth = (float) containerWidth;
        newContainerHeight = newContainerWidth * h2w;
    } else {
        newContainerHeight = (float) containerHeight;
        newContainerWidth = newContainerHeight / h2w;
    }
} else {
    // width is greater than height
    if (ch2cw) {
        newContainerWidth = (float) containerWidth;
        newContainerHeight = newContainerWidth / h2w; 
    } else {
        newContainerWidth = (float) containerHeight;
        newContainerHeight = newContainerWidth * h2w;       
    }
}
Bitmap copy = Bitmap.createScaledBitmap(bmp, (int) newContainerWidth, (int) newContainerHeight, false);
imageView.setBackgroundDrawable(new BitmapDrawable(copy));
LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
imageView.setLayoutParams(params);
imageView.setMaxHeight((int) newContainerHeight);
imageView.setMaxWidth((int) newContainerWidth);

위의 코드 스 니펫에서 bmp 는 표시 될 Bitmap 객체이고 imageViewImageView객체입니다

중요한 것은 레이아웃 매개 변수의 변경입니다 . 때문에 필요 setMaxHeight하고 setMaxWidth폭과 높이가 부모를 채우기 위해하지, 내용을 포장하기 위해 정의 된 경우에만 차이를 만들 것입니다. 그렇지 않으면 때문에 반면에 채우기 부모는 처음에 원하는 설정으로 containerWidth하고 containerHeight두 값이 모두 당신이 당신의 이미지 뷰에 대해이 같은 뭔가를해야합니다 귀하의 레이아웃 파일, 0 그래서 동일해야합니다 :

...
<ImageView android:id="@+id/my_image_view"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"/>
...

4

이것은 가장 성능이 좋은 솔루션은 아니지만 배경 대신 누군가가 제안한 것처럼 FrameLayout 또는 RelativeLayout을 만들고 의사 배경으로 ImageView를 사용할 수 있습니다. 다른 요소는 바로 위에 위치합니다.

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

    <ImageView
        android:id="@+id/ivBackground"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:scaleType="fitStart"
        android:src="@drawable/menu_icon_exit" />

    <Button
        android:id="@+id/bSomeButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="61dp"
        android:layout_marginTop="122dp"
        android:text="Button" />

</RelativeLayout>

ImageView의 문제점은 사용 가능한 scaleTypes 만 CENTER, CENTER_CROP, CENTER_INSIDE, FIT_CENTER, FIT_END, FIT_START, FIT_XY, MATRIX ( http://etcodehome.blogspot.de/2011/05/android-imageview-scaletype-samples.html)입니다. )

경우에 따라 이미지를 전체 화면에 채우고 (예 : 배경 이미지) 화면의 가로 세로 비율이 이미지와 다른 경우 필요한 배율 유형이 종류 인 경우 TOP_CROP 중

CENTER_CROP는 이미지 가장자리의 상단 가장자리를 이미지보기의 상단 가장자리에 맞추지 않고 축척 된 이미지를 중앙에 맞추고 FIT_START는 화면 높이에 맞으며 너비를 채우지 않습니다. 그리고 사용자 Anke가 FIT_XY가 종횡비를 유지하지 않는다는 것을 알았습니다.

기꺼이 누군가 TOP_CROP를 지원하도록 ImageView를 확장했습니다.

public class ImageViewScaleTypeTopCrop extends ImageView {
    public ImageViewScaleTypeTopCrop(Context context) {
        super(context);
        setup();
    }

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

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

    private void setup() {
        setScaleType(ScaleType.MATRIX);
    }

    @Override
    protected boolean setFrame(int frameLeft, int frameTop, int frameRight, int frameBottom) {

        float frameWidth = frameRight - frameLeft;
        float frameHeight = frameBottom - frameTop;

        if (getDrawable() != null) {

            Matrix matrix = getImageMatrix();
            float scaleFactor, scaleFactorWidth, scaleFactorHeight;

            scaleFactorWidth = (float) frameWidth / (float) getDrawable().getIntrinsicWidth();
            scaleFactorHeight = (float) frameHeight / (float) getDrawable().getIntrinsicHeight();

            if (scaleFactorHeight > scaleFactorWidth) {
                scaleFactor = scaleFactorHeight;
            } else {
                scaleFactor = scaleFactorWidth;
            }

            matrix.setScale(scaleFactor, scaleFactor, 0, 0);
            setImageMatrix(matrix);
        }

        return super.setFrame(frameLeft, frameTop, frameRight, frameBottom);
    }

}

https://stackoverflow.com/a/14815588/2075875

누군가가 그런 이미지를 스케일링하는 커스텀 Drawable을 작성한다면 IMHO는 완벽 할 것입니다. 그런 다음 배경 매개 변수로 사용할 수 있습니다.


Reflog는 드로어 블을 사용하기 전에 프리 스케일 드로 어링을 제안합니다. 다음 명령은 어떻게 할 것입니다 : 자바 (안드로이드) : 어떻게 비트 맵없이 드로어 블을 확장하는 방법? 단점은 있지만 업 스케일 드로어 블 / 비트 맵은 더 많은 RAM을 사용하는 반면 ImageView에서 사용하는 스케일링에는 더 많은 메모리가 필요하지 않습니다. 이점은 프로세서로드가 적을 수 있습니다.


좋은 것! 폭을 비례 적으로 늘리고 이미지 하단을 잘라내어 전체 화면을 채우는 배경 이미지입니다.
CMash

4

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

int bwidth=bitMap1.getWidth();
int bheight=bitMap1.getHeight();
int swidth=imageView_location.getWidth();
int sheight=imageView_location.getHeight();
new_width=swidth;
new_height = (int) Math.floor((double) bheight *( (double) new_width / (double) bwidth));
Bitmap newbitMap = Bitmap.createScaledBitmap(bitMap1,new_width,new_height, true);
imageView_location.setImageBitmap(newbitMap)

2

Dweebo가 제안한 것은 효과가 있습니다. 그러나 나의 겸손한 의견으로는 불필요합니다. 배경 드로어 블 자체가 잘 확장됩니다. 다음 예제와 같이 뷰의 너비와 높이는 고정되어 있어야합니다.

 < RelativeLayout 
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@android:color/black">

    <LinearLayout
        android:layout_width="500dip"
        android:layout_height="450dip"
        android:layout_centerInParent="true"
        android:background="@drawable/my_drawable"
        android:orientation="vertical"
        android:padding="30dip"
        >
        ...
     </LinearLayout>
 < / RelativeLayout>

2
내 이해는 배경이 뷰를 채우기 위해 확장되지만 축소되지는 않는다는 것입니다.
Edward Falk

1

시도하는 한 가지 옵션은 이미지를 drawable-nodpi폴더에 넣고 레이아웃의 배경을 드로어 블 리소스 ID로 설정하는 것입니다.

이것은 확실히 스케일 다운과 함께 작동하지만 스케일 업으로 테스트하지 않았습니다.


0

코 틀린 :

뷰에서 비트 맵을 그려야하는 경우 FIT로 조정됩니다.

bm 높이를 컨테이너와 동일하게 설정하고 너비를 조정할 수있는 적절한 계산을 수행 할 수 있습니다 (bm 너비 대 높이 비율이 컨테이너 너비 대 높이 비율보다 작거나 반대 시나리오의 경우).

이미지 :

예시 이미지 1

예시 이미지 2

// binding.fragPhotoEditDrawCont is the RelativeLayout where is your view
// bm is the Bitmap
val ch = binding.fragPhotoEditDrawCont.height
val cw = binding.fragPhotoEditDrawCont.width
val bh = bm.height
val bw = bm.width
val rc = cw.toFloat() / ch.toFloat()
val rb = bw.toFloat() / bh.toFloat()

if (rb < rc) {
    // Bitmap Width to Height ratio is less than Container ratio
    // Means, bitmap should pin top and bottom, and have some space on sides.
    //              _____          ___
    // container = |_____|   bm = |___| 
    val bmHeight = ch - 4 //4 for container border
    val bmWidth = rb * bmHeight //new width is bm_ratio * bm_height
    binding.fragPhotoEditDraw.layoutParams = RelativeLayout.LayoutParams(bmWidth.toInt(), bmHeight)
}
else {
    val bmWidth = cw - 4 //4 for container border
    val bmHeight = 1f/rb * cw
    binding.fragPhotoEditDraw.layoutParams = RelativeLayout.LayoutParams(bmWidth, bmHeight.toInt())
}

-4

드로어 블을 배경으로 사용하기 전에 해당 드로어 블을 사전 축척해야합니다


이것이 실제로 유일한 옵션입니까? 디스플레이 크기를 지정할 수있는 ImageView를 배치 할 컨테이너 유형이 없습니까?
GrkEngineer

또한 SurfaceView
AZ_

3
iOS에서 가로 세로 맞춤, 가로 세로 채우기, 왼쪽 상단, 상단 등은 없습니까? 그 짜증 ..
Maciej Swic

@Aleksej가 말했듯이 정답은 아닙니다.
학습자

-5

다음 중 하나를 사용할 수 있습니다.

android : gravity = "fill_horizontal | clip_vertical"

또는

android : gravity = "fill_vertical | clip_horizontal"

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