배경 Drawable을 설정할 때 패딩은 어디에 있습니까?


86

나는 내 EditTextButton뷰 에이 문제 가 있는데, 텍스트에서 멀리 떨어져있는 좋은 패딩이 있지만 배경을 변경 setBackgroundDrawable하거나 setBackgroundResource패딩이 영원히 손실됩니다.


2
이 문제는 Android 4.4 KitKat
Vladimir

2
4.4.3이 설치된 Nexus 5에서이 문제가 여전히 발생합니다.
Bianca Daniciuc 2015

1
나는 롤리팝 만 (5.0) 고정 된 생각
아비브 Shabat

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

이 접근 방식을 사용하는 데 문제가있는 사람은 setBackgroundResource ()를 호출하기 전에 getPadding ...을 호출해야합니다.
Chris.Zou

이런 식으로 드로어 블 패딩을 유지하지 않을 것 같습니까?
Thuy Trinh 2014

4
Google이이 버그를 해결 했으므로 API 19 (Kitkat) 위에서이 작업을 수행하지 않아도된다는 점을 말씀 드리고 싶습니다.
ywwynm

@ywwynm 이상이거나 kitkat과 같습니까?
HendraWD

OK, 나는 그것을 자신을 시도, 우리는 API 19 (Kitkat으로) 이상 (> = Kitkat으로) 그것을 사용할 필요가 없습니다
HendraWD

14

요소를 다른 레이아웃 (이 경우 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 2013

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

EditText 또는 Button 뷰에서 setPadding을 호출하여 setBackgroundDrawable을 호출 한 후 코드에서 수동으로 패딩을 설정할 수 있습니다.


XML의 EditText 및 Button에 대해 패딩이 정의되어 있으며 Drawable을 변경할 때까지 훌륭하게 표시되며 패딩이 손실됩니다.
Dandre Allison 2012

이전 드로어 블과 새 드로어 블 간의 콘텐츠 영역 변경에 따라 변경 될 수 있습니다. 패딩을 늘리고 패딩을 제공하는지 확인하십시오.
Achie

1
네 질문을 완전히 읽었어야했는데 죄송합니다. backgrounddrawable을 변경하기 때문에 패딩이 제거 될 수 있습니다. 나는 그것이 사실인지 잘 모르겠습니다. 그러나이 경우 EditText 또는 Button 뷰에서 setPadding을 호출하여 setBackgroundDrawable을 호출 한 후 코드에서 패딩을 수동으로 설정해 볼 수 있습니다.
achie

1

일반 검색 자에게는

setBackgroudDrawable 뒤에 setPadding을 추가하기 만하면됩니다. 드로어 블을 변경할 때 setPadding을 다시 호출해야합니다.

처럼:

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

가장 깨끗한 방법은 drawable-image-file을 가리키는 xml-drawable 내부에 패딩을 정의하는 것입니다.

Greatings


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

모든 솔루션을 결합하여 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)
}

1

무슨 일이 일어나고 있는지 설명하기 위해 :

실제로 기능입니다. 배경으로 사용할 수있는 레이아웃 드로어 블은 다음과 같이 패딩을 정의 할 수 있습니다.

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

이 패딩은 새로운 드로어 블 배경과 함께 설정됩니다. 패딩이없는 경우 기본값은 0입니다.

Romain Guy가 작성한 이메일의 추가 정보 : https://www.mail-archive.com/android-developers@googlegroups.com/msg09595.html


0

이 컴파일 'com.android.support:appcompat-v7:22.1.0'과 같이 android studio에서 lib를 v7 : 22.1.0으로 변경하십시오.


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을 통해 리소스 ID를 정의해야합니다.

<?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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.