버튼의 드로어 블을 축소하려면 어떻게해야합니까?


87

버튼의 드로어 블을 어떻게 작게 만들 수 있습니까? 아이콘이 너무 커서 실제로 버튼보다 높습니다. 이것은 내가 사용하는 코드입니다.

    <Button
    android:background="@drawable/red_button"
    android:drawableLeft="@drawable/s_vit"
    android:id="@+id/ButtonTest"
    android:gravity="left|center_vertical" 
    android:text="S-SERIES CALCULATOR"
    android:textColor="@android:color/white"
    android:layout_height="wrap_content"
    android:layout_width="wrap_content"
    android:layout_marginLeft="25dp"
    android:layout_marginRight="25dp"
    android:drawablePadding="10dp">
    </Button>

윗부분은 어떻게 보일지, 아랫 부분은 지금 보이는 모습입니다.

윗부분은 어떻게 보일지, 아랫 부분은 지금 보이는 모습입니다.

나는 이것을 시도했지만 이미지가 표시되지 않습니다. :-(

    Resources res = getResources();
    ScaleDrawable sd = new ScaleDrawable(res.getDrawable(R.drawable.s_vit), 0, 10f, 10f);
    Button btn = (Button) findViewById(R.id.ButtonTest);
    btn.setCompoundDrawables(sd.getDrawable(), null, null, null);

당신이 무엇을 얻고 있고 무엇을하려고하는지에 대한 이미지를 업로드하면 더 좋을 것입니다. 감사.
Lalit Poptani 2011 년

드로어 블의 크기를 정의하기 위해 사용자 정의 버튼을 정의 할 수 있습니다. 여기 내 대답을 참조하십시오. stackoverflow.com/a/31916731/2308720
Oleksandr

나는 이것이 2011 년부터 알고 ...하지만 실제로 카메라 버튼의 경계를 벗어나고 자와 버튼의 모양을 선호 - 나는 ... 그것을 그것이 길을 떠난 것이 바로 선생님 ':
killercowuk

답변:


70

당신은 사용해야 하여 ImageButton을 하고있는 이미지를 지정 android:src하고 설정 android:scaletype하는 방법에 대해fitXY


코드에서 크기 조정 된 드로어 블 설정

Drawable drawable = getResources().getDrawable(R.drawable.s_vit);
drawable.setBounds(0, 0, (int)(drawable.getIntrinsicWidth()*0.5), 
                         (int)(drawable.getIntrinsicHeight()*0.5));
ScaleDrawable sd = new ScaleDrawable(drawable, 0, scaleWidth, scaleHeight);
Button btn = findViewbyId(R.id.yourbtnID);
btn.setCompoundDrawables(sd.getDrawable(), null, null, null); //set drawableLeft for example

코드에서 드로어 블을 설정하면 버튼 높이를 기준으로 크기를 조정 한 다음 설정할 수 있습니다.
Ronnie

이제 이미지가 표시되지만 크기가 조정되지 않습니다! 0.1f에서 10f 사이의 값을 시도했습니다. 어떤 생각? 도와 주셔서 감사합니다 ...
Reto

시도해보세요drawable.setBounds(0, 0, drawable.getIntrinsicWidth()*0.5, drawable.getIntrinsicHeight()*0.5);
Ronnie

이렇게하면 드로어 블 크기가 조정되면 scaledrawable 부분을 제거하고 드로어 블을 직접 사용할 수 있습니다.
Ronnie

2
scaleWidth 및 scaleHeight에 대한 자체 값을 설정해야합니까? 설명 적입니까?
SametSahin

90

필요하지 않은 매우 간단하고 효과적인 XML 솔루션을 찾았습니다. ImageButton

아래와 같이 이미지의 드로어 블 파일을 만들고 사용하십시오. android:drawableLeft

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

    <item
    android:id="@+id/half_overlay"
    android:drawable="@drawable/myDrawable"
    android:width="40dp"
    android:height="40dp"
    />

</layer-list>

android:widthandroid:height속성을 사용하여 이미지 크기를 설정할 수 있습니다 .

이렇게하면 적어도 다른 화면에 대해 동일한 크기를 얻을 수 있습니다.

단점은 이미지 너비를 X에 맞게 조정하고 그에 따라 이미지 높이를 조정하는 fitXY와 정확히 같지 않다는 것입니다.


9
이것은 받아 들여진 대답이어야합니다. ImageButton을 원하지 않는 경우 (예 : 텍스트 등을 원하기 때문에)이 답변은 Text와 0 코드가있는 Button 내에서 크기가 지정된 이미지를 허용합니다.
Recycled Steel

3
나는 이와 같은 새로운 드로어 블을 만든 다음 android:drawableTop새로운 드로어 블을 추가했습니다. 내가 설정 한 너비 / 높이 값에 관계없이 기본 값이 표시됩니다.
driftking9987

9
Lollipop 이하의 Android 버전에서는 작동하지 않는 것 같습니다.
Jyotman Singh 2016-07-29

32
높이, 너비는 API 레벨 23 이상에서만 작동합니다. 역방향 지원되지 않습니다.
Palak Darji

동의합니다. 이것이 최고의 솔루션입니다
Senzo Malinga

10

버튼은 내부 이미지의 크기를 조정하지 않습니다.

내 솔루션에는 코드 조작이 필요하지 않습니다.

TextView 및 ImageView와 함께 레이아웃을 사용합니다.

레이아웃의 배경에는 빨간색 3D 드로어 블이 있어야합니다.

android : scaleType xml 속성 을 정의해야 할 수 있습니다 .

예:

<LinearLayout
    android:id="@+id/list_item"
    android:layout_width="fill_parent"
    android:layout_height="50dp"
    android:padding="2dp" >

    <ImageView
        android:layout_width="50dp"
        android:layout_height="fill_parent"
        android:src="@drawable/camera" />

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_weight="1"
        android:lines="1"
        android:gravity="center_vertical"
        android:text="Hello - primary" />

</LinearLayout>

BTW :

  1. 다른 해상도 아이콘으로 계산하면 UI가 예측 불가능할 수 있습니다 (아이콘이 너무 크거나 너무 작음).
  2. 텍스트보기 (버튼 포함)의 텍스트가 구성 요소를 채우지 않습니다. 이것은 Android 문제이며 해결 방법을 모르겠습니다.
  3. 포함으로 사용할 수 있습니다.

행운을 빕니다


RE : TextViews,보기를 최대한 작게하려면 패딩을 0으로 설정합니다. 그렇지 않으면 기본 패딩이있는 것으로 보입니다.
William T. Mallard

6

Abhinav가 제안한 대로 ScaleDrawable 을 사용합니다 .

문제는 드로어 블이 표시되지 않는다는 것입니다. 이것은 ScaleDrawables의 일종의 버그입니다. 프로그래밍 방식으로 "레벨"을 변경해야합니다. 이것은 모든 버튼에서 작동합니다.

// Fix level of existing drawables
Drawable[] drawables = myButton.getCompoundDrawables();
for (Drawable d : drawables) if (d != null && d instanceof ScaleDrawable) d.setLevel(1);
myButton.setCompoundDrawables(drawables[0], drawables[1], drawables[2], drawables[3]);

좋은. 가까운 장래에 이것을 사용할 것 같습니다!
Abhinav

@zeh, 이제 setContentView 전에 위 코드를 실행하면 작동한다는 것을 알았습니다. 그렇지 않으면 작동하지 않습니다. 이것을 게시물에 추가하면 더 좋을 수 있습니다.
Buddy

어떤 이유로 위의 솔루션이 모든 Android 버전에서 작동하지 않습니다.
Buddy

6

내 DiplayScaleHelper는 완벽하게 작동합니다.

import android.content.Context;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.ScaleDrawable;
import android.widget.Button;

public class DisplayHelper {

  public static void scaleButtonDrawables(Button btn, double fitFactor) {
        Drawable[] drawables = btn.getCompoundDrawables();

        for (int i = 0; i < drawables.length; i++) {
            if (drawables[i] != null) {
                if (drawables[i] instanceof ScaleDrawable) {
                    drawables[i].setLevel(1);
                }
                drawables[i].setBounds(0, 0, (int) (drawables[i].getIntrinsicWidth() * fitFactor),
                    (int) (drawables[i].getIntrinsicHeight() * fitFactor));
                ScaleDrawable sd = new ScaleDrawable(drawables[i], 0, drawables[i].getIntrinsicWidth(), drawables[i].getIntrinsicHeight());
                if(i == 0) {
                    btn.setCompoundDrawables(sd.getDrawable(), drawables[1], drawables[2], drawables[3]);
                } else if(i == 1) {
                    btn.setCompoundDrawables(drawables[0], sd.getDrawable(), drawables[2], drawables[3]);
                } else if(i == 2) {
                    btn.setCompoundDrawables(drawables[0], drawables[1], sd.getDrawable(), drawables[3]);
                } else {
                    btn.setCompoundDrawables(drawables[0], drawables[1], drawables[2], sd.getDrawable());
                }
            }
        }
    }
}

4

setBounds"복합"드로어 블을 호출 하여 이미지 크기를 수정할 수 있습니다 .

이 코드를 사용하여 버튼의 드로어 블 크기를 자동으로 조정하십시오.

DroidUtils.scaleButtonDrawables((Button) findViewById(R.id.ButtonTest), 1.0);

이 함수로 정의 :

public final class DroidUtils {

    /** scale the Drawables of a button to "fit"
     *  For left and right drawables: height is scaled 
     *  eg. with fitFactor 1 the image has max. the height of the button.
     *  For top and bottom drawables: width is scaled: 
     *  With fitFactor 0.9 the image has max. 90% of the width of the button 
     *  */
    public static void scaleButtonDrawables(Button btn, double fitFactor) {
        Drawable[] drawables = btn.getCompoundDrawables();

        for (int i = 0; i < drawables.length; i++) {
            if (drawables[i] != null) {
                int imgWidth = drawables[i].getIntrinsicWidth();
                int imgHeight = drawables[i].getIntrinsicHeight();
                if ((imgHeight > 0) && (imgWidth > 0)) {    //might be -1
                    float scale;
                    if ((i == 0) || (i == 2)) { //left or right -> scale height
                        scale = (float) (btn.getHeight() * fitFactor) / imgHeight;
                    } else { //top or bottom -> scale width
                        scale = (float) (btn.getWidth() * fitFactor) / imgWidth;                    
                    }
                    if (scale < 1.0) {
                        Rect rect = drawables[i].getBounds();
                        int newWidth = (int)(imgWidth * scale);
                        int newHeight = (int)(imgHeight * scale);
                        rect.left = rect.left + (int)(0.5 * (imgWidth - newWidth)); 
                        rect.top = rect.top + (int)(0.5 * (imgHeight - newHeight));
                        rect.right = rect.left + newWidth;
                        rect.bottom = rect.top + newHeight;
                        drawables[i].setBounds(rect);
                    }
                }
            }
        }
    }
}

onCreate()단추 높이와 너비는 아직 사용할 수 없기 때문에 활동 에서 호출 되지 않을 수 있습니다. 이것을 호출하거나이 솔루션onWindowFocusChanged()사용 하여 함수를 호출하십시오.

편집 :

이 기능의 첫 번째 구현은 올바르게 작동하지 않았습니다. userSeven7s 코드를 사용하여 이미지의 크기를 조정했지만 반환 ScaleDrawable.getDrawable() 이 작동하지 않는 것 같습니다 (도 마찬가지입니다 ScaleDrawable).

수정 된 코드는 setBounds이미지의 경계를 제공하는 데 사용 됩니다. Android는 이미지를 이러한 범위에 맞 춥니 다.


전화하지 말라고 해주셔서 감사합니다 onCreate().
Binarian


1

아래와 같이하고 있습니다. 이렇게하면 입력 이미지와 관계없이 버튼에 100x100 크기의 이미지가 생성됩니다.

drawable.bounds = Rect(0,0,100,100)
button.setCompoundDrawables(drawable, null, null, null)

ScaleDrawable어느 쪽도 사용하지 않습니다 . button.setCompoundDrawablesRelativeWithIntrinsicBounds()방금 설정 한 경계 대신 고유 경계 (소스 이미지 크기)를 사용하는 것처럼 보이기 때문에 사용 하지 않으면 문제가 해결되었습니다.



0

ScaleDrawable 에서 이미지를 래핑 한 다음 버튼에서 사용 하려고 했습니까 ?


2
방금 시도했지만 ScaleDrawable이 표시되지 않습니다. :-( ImageView에는 없습니다. 샘플 코드를 가져 와서 드로어 블을 대체했습니다. 이것이 작동하지 않는 이유를 아십니까?
Reto

나는 같은 문제가 있었다. ScaleDrawable완벽 하겠지만 작동하지 않습니다. "레벨"과 관련이있는 것 같습니다. 자세한 내용은 여기 (및 완벽하지 않은 몇 가지 해결 방법) : stackoverflow.com/questions/5507539/…
zeh

(편집) 일반 코드로 수정했습니다! 여기에 솔루션 아직 사용 ScaleDrawables 당신을 허용 : stackoverflow.com/a/13706836/439026
ZEH

0

여기에 벡터 드로어 블 크기 조정을 위해 만든 함수가 있습니다. TextView 복합 드로어 블 설정에 사용했습니다.

/**
 * Used to load vector drawable and set it's size to intrinsic values
 *
 * @param context Reference to {@link Context}
 * @param resId   Vector image resource id
 * @param tint    If not 0 - colour resource to tint the drawable with.
 * @param newWidth If not 0 then set the drawable's width to this value and scale 
 *                 height accordingly.
 * @return On success a reference to a vector drawable
 */
@Nullable
public static Drawable getVectorDrawable(@NonNull Context context,
                                         @DrawableRes int resId,
                                         @ColorRes int tint,
                                         float newWidth)
{
    VectorDrawableCompat drawableCompat =
            VectorDrawableCompat.create(context.getResources(), resId, context.getTheme());
    if (drawableCompat != null)
    {
        if (tint != 0)
        {
            drawableCompat.setTint(ResourcesCompat.getColor(context.getResources(), tint, context.getTheme()));
        }

        drawableCompat.setBounds(0, 0, drawableCompat.getIntrinsicWidth(), drawableCompat.getIntrinsicHeight());

        if (newWidth != 0.0)
        {
            float scale = newWidth / drawableCompat.getIntrinsicWidth();
            float height = scale * drawableCompat.getIntrinsicHeight();
            ScaleDrawable scaledDrawable = new ScaleDrawable(drawableCompat, Gravity.CENTER, 1.0f, 1.0f);
            scaledDrawable.setBounds(0,0, (int) newWidth, (int) height);
            scaledDrawable.setLevel(10000);
            return scaledDrawable;
        }
    }
    return drawableCompat;
}


0

당신이하지 않았기 때문 setLevel입니다. 당신이 setLevel(1)원하는대로 표시됩니다


0

Kotlin 확장 사용

val drawable = ContextCompat.getDrawable(context, R.drawable.my_icon)
// or resources.getDrawable(R.drawable.my_icon, theme)
val sizePx = 25
drawable?.setBounds(0, 0, sizePx, sizePx)
//                            (left,     top,  right, bottom)
my_button.setCompoundDrawables(drawable, null, null, null)

쉽게 재사용 할 수 있도록 TextView ( Button extends it ) 에 확장 기능을 만드는 것이 좋습니다 .

button.leftDrawable(R.drawable.my_icon, 25)

// Button extends TextView
fun TextView.leftDrawable(@DrawableRes id: Int = 0, @DimenRes sizeRes: Int) {
    val drawable = ContextCompat.getDrawable(context, id)
    val size = context.resources.getDimensionPixelSize(sizeRes)
    drawable?.setBounds(0, 0, size, size)
    this.setCompoundDrawables(drawable, null, null, null)
}

질문은 TextView가 아니라 Button에 관한 것이 었습니다.
Firzen

1
답을 읽어 보셨어야합니다. Button은 TextView를 확장하므로 두 가지 모두에 사용할 수 있습니다. 또는 버튼 만 확장하도록 확장 변경
Gibolt

-1

이 게시물의 기술을 시도했지만 그다지 매력적이지 않았습니다. 내 해결책은 imageview와 textview를 사용하고 imageview의 상단과 하단을 textview에 정렬하는 것이 었습니다. 이 방법으로 원하는 결과를 얻었습니다. 다음은 몇 가지 코드입니다.

<RelativeLayout
    android:id="@+id/relativeLayout1"
    android:layout_width="match_parent"
    android:layout_height="48dp" >


    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignTop="@+id/textViewTitle"
        android:layout_alignBottom="@+id/textViewTitle"
        android:src="@drawable/ic_back" />

    <TextView
        android:id="@+id/textViewBack"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@+id/textViewTitle"
        android:layout_alignBottom="@+id/textViewTitle"
        android:layout_toRightOf="@+id/imageView1"
        android:text="Back"
        android:textColor="@color/app_red"
        android:textSize="@dimen/title_size" />
</RelativeLayout>

-1

이를 위해 사용자 정의 버튼 클래스를 만들었습니다.

CustomButton.java

public class CustomButton extends android.support.v7.widget.AppCompatButton {

    private Drawable mDrawable;

    public CustomButton(Context context, AttributeSet attrs) {
        super(context, attrs);

        TypedArray a = context.getTheme().obtainStyledAttributes(
                attrs,
                R.styleable.CustomButton,
                0, 0);

        try {
            float mWidth = a.getDimension(R.styleable.CustomButton_drawable_width, 0);
            float mHeight = a.getDimension(R.styleable.CustomButton_drawable_width, 0);

            Drawable[] drawables = this.getCompoundDrawables();
            Drawable[] resizedDrawable = new Drawable[4];

            for (int i = 0; i < drawables.length; i++) {
                if (drawables[i] != null) {
                    mDrawable = drawables[i];
                }
                resizedDrawable[i] = getResizedDrawable(drawables[i], mWidth, mHeight);
            }

            this.setCompoundDrawables(resizedDrawable[0], resizedDrawable[1], resizedDrawable[2], resizedDrawable[3]);
        } finally {
            a.recycle();
        }
    }

    public Drawable getmDrawable() {
        return mDrawable;
    }

    private Drawable getResizedDrawable(Drawable drawable, float mWidth, float mHeight) {
        if (drawable == null) {
            return null;
        }

        try {
            Bitmap bitmap;

            bitmap = Bitmap.createBitmap((int)mWidth, (int)mHeight, Bitmap.Config.ARGB_8888);

            Canvas canvas = new Canvas(bitmap);
            drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
            drawable.draw(canvas);
            return drawable;
        } catch (OutOfMemoryError e) {
            // Handle the error
            return null;
        }
    }
}

attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="CustomButton">
        <attr name="drawable_width" format="dimension" />
        <attr name="drawable_height" format="dimension" />
    </declare-styleable>
</resources>

XML에서의 사용법

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:custom="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.MainActivity">

     <com.example.CustomButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:drawableTop="@drawable/ic_hero"
            android:text="Avenger"
            custom:drawable_height="10dp"
            custom:drawable_width="10dp" />

</RelativeLayout>

1
아무것도하지 않으려는 경우 왜 인을 생성하고 그 Canvas안으로 getResizedDrawable드로우합니까? 전체 기능을 drawable.setBounds(0, 0, mWidth, mHeight).
Antimonit
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.