Фоновые рисунки определяют размер представления

Для ясности этот вопрос был значительно отредактирован.

Скажем, у меня есть .png ресурс 100x100px:
enter image description here

Я хочу использовать это изображение в качестве фона для моего TextView s, размер которого определяется его содержимым, которое является переменной во время выполнения. В частности, я хочу, чтобы это изображение было разбито, когда размер TextView больше 100x100px, и я хочу, чтобы его обрезали, когда TextView меньше 100x100px.

Последний кажется сложным.

Пример кода

У меня есть ресурс bg_tile.xml:

<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
    android:src="@drawable/bg"
    android:tileMode="repeat" />

Мой файл макета:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="8dp"
        android:background="@drawable/bg_tile"
        android:text="Short text"
        android:textSize="20sp" />

    <TextView android:layout_margin="8dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/bg_tile"
        android:text="Long text long text long text long text long text long text long text long text long textlong text long text long text long text long text long text long text long text long textlong text long text long text long text long text long text long text long text long text "
        android:textSize="20sp" />

</LinearLayout>

Что происходит

Вот скриншот результата этого кода, и одно из того, что я ожидаю/чего хочу: enter image description here

Как вы можете видеть, плитка работает, а нижняя плитка обрезается. Однако, когда TextView меньше фона, TextView принимает размер фона.

Предлагаемые решения

  • android:gravity="clip_vertical|clip_horizontal" - Это не работает, даже без tilemode.
  • Использовать match_parent как параметры макета - Не вариант.
  • Настройка фиксированной высоты. Невозможно указать, сколько времени будет содержать содержимое TextView и с его размером.

Как я могу достичь своей цели?

Ответы

Ответ 1

Я не пробовал это сам, но вы могли бы попробовать эту идею/взломать/обход:

Минимальная высота/ширина представления (TextView) определяется его фоновой способностью (среди прочего). Он использует фон Drawable getMinimumHeight() и getMinimumWidth() для определения минимальной высоты и ширины представления.

Похоже, вы хотите, чтобы минимальная высота и ширина представления были равны 0 (исключая заполнение), а ширина/высота представления должны основываться только на содержимом представления (в вашем случае текст TextView).

Попробуйте это в onCreate своей деятельности или onCreateView вашего фрагмента, где вы ухватите TextView, который вы пытаетесь "исправить". Позвольте называть это TextView 'tv':

TextView tv; 
...
...
tv = (TextView)...findViewById(...);
....

// Swap the 'standard' bitmap background with one that has no minimum width/height.
BitmapDrawable background = (BitmapDrawable)tv.getBackground(); // assuming you have bg_tile as background.
BitmapDrawable newBackground = new BitmapDrawable(background.getBitmap) {
    @Override
    public int getMinimumWidth() {
        return 0;
    }

    @Override
    public int getMinimumHeight() {
        return 0;
    }
};
newBackground.setTileModeXY(background.getTileModeX(), background.getTileModeY());
tv.setBackgroundDrawable(newBackground);
...
...

Ответ 2

Этот метод работает для меня.

  1. очистить фон TextView
  2. (в postRunnable) сохранить ширину и высоту TextView
  3. (в postRunnable) установить новый фон для TextView
  4. (в postRunnable) установить ширину и высоту для TextView

пример

public void setTextViewBg(final TextView textView, final Drawable newBgDrawable) {
    textView.setBackground(null);
    textView.post(new Runnable() {
        @Override
        public void run() {
            int width = textView.getWidth();
            int height = textView.getHeight();
            textView.setBackgroundDrawable(newBgDrawable);
            LinearLayout.LayoutParams layoutParams = (LayoutParams) textView.getLayoutParams();
            layoutParams.width = width;
            layoutParams.height = height;
        }
    });
}

Надеюсь, это поможет ~

Ответ 3

Я предполагаю, что ваша проблема здесь:

Android: layout_width = "wrap_content" андроид: layout_height = "wrap_content"

Он устанавливает ширину для обертывания содержимого, а контент включает фоновое изображение. Я не уверен, каков контекст вашего представления, но если вы можете просто установить высоту из кода или из xml файла, ваша проблема должна исчезнуть. Вы также можете добавить android: scaleType = "centerCrop" или centerInside, как сказал Houcine, если фон по-прежнему не отображается по вашему вкусу.

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

Ответ 4

Вы всегда можете использовать:

android:layout_width="match_parent"
android:layout_height="match_parent"

Ответ 5

Попробуйте следующее:

<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
    android:src="@drawable/bg_light"
    android:tileMode="repeat"
    android:gravity="clip_vertical|clip_horizontal" />

Дополнительные параметры: http://developer.android.com/guide/topics/resources/drawable-resource.html#Bitmap

Изменить: я прочитал документацию, это не будет работать с набором tileMode:

android:tileMode

Keyword. Defines the tile mode. When the tile mode is enabled, the bitmap is repeated. Gravity is ignored when the tile mode is enabled.

Если вы знаете размер Представлений раньше времени и знаете, что он будет клип, у вас может быть один Bitmap-XML для tileMode и другой для гравитации, а затем использовать соответствующий. Не идеально, к сожалению.