I have this issue on my EditText
and Button
views, where I have a nice padding for them to space away from the text, but when I change the background with setBackgroundDrawable
or setBackgroundResource
that padding is lost forever.

- 5,975
- 5
- 42
- 56
-
2This issue was fixed in Android 4.4 KitKat – Vladimir Apr 18 '15 at 14:52
-
2On my Nexus 5 with 4.4.3 this issue is still happening. – Bianca Daniciuc Jul 24 '15 at 09:27
-
1I believe it was fixed only in Lollipop (5.0) – Aviv Ben Shabat Apr 13 '16 at 11:33
-
I was having the same problem with a `TextView` and the accepted solution below also worked for that type of view. – Stonz2 Apr 21 '16 at 16:06
-
1Having the issue on a `TextView` on API 28 (Android 9) as well. Looks like it was never fixed. – Sdghasemi Nov 05 '19 at 07:57
17 Answers
What I found was adding a 9 patch as a background resource reset the padding - although interestingly if I added a color, or non-9 patch image, it didn't. The solution was to save the padding values before the background gets added, then set them again afterwards.
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);

- 15,983
- 17
- 62
- 77
-
For anyone who run into some problems using this approach, be sure to call getPadding... BEFORE call setBackgroundResource(). – Chris.Zou Dec 31 '13 at 03:36
-
-
4I'd like to mention that you have not to do this above API 19(Kitkat) since Google has solved this bug. – ywwynm Aug 13 '15 at 01:03
-
-
OK, i have tried it myself, we don't need to use it for API 19(Kitkat) or higher(>=Kitkat) – HendraWD Oct 03 '16 at 11:03
-
bug is still there? i have my app set to minimum 19 but running the app on 23? – Jono Feb 28 '18 at 16:45
I was able to wrap the element inside another layout, in this case, a FrameLayout
. That enabled me to change the background on the FrameLayout
without destroying the padding, which is on the contained 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"
/>
...
The other option is to set it programmatically after setting the background Drawable
as suggested above. Just make sure to calculate the pixels to correct for the resolution of the device.

- 616
- 7
- 15

- 538
- 5
- 17
I had this problem in a TextView, so I subclassed TextView and made an Override method of the TextView.setBackgroundResource(int resid)
method. Like this:
@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);
}
This way, it gets the padding of the item before it sets the resource, but doesn't actually mess with the original functionality of the method, other than keeping the padding.

- 8,869
- 1
- 29
- 28
Haven't tested this super thoroughly, but this method might be of use:
/**
* 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);
}
Use this instead of view.setBackgroundDrawable(Drawable).

- 21,220
- 37
- 123
- 171
-
3If view already has padding on some side, after calling this function multiple times, background image moves to side, because you increment view padding with previous value – iBog Feb 21 '13 at 12:18
-
Yea if the padding is going to be changed several times you would want to take a different approach. Possibly keep track of the original padding versus the drawable padding. – cottonBallPaws Feb 24 '13 at 17:31
Just to explain what's happening :
It's actually a feature. Layout drawables you might use as backgrounds can define a padding this way :
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android"
android:paddingRight="8dp"
>
...
</layer-list>
This padding will be set along with the new drawable background. When there's no padding, the default value is 0.
More info from an email written by Romain Guy: https://www.mail-archive.com/android-developers@googlegroups.com/msg09595.html

- 1,275
- 16
- 20
Backward compatable version of cottonBallPaws's answer
/**
* 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,547
- 1
- 13
- 27
You can give some padding by using 9-patch images and defining the content area in the drawable. Check this
You can also set the padding in your layout from xml or programatically
xml padding tags
android:padding
android:paddingLeft
android:paddingRight
android:paddingTop
android:paddingBottom
You can try setting the padding manually from the code after you call the setBackgroundDrawable by calling setPadding on your EditText or Button Views

- 4,716
- 7
- 45
- 59
-
I have padding defined for the EditText and Button in XML, and it shows great, until I change the Drawable, then I lose the padding. – Dandre Allison Apr 10 '12 at 21:45
-
It may change depending on the change in the content areas between your previous and new drawables. Did you try increasing the padding and see if it is giving any padding or not. – achie Apr 10 '12 at 21:50
-
1Ok sorry I should have read your question completely. Since you are changing the backgrounddrawable, it might be removing the padding. I am not sure that it is the case. But if that is the case you can try setting the padding manually from the code after ou call the setBackgroundDrawable by calling setPadding on your EditText or Button Views – achie Apr 10 '12 at 21:54
For common searcher,
just add setPadding after setBackgroudDrawable. When you change your drawable, you have to call setPadding again.
Like:
view.setBackgroundDrawable(backgroundDrawable);
view.setPadding(x, x, x, x);
The cleanest way is define your paddings inside a xml-drawable which points to the drawable-image-file
Greatings

- 11
- 1
My solution was to extend the view (in my case an EditText) and override setBackgroundDrawable()
and setBackgroundResource()
methods:
// 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();
}

- 2,742
- 2
- 19
- 36
Combining the solutions of all, I wrote one in Kotlin:
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)
}

- 114,585
- 152
- 739
- 1,270
just change lib to v7:22.1.0 in android studio like this compile 'com.android.support:appcompat-v7:22.1.0'

- 1
- 1
Most of answers are correct but should handle the background setting correctly.
First get the padding of your view
//Here my view has the same padding in all directions so I need to get just 1 padding
int padding = myView.getPaddingTop();
Then set the background
//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));
}
Then set the padding the view had before the background change
myView.setPadding(padding, padding, padding, padding);

- 9,887
- 3
- 45
- 59
I found another solution. I was facing the similar problem with Buttons. Eventually, i added:
android:scaleX= "0.85"
android:scaleY= "0.85"
it worked for me. The default padding is almost the same.

- 588
- 4
- 10
In my case I had a drawable and was so stupid I didn't see the paddings were all set to 0 in the xml.

- 670
- 8
- 20
maybe it will be relevant for someone
small hack using drawable in selector doesn't remove padding
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/anything" />
</selector>

- 381
- 2
- 10
Here an improved version of cottonBallPaws' setBackgroundAndKeepPadding. This maintains the padding even if you call the method multiple times:
/**
* 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);
}
You need to define a resource id via values/ids.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="prev_background_padding" type="id"/>
</resources>

- 1,188
- 14
- 12
I use this pretty easy workaround I define a accentColor
in my style.xml
like below
<item name="colorAccent">#0288D1</item>
and then I use the either of following styles in my Button
tags
style="@style/Base.Widget.AppCompat.Button.Colored"
style="@style/Base.Widget.AppCompat.Button.Small"
for Example :
<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" />

- 1,910
- 2
- 28
- 33