jak mogę zmniejszyć rozmiar nadający się do rysowania na przycisku? Ikona jest zbyt duża, w rzeczywistości wyższa niż przycisk. Oto kod, którego używam:
<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>
Górna jest tak, jak powinna wyglądać, a niższa, jak wygląda teraz.
Próbowałem tego, ale nie ma obrazu. :-(
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);
Odpowiedzi:
Należy użyć ImageButton i określić obraz w
android:src
i ustawićandroid:scaletype
nafitXY
Ustawienie skalowalnego rysowania w kodzie
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
źródło
drawable.setBounds(0, 0, drawable.getIntrinsicWidth()*0.5, drawable.getIntrinsicHeight()*0.5);
Znalazłem bardzo proste i skuteczne rozwiązanie XML, które nie wymaga
ImageButton
Utwórz plik do rysowania dla swojego obrazu, jak poniżej i użyj go do
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>
Możesz ustawić rozmiar obrazu za pomocą
android:width
iandroid:height
właściwości.W ten sposób możesz przynajmniej uzyskać ten sam rozmiar dla różnych ekranów.
Wadą jest to, że nie jest dokładnie takie, jak fitXY, które skaluje szerokość obrazu, aby dopasować go do X i odpowiednio skaluje wysokość obrazu.
źródło
android:drawableTop
dodałem nowy element do rysowania. Bez względu na to, jakie wartości ustawiłem dla szerokości / wysokości, pokazuje mi domyślną.Przyciski nie zmieniają rozmiaru swoich wewnętrznych obrazów.
Moje rozwiązanie nie wymaga manipulacji kodem.
Używa układu z TextView i ImageView.
Tło układu powinno mieć czerwony kolor 3d, który można narysować.
Może być konieczne zdefiniowanie atrybutu android: scaleType xml.
Przykład:
<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:
Powodzenia
źródło
Użyj ScaleDrawable, jak zasugerował Abhinav .
Problem polega na tym, że to, co można rysować, nie wyświetla się wtedy - to jakiś błąd w ScaleDrawables. musisz programowo zmienić „poziom”. To powinno działać dla każdego przycisku:
// 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]);
źródło
Mój DiplayScaleHelper, który działa idealnie:
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()); } } } } }
źródło
Możesz odwołać
setBounds
się do „złożonych” rysunków, aby zmodyfikować rozmiar obrazu.Wypróbuj ten kod, aby automatycznie zmienić rozmiar możliwego do rysowania przycisku:
DroidUtils.scaleButtonDrawables((Button) findViewById(R.id.ButtonTest), 1.0);
zdefiniowane przez tę funkcję:
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); } } } } } }
Należy pamiętać, że może to nie zostać wywołane w
onCreate()
działaniu, ponieważ wysokość i szerokość przycisku nie są tam (jeszcze) dostępne. Wywołaj toonWindowFocusChanged()
lub użyj tego rozwiązania, aby wywołać funkcję.Edytowano:
Pierwsze wcielenie tej funkcji nie działało poprawnie. Użył kodu userSeven7s do skalowania obrazu, ale zwracanie
ScaleDrawable.getDrawable()
nie wydaje się działać ( podobnie jak powrótScaleDrawable
) dla mnie.Zmodyfikowany kod używa
setBounds
do określenia granic obrazu. Android dopasowuje obraz do tych granic.źródło
onCreate()
.Jeśli chcesz użyć 1 obrazu i wyświetlić go w innym rozmiarze, możesz użyć opcji rysowania w skali ( http://developer.android.com/guide/topics/resources/drawable-resource.html#Scale ).
źródło
Robię to jak poniżej. Tworzy to obraz o rozmiarze 100x100 na przycisku niezależnie od obrazu wejściowego.
drawable.bounds = Rect(0,0,100,100) button.setCompoundDrawables(drawable, null, null, null)
Nie używam
ScaleDrawable
też. Nie użyciebutton.setCompoundDrawablesRelativeWithIntrinsicBounds()
rozwiązało mój problem, ponieważ wydaje się, że używa wewnętrznych granic (rozmiar obrazu źródłowego) zamiast granic, które właśnie ustawiłeś.źródło
Możesz użyć różnych rozmiarów rysunków, które są używane z różnymi gęstościami / rozmiarami ekranu itp., Aby Twój obraz wyglądał dobrze na wszystkich urządzeniach.
Zobacz tutaj: http://developer.android.com/guide/practices/screens_support.html#support
źródło
Czy próbowałeś opakować swój obraz w ScaleDrawable, a następnie użyć go w swoim przycisku?
źródło
ScaleDrawable
byłoby idealne, ale po prostu nie działa. Wydaje się, że ma to coś wspólnego z „poziomami”. Więcej informacji tutaj (i niektóre obejścia, które są mniej niż idealne): stackoverflow.com/questions/5507539/…Tutaj funkcja, którą stworzyłem do skalowania rysunków wektorowych. Użyłem go do ustawienia możliwości rysowania złożonego 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; }
źródło
Korzystając z funkcji IMPORT RYSOWALNYCH SERII, możesz importować rozmiar niestandardowy w zależności od wymagań. Przykład 20dp * 20dp
Teraz po zaimportowaniu użyj importowanego drawable_image jako drawable_source dla swojego przycisku
W ten sposób jest prostsze
źródło
To dlatego, że tego nie zrobiłeś
setLevel
. po tobiesetLevel(1)
będzie wyświetlany tak, jak chceszźródło
Korzystanie z rozszerzenia 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)
Sugeruję utworzenie funkcji rozszerzenia w TextView ( przycisk rozszerza ją ) w celu łatwego ponownego użycia.
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) }
źródło
Wypróbowałem techniki z tego postu, ale żadna z nich nie była tak atrakcyjna. Moim rozwiązaniem było użycie widoku obrazu i widoku tekstu i wyrównanie widoku obrazu od góry do dołu do widoku tekstu. W ten sposób uzyskałem pożądany efekt. Oto kod:
<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>
źródło
Aby to osiągnąć, stworzyłem niestandardową klasę przycisków.
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>
Wykorzystanie w 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>
źródło
Canvas
ingetResizedDrawable
i wciągasz się w to, jeśli nie zamierzasz nic z tym zrobić? Całość funkcji można by zredukować tylko dodrawable.setBounds(0, 0, mWidth, mHeight)
.