У меня есть эта проблема в моих представлениях EditText
и Button
, где у меня есть приятное дополнение, чтобы они были вдали от текста, но когда я меняю фон на setBackgroundDrawable
или setBackgroundResource
, это дополнение потерянный навсегда.
Куда идет отступы, когда устанавливаете фон Drawable?
Ответ 1
Я обнаружил, что добавление 9 патчей в качестве фонового ресурса reset дополнения - хотя интересно, если бы я добавил цвет или не-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);
Ответ 2
Мне удалось обернуть элемент внутри другого макета, в данном случае, 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
, как было предложено выше. Просто убедитесь, что подсчитаны пиксели для исправления разрешения устройства.
Ответ 3
У меня была эта проблема в 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);
}
Таким образом, он получает заполнение элемента до того, как он устанавливает ресурс, но на самом деле не путается с исходными функциональными возможностями метода, кроме сохранения отступов.
Ответ 4
Не тестировали это супер тщательно, но этот метод может быть полезным:
/**
* 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).
Ответ 5
Обратная совместимость версии 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);
}
Ответ 6
Для обычного искателя
просто добавьте setPadding после setBackgroudDrawable. Когда вы меняете свой вариант, вам нужно снова вызвать setPadding.
Как
view.setBackgroundDrawable(backgroundDrawable);
view.setPadding(x, x, x, x);
Самый чистый способ - определить ваши paddings внутри xml-drawable, который указывает на файл drawable-image-file
ПОЗДРАВЛЕНИЯ
Ответ 7
Мое решение состояло в том, чтобы расширить представление (в моем случае 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();
}
Ответ 8
Вы можете дать некоторые дополнения, используя 9-патч-изображения и определяя область содержимого в drawable. Проверьте это
Вы также можете установить отступы в макете из xml или программно
xml теги прокладки
android:padding
android:paddingLeft
android:paddingRight
android:paddingTop
android:paddingBottom
Вы можете попытаться настроить прописку вручную из кода после вызова setBackgroundDrawable, вызвав setPadding в EditText или Button Views
Ответ 9
просто измените lib на v7: 22.1.0 в студии android, как это compile 'com.android.support:appcompat-v7:22.1.0'
Ответ 10
Большинство ответов верны, но они должны правильно регулировать фон.
Сначала получите дополнение вашего представления
//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);
Ответ 11
Я нашел другое решение. Я столкнулся с аналогичной проблемой с кнопками. В конце концов, я добавил:
android:scaleX= "0.85"
android:scaleY= "0.85"
это сработало для меня. Отступ по умолчанию почти тот же.
Ответ 12
Объединив решения всех, я написал одно в Котлине:
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)
}
Ответ 13
Просто чтобы объяснить, что происходит:
Это на самом деле особенность. Рисунки макетов, которые вы можете использовать в качестве фона, могут определять заполнение следующим образом:
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android"
android:paddingRight="8dp"
>
...
</layer-list>
Этот отступ будет установлен вместе с новым рисованным фоном. Если отступа нет, значение по умолчанию равно 0.
Больше информации из письма, написанного Romain Guy:https://www.mail-archive.com/[email protected]/msg09595.html
Ответ 14
Здесь представлена улучшенная версия setBackgroundAndKeepPadding из batBallPaws. Это поддерживает добавление, даже если вы вызываете метод несколько раз:
/**
* 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);
}
Вам нужно определить идентификатор ресурса с помощью значений /ids.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="prev_background_padding" type="id"/>
</resources>
Ответ 15
Я использую это довольно легкое обходное решение. Я определяю 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" />