Как реализовать андроид: фон, который не растягивается?

100

Я нашел эту замечательную ветку, описывающую, как «съесть торт и съесть его тоже», т.е. использовать изображение Buttonвместо ImageButton(что не позволяет SetText(), изменение размера и т. Д.).

Это достигается с помощью атрибута View:

android:background="@drawable/bgimage"

Единственная проблема заключается в том, что изображение растягивается до размера кнопки.

Если не считать жесткого кодирования фиксированного размера кнопки (в пикселях!), Есть ли способ запретить Android вообще растягивать фоновое изображение и либо обрезать, либо дополнять его?

ef2011
источник

Ответы:

29

Вам следует использовать ImageView, если вы не хотите, чтобы он растягивался. Фоновые изображения всегда растягиваются, чтобы соответствовать виду. Вам нужно установить его как Drawable, чтобы заставить аспект изображения объекту.

В противном случае, если вы придерживаетесь идеи кнопки, вам нужно будет принудительно масштабировать кнопку, чтобы изображение не растягивалось.

Код:

onCreate(Bundle bundle) {
  // Set content layout, etc up here

  // Now adjust button sizes
  Button b = (Button) findViewById(R.id.somebutton);
  int someDimension = 50; //50pixels
  b.setWidth(someDimension);
  b.setHeight(someDimension);
}
Доктор Дж.
источник
1
Спасибо +1. ImageViewВыглядит интересно. Я заметил , что это имеет атрибут, которого нет в Button: android:cropToPadding. Я не против использовать вместо этого ImageView, если он есть setOnClickListener()- а он это делает. Что я потеряю, переключившись с Buttonна ImageView?
ef2011 05
1
Кстати, второе предложенное вами решение по-прежнему растягивает изображение.
ef2011 05
В итоге я использовал фиксированный размер кнопки (в пикселях!), Но я принимаю ваш ответ, потому что первое предложение выглядит как рабочее альтернативное решение.
ef2011 05
1
@ ef2011 Для ImageView не устанавливайте его в качестве фонового изображения, вы должны установить его как, setDrawableResourceа затем убедиться, что setAdjustViewBoundsустановлено значение true
Д-р Джей
9
Проголосовали за неудачное решение. Правильное решение здесь: stackoverflow.com/a/9362168/145046
Алекс Н.
261

Вы можете создать растровое изображение xml и использовать его в качестве фона для представления. Чтобы предотвратить растяжение, вы можете указать android:gravityатрибут.

например:

<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
    android:src="@drawable/dvdr"
    android:tileMode="disabled" android:gravity="top" >
</bitmap>

Есть много параметров, которые вы можете использовать для настройки рендеринга изображения.

http://developer.android.com/guide/topics/resources/drawable-resource.html#Bitmap.

Сантош
источник
3
Использование ImageViews - это обходной путь, который не всегда возможен - я считаю, что это правильное решение :)
JakeP
3
Я устанавливаю фон во время выполнения. Есть ли какое-либо решение для создания растрового изображения во время выполнения?
Вивек Кумар Шривастава
1
для меня это было лучшее решение, но с удалением атрибута «gravity», который соответствует его значению по умолчанию «fill». Это позволит изменять размер изображения по размеру экрана. Изучите ссылку @Santosh для получения дополнительной информации. Спасибо!
Hugo
12
Я вижу только одну проблему с этим подходом. Если доступный для рисования источник уже больше контейнера, это будет обрезать изображение (в зависимости от силы тяжести), а не изменять его размер, сохраняя соотношение сторон, чтобы соответствовать контейнеру.
Shashwat Black
1
Сейчас выглядит немного устаревшим. Это работает только для растровых изображений и не работает для векторных чертежей.
The_Sympathizer
25

Простое использование ImageButtonвместо Buttonрешает проблему.

<ImageButton android:layout_width="30dp"
             android:layout_height="30dp"
             android:src="@drawable/bgimage" />

и вы можете установить

android:background="@null"

чтобы удалить фон кнопки, если хотите.

Быстрая починка !! :-)

Адиль Малик
источник
1
А затем установите изображение с помощью метода setImageResource () ... который сработал для меня.
arlomedia
я хотел и изображение, и цвет фона в кнопке ... это сработало как шарм
Абхишек Чаухан
У меня работает точнее (я имею в виду - layout_centerVertical, например).
Максим Фирсофф
12

