Куди піде відступ, коли встановлюється фон, який можна малювати?


86

У мене є ця проблема в моїх EditTextі Buttonподаннях, де я маю приємну підкладку, щоб вони відступили від тексту, але коли я змінюю фон за допомогою setBackgroundDrawableабо setBackgroundResourceте, що відступ буде втрачено назавжди.


2
Цю проблему було виправлено в Android 4.4 KitKat
Володимир

2
На моєму Nexus 5 з 4.4.3 ця проблема все ще трапляється.
Bianca Daniciuc

1
Я вважаю, що це було виправлено лише в Lollipop (5.0)
Авів Бен-Шабат

У мене була та ж проблема з a, TextViewі прийняте нижче рішення також працювало для такого типу подання.
Stonz2,

Виник також проблема з TextViewAPI 28 (Android 9). Схоже, це ніколи не було виправлено.
Sdghasemi

Відповіді:


97

Я виявив, що додав патч 9 як фоновий ресурс, який скинув відступ - хоча цікаво, що якщо я додав кольорове зображення або зображення, яке не містить 9, цього не сталося. Рішенням було зберегти значення заповнення до того, як додається фон, а потім встановити їх знову.

private EditText value = (EditText) findViewById(R.id.value);

int pL = value.getPaddingLeft();
int pT = value.getPaddingTop();
int pR = value.getPaddingRight();
int pB = value.getPaddingBottom();

value.setBackgroundResource(R.drawable.bkg);
value.setPadding(pL, pT, pR, pB);

Для тих, хто стикається з деякими проблемами, використовуючи цей підхід, обов’язково телефонуйте getPadding ... ДО виклику setBackgroundResource ().
Chris.Zou

Здається, таким чином не можна було б утримати прокладку, що малюється?
Thuy Trinh

4
Я хотів би зазначити, що вам не потрібно робити це вище API 19 (Kitkat), оскільки Google вирішив цю помилку.
ywwynm

@ywwynm вище або дорівнює kitkat?
HendraWD

Добре, я спробував сам, нам не потрібно використовувати його для API 19 (Kitkat) або вище (> = Kitkat)
HendraWD

14

Мені вдалося обернути елемент всередині іншого макета, в даному випадку a FrameLayout. Це дозволило мені змінити фон на, FrameLayoutне руйнуючи відступ, який є на вміщеному RelativeLayout.

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:id="@+id/commentCell"
          android:layout_width="fill_parent"
          android:layout_height="wrap_content"
          android:background="@drawable/comment_cell_bg_single" >

    <RelativeLayout android:layout_width="fill_parent"
                    android:layout_height="fill_parent"
                    android:padding="20dp" >

    <ImageView android:id="@+id/sourcePic"
               android:layout_height="75dp"
               android:layout_width="75dp"
               android:padding="5dp"
               android:background="@drawable/photoframe" 
     />
...

Інший варіант - встановити його програмно після встановлення фону, Drawableяк було запропоновано вище. Просто не забудьте обчислити пікселі, щоб скорегувати роздільну здатність пристрою.


12

У мене була проблема в TextView, тому я підкласикував TextView і зробив метод Override TextView.setBackgroundResource(int resid)методу. Подобається це:

@Override
public void setBackgroundResource(int resid) {
    int pl = getPaddingLeft();
    int pt = getPaddingTop();
    int pr = getPaddingRight();
    int pb = getPaddingBottom();

    super.setBackgroundResource(resid);

    this.setPadding(pl, pt, pr, pb);
}

Таким чином, він отримує заповнення елемента до того, як він задає ресурс, але насправді не плутається з початковою функціональністю методу, крім збереження відступу.


9

Ще не перевірив це дуже ретельно, але цей метод може бути корисним:

    /**
 * Sets the background for a view while preserving its current padding. If the background drawable
 * has its own padding, that padding will be added to the current padding.
 * 
 * @param view View to receive the new background.
 * @param backgroundDrawable Drawable to set as new background.
 */
public static void setBackgroundAndKeepPadding(View view, Drawable backgroundDrawable) {
    Rect drawablePadding = new Rect();
    backgroundDrawable.getPadding(drawablePadding);
    int top = view.getPaddingTop() + drawablePadding.top;
    int left = view.getPaddingLeft() + drawablePadding.left;
    int right = view.getPaddingRight() + drawablePadding.right;
    int bottom = view.getPaddingBottom() + drawablePadding.bottom;

    view.setBackgroundDrawable(backgroundDrawable);
    view.setPadding(left, top, right, bottom);
}

Використовуйте це замість view.setBackgroundDrawable (Drawable).


