Как я могу уменьшить рисунок на кнопке?
Как я могу сделать рисование на кнопке меньше? Значок слишком большой, на самом деле выше, чем кнопка. Это код, который я использую:
<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);
14 ответов
Вы должны использовать 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
Я нашел очень простое и эффективное решение 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:width
а также android:height
свойства.
Таким образом, вы можете получить одинаковый размер для разных экранов.
Недостатком является то, что он не совсем похож на fitXY, который масштабировал бы ширину изображения, чтобы соответствовать X, и соответственно масштабировал высоту изображения.
Кнопки не меняют свои внутренние изображения.
Мое решение не требует манипулирования кодом.
Он использует макет с 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>
КСТАТИ:
- Подсчет значков с разным разрешением может привести к непредсказуемому пользовательскому интерфейсу (значок слишком большой или слишком маленький)
- Текст в текстовом представлении (включая кнопки) не заполняет компонент. Это проблема Android, и я не знаю, как ее решить.
- Вы можете использовать его в качестве включения.
Удачи
Мой 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());
}
}
}
}
}
Используйте ScaleDrawable, как предложил Абхинав.
Проблема в том, что drawable тогда не отображается - это какая-то ошибка в 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]);
Ты можешь позвонить 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 вписывает изображение в эти границы.
Я делаю это, как показано ниже. Это создает изображение размером 100x100 в кнопке независимо от входного изображения.
drawable.bounds = Rect(0,0,100,100)
button.setCompoundDrawables(drawable, null, null, null)
Не используется ScaleDrawable
или. Не используется button.setCompoundDrawablesRelativeWithIntrinsicBounds()
решил мою проблему, так как кажется, что вместо внутренних границ, которые вы только что установили, используются внутренние границы (размер исходного изображения).
Если вы хотите использовать 1 изображение и отображать его в другом размере, вы можете использовать масштабируемое рисование ( http://developer.android.com/guide/topics/resources/drawable-resource.html).
Вот функция, которую я создал для масштабирования векторных отрисовок. Я использовал его для настройки составного объекта 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;
}
Вы пытались обернуть ваше изображение в ScaleDrawable и затем использовать его в своей кнопке?
Это потому что ты не setLevel
, после тебя setLevel(1)
, это будет отображаться как вы хотите
Вы можете использовать рисованные объекты разных размеров, которые используются с различными плотностями / размерами экрана и т. Д., Чтобы ваше изображение выглядело правильно на всех устройствах.
Смотрите здесь: http://developer.android.com/guide/practices/screens_support.html
Я попробовал методы этого поста, но не нашел ни одного из них столь привлекательным. Мое решение состояло в том, чтобы использовать viewview и textview и выровнять верхнюю и нижнюю часть viewview к 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>
Я сделал пользовательский класс кнопок для достижения этой цели.
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>
Использование расширения 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.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)
}