Я использую ImageView в RelativeLayout, который накладывается на мой обычный макет. Код не требуется. Он устанавливает размер изображения на всю высоту экрана (или любой другой макет, который вы используете), а затем обрезает изображение слева и справа по ширине. В моем случае, если пользователь поворачивает экран, изображение может быть слишком маленьким. Поэтому я использую match_parent, что заставляет изображение растягиваться по ширине, если оно слишком маленькое.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/main_backgroundImage"
        android:layout_width="match_parent"
        //comment: Stretches picture in the width if too small. Use "wrap_content" does not stretch, but leaves space

        android:layout_height="match_parent"
        //in my case I always want the height filled

        android:layout_alignParentTop="true"
        android:scaleType="centerCrop"
        //will crop picture left and right, so it fits in height and keeps aspect ratio

        android:contentDescription="@string/image"
        android:src="@drawable/your_image" />

    <LinearLayout
        android:id="@+id/main_root"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >
    </LinearLayout>

</RelativeLayout>
Гуннар Бернштейн
источник
На самом деле это гораздо более простое решение проблемы, которой не должно быть,
Акос Никхази
6

У меня была та же проблема: вы должны использовать только изображение с 9 патчами (.9.png) вместо исходного изображения.

Serge

Серж Боллаертс
источник
5

Используйте draw9patch ... включенный в инструменты SDK Android Studio. Вы можете определить растяжимые области вашего изображения. Важные части ограничены, и изображение не выглядит искаженным. Хорошая демонстрация на dra9patch ЗДЕСЬ

Используйте draw9patch, чтобы изменить существующий splash.png на new_splash.9.png, перетащите new_splash.9.png в папку проекта drawable-hdpi и убедитесь, что файлы AndroidManifest и styles.xml правильные, как показано ниже:

AndroidManifest.xml:

<application
...
        android:theme="@style/splashScreenStyle"
>

styles.xml:

<style name="splashScreenStyle" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="android:windowBackground">@drawable/new_splash</item>
</style>
WM1
источник
3

У меня было фоновое изображение, небольшое по размеру, но со странными размерами - отсюда растяжение и плохая производительность. Я создал метод с параметрами Context, View и идентификатором (int), который будет соответствовать размеру экрана устройства. Используйте это, например, в Fragments onCreateView, чтобы установить фон.

public void setBackground(Context context, View view, int drawableId){
    Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(),drawableId);

    bitmap = Bitmap.createScaledBitmap(bitmap, Resources.getSystem().
             getDisplayMetrics().widthPixels,
             Resources.getSystem().getDisplayMetrics().heightPixels,
             true);

    BitmapDrawable bitmapDrawable = new BitmapDrawable(context.getResources(), 
                                    bitmap);

    view.setBackground(bitmapDrawable);
}
ZooMagic
источник
1

Вот версия ответа Сантоша для программно созданных кнопок без необходимости отдельной конфигурации XML:

Button button = new Button(getContext());
Bitmap backgroundBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.my_button);
BitmapDrawable backgroundDrawable = new BitmapDrawable(getResources(), backgroundBitmap);
backgroundDrawable.setGravity(Gravity.CENTER); // also LEFT, CENTER_VERTICAL, etc.
backgroundDrawable.setColorFilter(new PorterDuffColorFilter(Color.RED, PorterDuff.Mode.SRC_ATOP));
button.setBackground(backgroundDrawable);

Я включил строку ColorFilter, поскольку она работает немного иначе, чем кнопки с обычным фоновым изображением.

Arlomedia
источник
1

Вы можете использовать a FrameLayoutс a в ImageViewкачестве первого дочернего элемента, а затем ваш обычный макет в качестве второго ребенка:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

  <ImageView
        android:id="@+id/background_image_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop"
        android:src="@drawable/your_drawable"/>

  <LinearLayout
        android:id="@+id/your_actual_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

  </LinearLayout>

</FrameLayout>
Адам Джонс
источник
0

Ключ состоит в том, чтобы установить возможность рисования как изображение кнопки, а не как фон. Как это:

rb.setButtonDrawable(R.drawable.whatever_drawable);
Хосе Л. Угиа
источник
Это метод CompoundButton, но не Button.
arlomedia
0

Можно использовать обычный ImageView в своем xml и сделать его интерактивным (android: clickable = "true")? Вам нужно только использовать в качестве src изображение, имеющее форму кнопки, то есть закругленные углы.

Григореас П.
источник