3
Якщо подання вже має відступ на якійсь стороні, після декількох викликів цієї функції фонове зображення переміщується в бік, оскільки ви збільшуєте відступ перегляду з попереднім значенням
iBog

Так, якщо набивання буде змінюватися кілька разів, ви хочете застосувати інший підхід. Можливо, відстежуйте оригінальну прокладку порівняно з прокладкою, що малюється.
cottonBallPaws

2

Відповідь порівнянної версії cottonBallPaws

/** 
  * Sets the background for a view while preserving its current     padding. If the background drawable 
  * has its own padding, that padding will be added to the current padding. 
 *  
 * @param view View to receive the new background. 
 * @param backgroundDrawable Drawable to set as new background. 
 */ 
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
@SuppressWarnings("deprecation")
public static void setBackgroundAndKeepPadding(View view, Drawable backgroundDrawable) {
    Rect drawablePadding = new Rect();
    backgroundDrawable.getPadding(drawablePadding);
    int top = view.getPaddingTop() + drawablePadding.top;
    int left = view.getPaddingLeft() + drawablePadding.left;
    int right = view.getPaddingRight() + drawablePadding.right;
    int bottom = view.getPaddingBottom() + drawablePadding.bottom;

    int sdk = android.os.Build.VERSION.SDK_INT;
    if(sdk < android.os.Build.VERSION_CODES.JELLY_BEAN) {
        view.setBackgroundDrawable(backgroundDrawable);
    } else {
        view.setBackground(backgroundDrawable);
    }
    view.setPadding(left, top, right, bottom);
}

1

Ви можете додати трохи відступів, використовуючи 9-патч-зображення та визначаючи область вмісту у малюваному. Перевір це

Ви також можете встановити відступ у своєму макеті з xml або програмно

теги для заповнення xml

android:padding
android:paddingLeft
android:paddingRight
android:paddingTop
android:paddingBottom

Ви можете спробувати встановити відступ вручну з коду після виклику setBackgroundDrawable, зателефонувавши setPadding у поданнях EditText або Button


Я визначив відступ для EditText і Button у XML, і це чудово показує, поки я не зміню Drawable, тоді я втрачаю відступ.
Dandre Allison

Це може змінюватися залежно від зміни областей вмісту між вашими попередніми та новими малюнками. Спробували збільшити відступ і подивитися, чи дає воно якесь заповнення чи ні.
achie

1
Добре, вибачте, я повинен був повністю прочитати ваше запитання. Оскільки ви змінюєте фон, який можна малювати, можливо, він видаляє відступ. Я не впевнений, що це так. Але якщо це так , ви можете спробувати встановити відступи вручну з коду після того, як НУ викликати setBackgroundDrawable по телефону setPadding на ваше EditText або Кнопку вибору режиму перегляду
achie

1

Для звичайного шукача,

просто додайте setPadding після setBackgroudDrawable. Коли ви змінюєте свій малювальний, вам доведеться зателефонувати setPadding знову.

Люблю:

view.setBackgroundDrawable(backgroundDrawable);
view.setPadding(x, x, x, x);

Найчистіший спосіб - це визначити відступи всередині xml-drawable, який вказує на файл-малюнок-малюнок

Грейдинги


1

Моє рішення полягало в розширенні подання (у моєму випадку - EditText ) і перевизначенні setBackgroundDrawable()та setBackgroundResource()методах:

// Stores padding to avoid padding removed on background change issue
public void storePadding(){
    mPaddingLeft = getPaddingLeft();
    mPaddingBottom = getPaddingTop();
    mPaddingRight = getPaddingRight();
    mPaddingTop = getPaddingBottom();
}

// Restores padding to avoid padding removed on background change issue
private void restorePadding() {
    this.setPadding(mPaddingLeft, mPaddingTop, mPaddingRight, mPaddingBottom);
}

@Override
public void setBackgroundResource(@DrawableRes int resId) {
    storePadding();
    super.setBackgroundResource(resId);
    restorePadding();
}

@Override
public void setBackgroundDrawable(Drawable background) {
    storePadding();
    super.setBackgroundDrawable(background);
    restorePadding();
}

1

Поєднуючи всі рішення, я написав одне в Котліні:

fun View.setViewBackgroundWithoutResettingPadding(@DrawableRes backgroundResId: Int) {
    val paddingBottom = this.paddingBottom
    val paddingStart = ViewCompat.getPaddingStart(this)
    val paddingEnd = ViewCompat.getPaddingEnd(this)
    val paddingTop = this.paddingTop
    setBackgroundResource(backgroundResId)
    ViewCompat.setPaddingRelative(this, paddingStart, paddingTop, paddingEnd, paddingBottom)
}

