Làm cách nào để thu nhỏ phần có thể vẽ trên một nút?


87

làm cách nào để làm cho phần có thể vẽ được trên một nút nhỏ hơn? Biểu tượng quá lớn, thực sự cao hơn nút. Đây là mã tôi đang sử dụng:

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

Phía trên trông như thế nào, phía dưới trông như thế nào ngay bây giờ.

Phía trên trông như thế nào, phía dưới trông như thế nào ngay bây giờ.

Tôi đã thử điều này nhưng không có hình ảnh hiển thị. :-(

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

Sẽ tốt hơn nếu bạn tải lên một hình ảnh về những gì bạn đang nhận được và những gì bạn đang cố gắng làm. Cảm ơn.
Lalit Poptani

Bạn có thể xác định nút tùy chỉnh của mình để xác định kích thước của đồ có thể kéo được. Xem câu trả lời của tôi tại đây stackoverflow.com/a/31916731/2308720
Oleksandr

Tôi biết điều này là từ năm 2011 ... nhưng tôi thực sự thích giao diện của nút với camera phá vỡ ra khỏi bờ cõi của các nút - Tôi sẽ để lại nó theo cách đó là ... chỉ sayin' :)
killercowuk

Câu trả lời:


70

Bạn nên sử dụng ImageButton và chỉ định hình ảnh trong đó android:srcvà đặt android:scaletypethànhfitXY


Đặt tỷ lệ có thể vẽ trong mã

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

Nếu bạn đặt có thể vẽ trong mã, bạn có thể thay đổi kích thước của nó dựa trên chiều cao của nút và sau đó đặt nó.
Ronnie

Bây giờ hình ảnh được hiển thị nhưng nó không được thay đổi kích thước! Tôi đã thử các giá trị từ 0,1f đến 10f. Bất kỳ ý tưởng? Cảm ơn sự giúp đỡ của bạn ...
Reto vào

Hãy thử điều nàydrawable.setBounds(0, 0, drawable.getIntrinsicWidth()*0.5, drawable.getIntrinsicHeight()*0.5);
Ronnie

Nếu điều này thay đổi kích thước của phần có thể vẽ, thì bạn có thể loại bỏ phần có thể thu nhỏ và sử dụng trực tiếp phần có thể vẽ.
Ronnie

2
Chúng ta có phải đặt các giá trị của riêng mình cho scaleWidth và scaleHeight không? Chúng chỉ mang tính chất mô tả?
SametSahin

89

Tôi đã tìm thấy một giải pháp XML rất đơn giản và hiệu quả mà không yêu cầu ImageButton

Tạo một tệp có thể vẽ cho hình ảnh của bạn như bên dưới và sử dụng nó cho 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>

Bạn có thể đặt kích thước hình ảnh với android:widthandroid:heightthuộc tính.

Bằng cách này, ít nhất bạn có thể có được cùng một kích thước cho các màn hình khác nhau.

Hạn chế là nó không chính xác như fitXY sẽ chia tỷ lệ chiều rộng hình ảnh cho vừa với X và chia tỷ lệ chiều cao hình ảnh cho phù hợp.


9
Đây phải là câu trả lời được chấp nhận. Nếu một người không muốn một ImageButton (ví dụ: vì họ muốn văn bản, v.v.) thì câu trả lời này cho phép các hình ảnh có kích thước trong một Nút có Văn bản cộng với mã không.
Thép tái chế

3
Tôi đã tạo một cái có thể kéo mới như thế này và sau đó android:drawableToptôi đã thêm cái có thể kéo mới. Bất kể giá trị nào cho chiều rộng / chiều cao tôi đặt, nó sẽ hiển thị cho tôi giá trị mặc định.
driftking9987

9
Dường như không hoạt động đối với các phiên bản Android bên dưới Lollipop.
Jyotman Singh,

32
chiều cao, chiều rộng chỉ hoạt động trong API cấp 23 trở lên. Không được hỗ trợ lùi.
Palak Darji

Tôi đồng ý, đây là bởi đến nay các giải pháp tốt nhất
Senzo Malinga

10

Các nút không thay đổi kích thước hình ảnh bên trong của chúng.

Giải pháp của tôi không yêu cầu thao tác mã.

Nó sử dụng bố cục với TextView và ImageView.

Nền của bố cục phải có 3d màu đỏ vẽ được.

Bạn có thể cần xác định thuộc tính xml android: scaleType .

Thí dụ:

<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. Việc đếm trên các biểu tượng có độ phân giải khác nhau có thể dẫn đến giao diện người dùng không thể đoán trước được (biểu tượng quá lớn hoặc quá nhỏ)
  2. Văn bản trong chế độ xem văn bản (bao gồm cả trong các nút) không điền vào thành phần. Đây là một vấn đề của Android và tôi không biết làm thế nào để giải quyết nó.
  3. Bạn có thể sử dụng nó như một bao gồm.

Chúc may mắn


RE: TextViews, nếu tôi muốn chế độ xem càng nhỏ càng tốt, tôi đặt vùng đệm cho nó thành 0. Nó dường như có một phần đệm mặc định nếu không.
William T. Mallard

6

Sử dụng ScaleDrawable như Abhinav đã đề xuất.

Vấn đề là drawable không hiển thị sau đó - đó là một số lỗi trong ScaleDrawables. bạn sẽ cần thay đổi "cấp độ" theo lập trình. Điều này sẽ hoạt động cho mọi nút:

// 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]);

Đẹp. Tôi nghĩ rằng tôi có thể sẽ sử dụng cái này trong tương lai gần!
Abhinav

@zeh, bây giờ tôi thấy rằng nó hoạt động nếu bạn chạy đoạn mã trên trước setContentView, nếu không thì nó không hoạt động. Sẽ tốt hơn nếu bạn thêm điều này vào bài viết của mình.
Buddy

Vì một số lý do, giải pháp ở trên của tôi không hoạt động trên tất cả các phiên bản Android.
Buddy

6

DiplayScaleHelper của tôi, hoạt động hoàn hảo:

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

Bạn có thể sử dụng các bảng có thể kéo setBoundsđược "phức hợp" để sửa đổi kích thước của hình ảnh.

Hãy thử mã này để tự động điều chỉnh kích thước có thể kéo của nút của bạn:

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

được định nghĩa bởi hàm này:

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

Xin lưu ý rằng điều này có thể không được gọi trong onCreate()một hoạt động, vì chiều cao và chiều rộng của nút chưa (chưa) khả dụng ở đó. Gọi này vào onWindowFocusChanged()hoặc sử dụng giải pháp này để gọi hàm.

Đã chỉnh sửa:

Phiên bản đầu tiên của hàm này không hoạt động chính xác. Nó đã sử dụng mã userSeven7s để chia tỷ lệ hình ảnh, nhưng việc trả lại ScaleDrawable.getDrawable() dường như không hoạt động (cũng không quay lại ScaleDrawable) đối với tôi.

Mã đã sửa đổi sử dụng setBoundsđể cung cấp giới hạn cho hình ảnh. Android phù hợp với hình ảnh trong những giới hạn này.


Cảm ơn bạn rằng bạn đã nói để không gọi nó vào onCreate().
Binarian 22/02/18


1

Tôi đang làm nó như dưới đây. Điều này tạo ra một hình ảnh kích thước 100x100 trong nút độc lập với hình ảnh đầu vào.

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

Cũng không sử dụng ScaleDrawable. Không sử dụng đã button.setCompoundDrawablesRelativeWithIntrinsicBounds()giải quyết được vấn đề của tôi, vì điều đó dường như sử dụng giới hạn nội tại (kích thước hình ảnh nguồn) thay vì giới hạn bạn vừa đặt.


0

Bạn có thể sử dụng các ngăn kéo có kích thước khác nhau được sử dụng với các mật độ / kích thước màn hình khác nhau, v.v. để hình ảnh của bạn trông phù hợp trên tất cả các thiết bị.

Xem tại đây: http://developer.android.com/guide/practices/screens_support.html#support


Tôi sử dụng cùng một hình ảnh ở những nơi khác nhau. Đây là lý do tại sao tôi không thể thay đổi kích thước nó, nó sẽ được hiển thị ở kích thước tôi muốn.
Reto vào

0

Bạn đã thử gói hình ảnh của mình trong ScaleDrawable và sau đó sử dụng nó trong nút của bạn?


2
Chỉ cần thử điều này, tuy nhiên ScaleDrawable của tôi không hiển thị. :-( Ngay cả khi không có trong ImageView. Tôi đã lấy mã mẫu và chỉ thay thế mã có thể vẽ được. Bất kỳ ý kiến ​​nào tại sao điều này không hoạt động?
Reto

Tôi đã từng gặp vấn đề tương tự. ScaleDrawablesẽ là hoàn hảo, nhưng nó chỉ đơn giản là không hoạt động. Nó dường như có một cái gì đó để làm với "cấp độ". Thông tin thêm tại đây (và một số cách giải quyết chưa hoàn hảo): stackoverflow.com/questions/5507539/…
zeh 4/12/12

(sửa) đã sửa nó bằng một số mã chung chung! Giải pháp ở đây vẫn cho phép bạn sử dụng ScaleDrawables: stackoverflow.com/a/13706836/439026
zeh 4/12/12

0

Đây là hàm mà tôi đã tạo để chia tỷ lệ các vector có thể vẽ được. Tôi đã sử dụng nó để thiết lập TextView có thể vẽ được.

/**
 * 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
  • Sử dụng tính năng "NHẬP KHẨU CÓ THỂ VẼ", bạn có thể nhập kích thước tùy chỉnh tùy theo yêu cầu của bạn, ví dụ 20dp * 20dp

    • Bây giờ sau khi nhập, hãy sử dụng drawable_image đã nhập làm drawable_source cho nút của bạn

    • Nó đơn giản hơn theo cách này nhập mô tả hình ảnh ở đây


Bạn đến đó bằng cách nào?
nhà phát triển android


0

Đó là bởi vì bạn đã không setLevel. sau khi bạn setLevel(1), nó sẽ được hiển thị như bạn muốn


0

Sử dụng Kotlin Extension

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)

Tôi đề nghị tạo một chức năng mở rộng trên TextView ( Nút mở rộng nó ) để dễ dàng sử dụng lại.

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

Câu hỏi là về Button, không phải TextView.
Firzen

1
Bạn nên đọc câu trả lời. Nút A mở rộng TextView, vì vậy bạn có thể sử dụng nó cho cả hai. Hoặc thay đổi phần mở rộng để chỉ mở rộng một Nút
Gibolt

-1

Tôi đã thử các kỹ thuật của bài đăng này nhưng không tìm thấy bất kỳ kỹ thuật nào hấp dẫn như vậy. Giải pháp của tôi là sử dụng chế độ xem hình ảnh và chế độ xem văn bản và căn chỉnh chế độ xem hình ảnh trên cùng và dưới cùng với chế độ xem văn bản. Bằng cách này tôi đã có được kết quả mong muốn. Đây là một số mã:

<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

Tôi đã tạo một lớp nút tùy chỉnh để đạt được điều này.

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>

Cách sử dụng trong 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
Tại sao bạn tạo ra một Canvastrong getResizedDrawablevà thu hút vào nó nếu bạn không định làm gì với nó? Toàn bộ chức năng có thể được giảm xuống chỉ drawable.setBounds(0, 0, mWidth, mHeight).
Antimonit
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.