Arka plan Drawable'ı ayarlarken dolgu nereye gitti?


88

Metinden uzaklaşmaları için güzel bir dolguya sahip olduğum, ancak arka planı değiştirdiğimde veya bu dolgu sonsuza kadar kaybolduğunda bu sorunu EditTextve Buttongörüşlerimde var .setBackgroundDrawablesetBackgroundResource


2
Bu sorun, Android 4.4 KitKat
Vladimir

2
4.4.3 ile Nexus 5'imde bu sorun hala devam ediyor.
Bianca Daniciuc

1
Sadece Lollipop'ta (5.0) düzeltildiğine inanıyorum
Aviv Ben Shabat

A ile aynı sorunu yaşıyordum TextViewve aşağıdaki kabul edilen çözüm de bu tür görünüm için çalıştı.
Stonz2

Bir meseleyi sahip TextViewkuyunun olarak API 28 (Android 9). Görünüşe göre hiç tamir edilmemiş.
Sdghasemi

Yanıtlar:


99

Bulduğum şey, arka plan kaynağı olarak bir 9 yaması ekleyerek dolguyu sıfırlamaktı - ilginç bir şekilde bir renk veya 9 olmayan yama görüntüsü eklersem, eklemedi. Çözüm, arka plan eklenmeden önce dolgu değerlerini kaydetmek ve ardından bunları yeniden ayarlamaktı.

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);

Bu yaklaşımı kullanırken bazı sorunlarla karşılaşan herkes için setBackgroundResource () 'u çağırmadan ÖNCE getPadding ...' i çağırmayı unutmayın.
Chris.Zou

Görünüşe göre bu şekilde çekilebilir dolgu kalmayacak mı?
Thuy Trinh

4
Google bu hatayı çözdüğü için API 19'un (Kitkat) üzerinde bunu yapmamanız gerektiğini belirtmek isterim.
ywwynm

@ywwynm yukarıda mı yoksa kitkat'a eşit mi?
HendraWD

Tamam, kendim denedim, API 19 (Kitkat) veya üstü (> =
Kitkat

14

Öğeyi başka bir düzenin içine, bu örnekte a FrameLayout. Bu FrameLayout, içerdiği dolguyu bozmadan arka planı değiştirmemi sağladı 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" 
     />
...

Diğer seçenek, arka planı Drawableyukarıda önerildiği gibi ayarladıktan sonra programlı olarak ayarlamaktır . Cihazın çözünürlüğünü düzeltmek için pikselleri hesapladığınızdan emin olun.


12

Bu sorunu bir TextView'da yaşadım, bu yüzden TextView'ı alt sınıflandırdım ve yöntemin Override yöntemini yaptım TextView.setBackgroundResource(int resid). Bunun gibi:

@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);
}

Bu şekilde, kaynağı ayarlamadan önce öğenin dolgusunu alır, ancak dolguyu korumaktan başka, yöntemin orijinal işlevselliği ile gerçekten uğraşmaz.


9