fun View.setViewBackgroundWithoutResettingPadding(background: Drawable?) {
    val paddingBottom = this.paddingBottom
    val paddingStart = ViewCompat.getPaddingStart(this)
    val paddingEnd = ViewCompat.getPaddingEnd(this)
    val paddingTop = this.paddingTop
    ViewCompat.setBackground(this, background)
    ViewCompat.setPaddingRelative(this, paddingStart, paddingTop, paddingEnd, paddingBottom)
}

1

Просто пояснити, що відбувається:

Це насправді особливість. Макети, які можна використовувати як фони, можуть визначати відступ таким чином:

<layer-list
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:paddingRight="8dp"
    >
    ...
</layer-list>

Це заповнення буде встановлено разом із новим фоном, який можна малювати. Коли відступів немає, значення за замовчуванням - 0.

Більше інформації з електронного листа, написаного Роменом Гаєм: https://www.mail-archive.com/android-developers@googlegroups.com/msg09595.html



0

Більшість відповідей є правильними, але вони повинні правильно обробляти налаштування фону.

Спочатку отримайте відступ вашого подання

//Here my view has the same padding in all directions so I need to get just 1 padding
int padding = myView.getPaddingTop();

Потім встановіть фон

//If your are supporting lower OS versions make sure to verify the version
if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.JELLY_BEAN) {
    //getDrawable was deprecated so use ContextCompat                            
    myView.setBackgroundDrawable(ContextCompat.getDrawable(context, R.drawable.bg_accent_underlined_white));
} else {
    myView.setBackground(ContextCompat.getDrawable(context, R.drawable.bg_accent_underlined_white));
}

Потім встановіть відступ, який вигляд мав до зміни фону

myView.setPadding(padding, padding, padding, padding);

0

Я знайшов інше рішення. Я стикався з подібною проблемою з кнопками. Зрештою, я додав:

android:scaleX= "0.85"
android:scaleY= "0.85"

це спрацювало для мене. Заповнення за замовчуванням майже однакове.


0

У моєму випадку у мене була можливість малювання, і я був настільки дурний, що не бачив, що для відступів у xml було встановлено значення 0.


-1

Ось вдосконалена версія cottonBallPaws 'setBackgroundAndKeepPadding. Це підтримує відступ, навіть якщо ви викликаєте метод кілька разів:

/**
 * Sets the background for a view while preserving its current padding. If the background drawable
 * has its own padding, that padding will be added to the current padding.
 */
public static void setBackgroundAndKeepPadding(View view, Drawable backgroundDrawable) {

    Rect drawablePadding = new Rect();
    backgroundDrawable.getPadding(drawablePadding);

    // Add background padding to view padding and subtract any previous background padding
    Rect prevBackgroundPadding = (Rect) view.getTag(R.id.prev_background_padding);
    int left = view.getPaddingLeft() + drawablePadding.left -
            (prevBackgroundPadding == null ? 0 : prevBackgroundPadding.left);
    int top = view.getPaddingTop() + drawablePadding.top -
            (prevBackgroundPadding == null ? 0 : prevBackgroundPadding.top);
    int right = view.getPaddingRight() + drawablePadding.right -
            (prevBackgroundPadding == null ? 0 : prevBackgroundPadding.right);
    int bottom = view.getPaddingBottom() + drawablePadding.bottom -
            (prevBackgroundPadding == null ? 0 : prevBackgroundPadding.bottom);
    view.setTag(R.id.prev_background_padding, drawablePadding);

    view.setBackgroundDrawable(backgroundDrawable);
    view.setPadding(left, top, right, bottom);
}

Вам потрібно визначити ідентифікатор ресурсу за допомогою values ​​/ ids.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <item name="prev_background_padding" type="id"/>
</resources>

-1

Я використовую цей досить простий обхідний шлях, який я визначаю accentColorв моєму, style.xmlяк показано нижче

<item name="colorAccent">#0288D1</item>

а потім я використовую один із наведених нижче стилів у своїх Buttonтегах

style="@style/Base.Widget.AppCompat.Button.Colored"
style="@style/Base.Widget.AppCompat.Button.Small"

наприклад :

<Button
    android:id="@+id/btnLink"
    style="@style/Base.Widget.AppCompat.Button.Colored"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@id/tvDescription"
    android:textColor="@color/textColorPrimary"
    android:text="Visit Website" />

<Button
    android:id="@+id/btnSave"
    style="@style/Base.Widget.AppCompat.Button.Small"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@id/tvDescription"
    android:layout_toRightOf="@id/btnLink"
    android:textColor="@color/textColorPrimaryInverse"
    android:text="Save" />

Це не пов'язано з питанням.
Miha_x64
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.