Eu tenho esse problema nas visualizações EditText
e Button
, onde tenho um bom preenchimento para eles se afastarem do texto, mas quando eu mudo o plano de fundo com setBackgroundDrawable
ou setBackgroundResource
esse preenchimento é perdido para sempre.
86
TextView
e a solução aceita abaixo também funcionou para esse tipo de visão.TextView
Também tenho o problema em um API 28 (Android 9). Parece que nunca foi corrigido.Respostas:
O que eu descobri foi adicionar um patch 9 como recurso de fundo para redefinir o preenchimento - embora, curiosamente, se eu adicionasse uma cor ou imagem de patch diferente de 9, isso não acontecesse. A solução era salvar os valores de preenchimento antes que o fundo fosse adicionado e, em seguida, configurá-los novamente.
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);
fonte
Consegui envolver o elemento dentro de outro layout, neste caso, a
FrameLayout
. Isso me permitiu alterar o fundo doFrameLayout
sem destruir o preenchimento, que está no contidoRelativeLayout
.<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" /> ...
A outra opção é defini-lo programaticamente após definir o plano de fundo
Drawable
como sugerido acima. Apenas certifique-se de calcular os pixels para corrigir a resolução do dispositivo.fonte
Eu tive esse problema em um TextView, então criei uma subclasse de TextView e criei um método Override do
TextView.setBackgroundResource(int resid)
método. Como isso:@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); }
Dessa forma, ele obtém o preenchimento do item antes de definir o recurso, mas na verdade não mexe com a funcionalidade original do método, exceto manter o preenchimento.
fonte
Não testei muito bem, mas este método pode ser útil:
/** * 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 isso em vez de view.setBackgroundDrawable (Drawable).
fonte
Versão compatível com versões anteriores da resposta do 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); }
fonte
Você pode fornecer algum preenchimento usando imagens de 9 patch e definindo a área de conteúdo no drawable. Verifique isto
Você também pode definir o preenchimento em seu layout de xml ou programaticamente
tags de preenchimento xml
android:padding android:paddingLeft android:paddingRight android:paddingTop android:paddingBottom
Você pode tentar definir o preenchimento manualmente a partir do código depois de chamar setBackgroundDrawable chamando setPadding em seu EditText ou em Visualizações de botão
fonte
Para o pesquisador comum,
basta adicionar setPadding após setBackgroudDrawable. Ao alterar seu drawable, você deve chamar setPadding novamente.
Gostar:
view.setBackgroundDrawable(backgroundDrawable); view.setPadding(x, x, x, x);
A maneira mais limpa é definir seus preenchimentos dentro de um xml-drawable que aponta para o arquivo drawable-image
Greatings
fonte
Minha solução foi estender a vista (no meu caso um EditText ) e override
setBackgroundDrawable()
esetBackgroundResource()
métodos:// 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(); }
fonte
Combinando as soluções de todas, escrevi uma em 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) }
fonte
Só para explicar o que está acontecendo:
Na verdade, é um recurso. Drawables de layout que você pode usar como plano de fundo podem definir um preenchimento desta forma:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" android:paddingRight="8dp" > ... </layer-list>
Esse preenchimento será definido junto com o novo plano de fundo drawable. Quando não há preenchimento, o valor padrão é 0.
Mais informações em um e-mail escrito por Romain Guy: https://www.mail-archive.com/[email protected]/msg09595.html
fonte
apenas altere lib para v7: 22.1.0 no android studio como este compilar 'com.android.support:appcompat-v7:22.1.0'
fonte
A maioria das respostas está correta, mas deve lidar com a configuração de fundo corretamente.
Primeiro obtenha o preenchimento de sua visão
//Here my view has the same padding in all directions so I need to get just 1 padding int padding = myView.getPaddingTop();
Em seguida, defina o fundo
//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)); }
Em seguida, defina o preenchimento que a vista tinha antes da mudança de fundo
myView.setPadding(padding, padding, padding, padding);
fonte
Encontrei outra solução. Eu estava enfrentando um problema semelhante com os botões. Eventualmente, eu adicionei:
android:scaleX= "0.85" android:scaleY= "0.85"
funcionou para mim. O preenchimento padrão é quase o mesmo.
fonte
No meu caso, eu tinha um drawable e era tão estúpido que não vi que os preenchimentos estavam todos configurados para 0 no xml.
fonte
Aqui, uma versão aprimorada do setBackgroundAndKeepPadding do cottonBallPaws. Isso mantém o preenchimento, mesmo se você chamar o método várias vezes:
/** * 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); }
Você precisa definir um id de recurso via values / ids.xml:
<?xml version="1.0" encoding="utf-8"?> <resources> <item name="prev_background_padding" type="id"/> </resources>
fonte
Eu uso esta solução bastante fácil, eu defino um
accentColor
no meustyle.xml
gosto abaixo<item name="colorAccent">#0288D1</item>
e eu uso um dos seguintes estilos em minhas
Button
tagsstyle="@style/Base.Widget.AppCompat.Button.Colored" style="@style/Base.Widget.AppCompat.Button.Small"
por exemplo :
<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" />
fonte