Bu süper cihazı kapsamlı bir şekilde test etmedim, ancak bu yöntem işe yarayabilir:

    /**
 * 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) yerine bunu kullanın.


3
Görünümün bir tarafında zaten dolgu varsa, bu işlevi birden çok kez çağırdıktan sonra, arka plan görüntüsü yana doğru hareket eder, çünkü önceki değerle görünüm dolgusunu
artırırsınız

Evet, dolgu birkaç kez değiştirilecekse, farklı bir yaklaşım benimsemek istersiniz. Muhtemelen orijinal dolguyu ve çekilebilir dolguyu takip edin.
cottonBallPaws

2

CottonBallPaws'in cevabının geriye dönük uyumlu versiyonu

/** 
  * 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 yama görüntülerini kullanarak ve çekilebilir dosyadaki içerik alanını tanımlayarak biraz dolgu verebilirsiniz. Şuna göz at

Düzeninizdeki dolguyu xml'den veya programlı olarak da ayarlayabilirsiniz.

xml dolgu etiketleri

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

SetBackgroundDrawable'ı çağırdıktan sonra EditText veya Düğme Görünümlerinizde setPadding'i çağırarak doldurmayı koddan manuel olarak ayarlamayı deneyebilirsiniz.


XML'de EditText ve Button için tanımladığım dolgu var ve Drawable'ı değiştirene kadar harika görünüyor, sonra dolguyu kaybediyorum.
Dandre Allison

Önceki ve yeni çekilebilir öğeleriniz arasındaki içerik alanlarındaki değişikliğe bağlı olarak değişebilir. Dolguyu artırmayı denediniz mi ve herhangi bir dolgu verip vermediğini gördünüz mü?
achie

1
Tamam, üzgünüm sorunuzu tamamen okumalıydım. Arka plan resmini değiştirdiğiniz için dolguyu kaldırıyor olabilir. Durumun bu olduğundan emin değilim. Eğer durum buysa Ama ou sizin EditText veya Düğme Views'daki setPadding arayarak setBackgroundDrawable çağırdıktan sonra kodundan manuel dolguyu ayarı deneyebilirsiniz
achie

1

Genel arama yapan için,

setBackgroudDrawable'dan sonra setPadding eklemeniz yeterlidir. Çekilebilir ürününüzü değiştirdiğinizde setPadding'i tekrar aramanız gerekir.

Sevmek:

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

En temiz yol, dolgularınızı çizilebilir görüntü dosyasına işaret eden bir xml-drawable içinde tanımlamaktır.

Greatings


1

Çözümüm , görünümü genişletmek (benim durumumda bir EditText ) ve geçersiz kılmak setBackgroundDrawable()ve setBackgroundResource()yöntemlerdi:

// 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

Hepsinin çözümlerini birleştirerek Kotlin'e bir tane yazdım:

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

Sadece neler olduğunu açıklamak için:

Aslında bir özellik. Arka plan olarak kullanabileceğiniz düzen çekmeceleri bir dolguyu şu şekilde tanımlayabilir:

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

Bu dolgu, yeni çekilebilir arka planla birlikte ayarlanacaktır. Dolgu olmadığında varsayılan değer 0'dır.

Romain Guy tarafından yazılan bir e-postadan daha fazla bilgi: https://www.mail-archive.com/android-developers@googlegroups.com/msg09595.html


0

Bu derleme 'com.android.support:appcompat-v7:22.1.0' gibi android stüdyosunda lib'i v7: 22.1.0 olarak değiştirin.


0

Cevapların çoğu doğrudur, ancak arka plan ayarını doğru şekilde işlemelidir.

Önce görünümünüzün dolgusunu alın

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

Ardından arka planı ayarlayın

//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));
}

Ardından, görünümün arka plan değişikliğinden önce sahip olduğu dolguyu ayarlayın

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

0

Başka bir çözüm buldum. Buttons ile benzer bir sorunla karşı karşıyaydım. Sonunda şunu ekledim:

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

benim için çalıştı. Varsayılan dolgu neredeyse aynıdır.


0

Benim durumumda bir çekmecem vardı ve çok aptaldım, dolguların xml'de 0'a ayarlandığını görmedim.


-1

Burada, cottonBallPaws'ın setBackgroundAndKeepPadding'in geliştirilmiş bir sürümü. Bu, yöntemi birden çok kez çağırsanız bile dolguyu korur:

/**
 * 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 aracılığıyla bir kaynak kimliği tanımlamanız gerekir:

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

-1

Bu oldukça kolay bir tanımlamak için geçici çözüm kullanmak accentColorbenim, style.xmlaşağıda gibi

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

ve sonra Buttonetiketlerimde aşağıdaki stillerden birini kullanıyorum

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

Örneğin :

<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" />

Bu soruyla ilgili değil.
Miha_x64
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.