studio programacion herramientas fundamentos con avanzado aplicaciones android scale compound-drawables

android - programacion - ¿Cómo puedo reducir el dibujo de un botón?



manual de android en pdf (14)

¿ ScaleDrawable envolver tu imagen en un ScaleDrawable y luego usarla en tu botón?

¿Cómo puedo hacer que el dibujo de un botón sea más pequeño? El icono es demasiado grande, en realidad más alto que el botón. Este es el código que estoy usando:

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

La parte superior es cómo debería verse, cuanto más bajo se vea ahora.

Intenté esto pero no se muestra ninguna imagen. :-(

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


Aquí la función que creé para escalar vectores se puede dibujar. Lo usé para establecer el compuesto de TextView dibujable.

/** * 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; }


Debe usar ImageButton y especificar la imagen en android:src , y configurar android:scaletype para fitXY

Ajuste escalado dibujable en el código

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


Es porque no estableciste setLevel . después de establecer setLevel(1) , se mostrará como quieras


He encontrado una solución XML muy simple y efectiva que no requiere ImageButton

Haga un archivo dibujable para su imagen como a continuación y android:drawableLeft para 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>

Puede establecer el tamaño de la imagen con android:width y android:height properties.

De esta forma, al menos podrías obtener el mismo tamaño para diferentes pantallas.

El inconveniente es que no es exactamente como fitXY lo que escalaría el ancho de la imagen para ajustarse a X y escalar la altura de la imagen en consecuencia.


Hice una clase de botón personalizado para lograr esto.

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>

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


Los botones no cambian el tamaño de sus imágenes internas.

Mi solución no requiere manipulación de código.

Utiliza un diseño con TextView e ImageView.

El fondo del diseño debe tener el 3d dibujable rojo.

Es posible que necesite definir el atributo android: scaleType xml.

Ejemplo:

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

Por cierto:

  1. Contar con diferentes iconos de resolución puede resultar en una IU no predecible (icono demasiado grande o demasiado pequeño)
  2. El texto en la vista de texto (incluidos los botones) no llena el componente. Este es un problema de Android y no sé cómo resolverlo.
  3. Puede usarlo como una inclusión.

Buena suerte


Mi DiplayScaleHelper, que funciona perfectamente:

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


Probé las técnicas de esta publicación, pero no encontré ninguna de ellas tan atractiva. Mi solución fue usar una vista de imagen y una vista de texto y alinear la vista superior e inferior de la imagen con la vista de texto. De esta manera obtuve el resultado deseado. Aquí hay un código:

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


Puede llamar a setBounds en los setBounds "compuestos" para modificar el tamaño de la imagen.

Pruebe este código para autoesificar el dibujo de su botón:

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

definido por esta función:

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

Tenga en cuenta que esto no se puede onCreate() en onCreate() de una actividad, porque la altura y el ancho del botón no están (todavía) disponibles allí. Llame esto en onWindowFocusChanged() o use esta solución para llamar a la función.

Editado:

La primera encarnación de esta función no funcionó correctamente. Usó el código userSeven7s para escalar la imagen, pero devolver ScaleDrawable.getDrawable() no parece funcionar (ni retorna ScaleDrawable ) para mí.

El código modificado usa setBounds para proporcionar los límites de la imagen. Android se ajusta a la imagen en estos límites.



Si desea usar 1 imagen y mostrarla en diferentes tamaños, puede usar la escala dibujable ( ScaleDrawable ).


Use un ScaleDrawable como sugirió Abhinav .

El problema es que el dibujable no se muestra en ese momento, es una especie de error en ScaleDrawables. necesitarás cambiar el "nivel" programáticamente. Esto debería funcionar para cada botón:

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


  • Con la función "IMPORTADOR DE BATCH DRAWABLE", puede importar tamaños personalizados según su ejemplo de requisito 20dp * 20dp

    • Ahora, después de importar, usa la imagen dibujable importada como drawable_source para tu botón

    • Es más simple de esta manera