프로그래밍 방식으로 ColorStateList를 작성하는 방법


158

이것을 사용하여 ColorStateList프로그래밍 방식 으로 만들려고합니다 .

ColorStateList stateList = new ColorStateList(states, colors); 

그러나 두 매개 변수가 무엇인지 잘 모르겠습니다.

설명서에 따라 :

public ColorStateList (int[][] states, int[] colors) 

API 레벨 1에 추가됨

상태에서 색상으로 지정된 매핑을 반환하는 ColorStateList를 만듭니다.

누군가 이것을 어떻게 만드는지 설명해 주시겠습니까?

상태에 대한 2 차원 배열의 의미는 무엇입니까?

답변:


343

http://developer.android.com/reference/android/R.attr.html#state_above_anchor를 참조 하십시오사용 가능한 상태 목록은 를 .

비활성화, 초점이 맞지 않거나 확인되지 않은 상태 등의 색상을 설정하려면 상태를 무효화하십시오.

int[][] states = new int[][] {
    new int[] { android.R.attr.state_enabled}, // enabled
    new int[] {-android.R.attr.state_enabled}, // disabled
    new int[] {-android.R.attr.state_checked}, // unchecked
    new int[] { android.R.attr.state_pressed}  // pressed
};

int[] colors = new int[] {
    Color.BLACK,
    Color.RED,
    Color.GREEN,
    Color.BLUE
};

ColorStateList myList = new ColorStateList(states, colors);

45
"반대"상태에 대한 정보를 주셔서 감사합니다!
BVB

이것은 디자인 라이브러리에서 팹의 색상을 변경하는 데 사용할 수 있습니다.
Tapirboy

5
주의 : 여기의 상태 순서가 좋지 않다는 것을 이해하려면 Roger Alien의 답변 (및 첫 번째 주석)을 참조하십시오. "활성화 됨"이 첫 번째이므로 일반적으로 단추가 활성화되어있는 동안 발생하는 다른 상태보다 우선합니다. "활성화"를 마지막에 두는 것이 좋습니다. (또는 "사용 가능"대신 비어 있거나 기본 항목이 마지막입니다.)
ToolmakerSteve

2
상태를 유지하지 않는 버튼 (NOT 토글 / 체크 박스) 수 있습니다에 대한 국가의 기본 목록 {pressed}, {focused}, {-enabled}, {}. 그것은 토글 A가있을 수 있습니다 들어 {checked, pressed}, {pressed}, {checked, focused}, {focused}, {checked}, {-enabled}, {}. 또는 무시가 초점을 맞출 것을 토글 : {checked, pressed}, {pressed}, {checked}, {-enabled}, {}.
ToolmakerSteve

누군가가 그 해결책 중 하나를 시도한다면 selector.xml과 같은 상태에주의하십시오!
Anton Makov

75

첫 번째 차원은 상태 집합의 배열이고 두 번째 차원은 상태 집합 자체입니다. 색상 배열은 각 일치하는 상태 세트의 색상을 나열하므로 색상 배열의 길이는 상태 배열의 첫 번째 차원과 일치해야합니다 (또는 상태를 "사용"하면 충돌 함). 여기와 예 :

ColorStateList myColorStateList = new ColorStateList(
                        new int[][]{
                                new int[]{android.R.attr.state_pressed}, //1
                                new int[]{android.R.attr.state_focused}, //2
                                new int[]{android.R.attr.state_focused, android.R.attr.state_pressed} //3
                        },
                        new int[] {
                            Color.RED, //1
                            Color.GREEN, //2
                            Color.BLUE //3
                        }
                    );

도움이 되었기를 바랍니다.

편집 예 : 다음과 같은 XML 색상 상태 목록 :

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" android:color="@color/white"/>
    <item android:color="@color/black"/>
</selector>

이처럼 보일 것입니다

ColorStateList myColorStateList = new ColorStateList(
        new int[][]{
                new int[]{android.R.attr.state_pressed},
                new int[]{}
        },
        new int[] {
                context.getResources().getColor(R.color.white),
                context.getResources().getColor(R.color.black)
        }
);

아래 xml "<selector xmlns : android =" schemas.android.com/apk/res/android "> <item android : state_pressed ="true "android : color ="@ color / white "/ > colorstatelist를 사용하는 <item android : color = "@ color / black"/> </ selector> "
Satish

@SatishKumar 내 편집 내용을 확인했지만 테스트하지는 않았습니다.
Su-Au Hwang

3
거짓 상태를 지정하려면 값을 무시할 수 있으므로 값을 누르지 않을 때의 색상을 지정하려면 다음을 사용해야합니다. new int [] {
-android.R.attr.state_pressed

1
@tinsukE가 말한 것에 덧붙이려면 : 그러나 나중에 목록의 항목을 실수로 억제하지 않으려면 대부분의 상태에서 부정을 두는 것이 합리적이지 않습니다. 대신 기본 (빈) 항목으로 모든 "기타"가능성을 처리하십시오 new int[]{}마지막-이 답변의 마지막 코드 블록에 표시된대로. 내가 일반적으로 사용하는 부정 된 값은 "-enabled"입니다. 당신은 세 가지 다른 색상을 원하는 경우 또 다른 예를 들어, :, "누르지 + 집중"당신은 단순히 넣을 수 있습니다, "+ 집중하지 누르면" "+를 누르면 초점을 맞추고" {focused, pressed}, {focused}, {pressed}. 첫 번째 "true"가 사용됩니다.
ToolmakerSteve

2
... 당신이 할 수있는 실수 같은 일련의 것입니다 {pressed}, {-pressed}, {focused}, {-focused}. 문제가 있다는 것입니다 {pressed}{-pressed}모든 가능성을 포함 (버튼 중 하나를 누르거나 누르지), 나중에 나열된 색상은 지금까지 사용되지 않도록.!
ToolmakerSteve

64

때때로 이것은 충분할 것입니다 :

int colorInt = getResources().getColor(R.color.ColorVerificaLunes);
ColorStateList csl = ColorStateList.valueOf(colorInt);

20

불행히도 어떤 해결책도 나를 위해 작동하지 않습니다.

  1. 처음 누른 상태를 설정하지 않으면 감지되지 않습니다.
  2. 설정 한 경우 기본 색상을 추가하려면 빈 상태를 정의해야합니다.
ColorStateList themeColorStateList = new ColorStateList(
        new int[][]{
                new int[]{android.R.attr.state_pressed},
                new int[]{android.R.attr.state_enabled},
                new int[]{android.R.attr.state_focused, android.R.attr.state_pressed},
                new int[]{-android.R.attr.state_enabled},
                new int[]{} // this should be empty to make default color as we want
        },
        new int[]{
                pressedFontColor,
                defaultFontColor,
                pressedFontColor,
                disabledFontColor,
                defaultFontColor
        }
);

이것은 소스 코드의 생성자입니다.

/**
 * Creates a ColorStateList that returns the specified mapping from
 * states to colors.
 */
public ColorStateList(int[][] states, int[] colors) {
    mStateSpecs = states;
    mColors = colors;

    if (states.length > 0) {
        mDefaultColor = colors[0];

        for (int i = 0; i < states.length; i++) {
            if (states[i].length == 0) {
                mDefaultColor = colors[i];
            }
        }
    }
}

5
참고로 : if-elseif처럼 취급해야합니다. 첫 번째 상태 인 true를 선택합니다. 따라서 state_enabled를 첫 번째 상태로 사용하는 경우보기가 비활성화되지 않은 경우 state_pressed 전에 선택됩니다.
LeoFarage 2016 년

FWIW, 마지막 기본 요소가 있으므로 첫 번째 "enabled"요소가 전혀 효과가 없다고 생각합니다. 왜 완전히 제거하지 않습니까?
ToolmakerSteve

18

다음 ColorList은 Kotlin 에서 프로그래밍 방식으로 만드는 방법에 대한 예입니다 .

val colorList = ColorStateList(
        arrayOf(
                intArrayOf(-android.R.attr.state_enabled),  // Disabled
                intArrayOf(android.R.attr.state_enabled)    // Enabled
        ),
        intArrayOf(
                Color.BLACK,     // The color for the Disabled state
                Color.RED        // The color for the Enabled state
        )
)

또한 Kotlin 도우미 기능에 대해서는 아래 답변을 참조하십시오 .
arekolek

7

Jonathan Ellis답변을 거부 하면 Kotlin에서 코드를 좀 더 관용적이고 읽기 쉽도록 도우미 함수를 정의하여 대신 작성할 수 있습니다.

val colorList = colorStateListOf(
    intArrayOf(-android.R.attr.state_enabled) to Color.BLACK,
    intArrayOf(android.R.attr.state_enabled) to Color.RED
)

colorStateListOf 다음과 같이 구현할 수 있습니다.

fun colorStateListOf(vararg mapping: Pair<IntArray, Int>): ColorStateList {
    val (states, colors) = mapping.unzip()
    return ColorStateList(states.toTypedArray(), colors.toIntArray())
}

나는 또한 가지고있다 :

fun colorStateListOf(@ColorInt color: Int): ColorStateList {
    return ColorStateList.valueOf(color)
}

선택기인지 단색인지에 관계없이 동일한 함수 이름을 호출 할 수 있습니다.


3

작성을위한 내 빌더 클래스 ColorStateList

private class ColorStateListBuilder {
    List<Integer> colors = new ArrayList<>();
    List<int[]> states = new ArrayList<>();

    public ColorStateListBuilder addState(int[] state, int color) {
        states.add(state);
        colors.add(color);
        return this;
    }

    public ColorStateList build() {
        return new ColorStateList(convertToTwoDimensionalIntArray(states),
                convertToIntArray(colors));
    }

    private int[][] convertToTwoDimensionalIntArray(List<int[]> integers) {
        int[][] result = new int[integers.size()][1];
        Iterator<int[]> iterator = integers.iterator();
        for (int i = 0; iterator.hasNext(); i++) {
            result[i] = iterator.next();
        }
        return result;
    }

    private int[] convertToIntArray(List<Integer> integers) {
        int[] result = new int[integers.size()];
        Iterator<Integer> iterator = integers.iterator();
        for (int i = 0; iterator.hasNext(); i++) {
            result[i] = iterator.next();
        }
        return result;
    }
}

사용 예

ColorStateListBuilder builder = new ColorStateListBuilder();
builder.addState(new int[] { android.R.attr.state_pressed }, ContextCompat.getColor(this, colorRes))
       .addState(new int[] { android.R.attr.state_selected }, Color.GREEN)
       .addState(..., some color);

if(// some condition){
      builder.addState(..., some color);
}
builder.addState(new int[] {}, colorNormal); // must add default state at last of all state

ColorStateList stateList = builder.build(); // ColorStateList created here

// textView.setTextColor(stateList);

2

리소스를 사용하는 경우 Colors.xml

int[] colors = new int[] {
                getResources().getColor(R.color.ColorVerificaLunes),
                getResources().getColor(R.color.ColorVerificaMartes),
                getResources().getColor(R.color.ColorVerificaMiercoles),
                getResources().getColor(R.color.ColorVerificaJueves),
                getResources().getColor(R.color.ColorVerificaViernes)

        };

ColorStateList csl = new ColorStateList(new int[][]{new int[0]}, new int[]{colors[0]}); 

    example.setBackgroundTintList(csl);

2
같은 getResources()지금,있다되지 않습니다 ContextCompat.getColor(this,R.color.colorname);또는 ContextCompat.getColor(getActivity(),R.color.colorname);플래그먼트에서 사용을 위해
iBobb

다른 독자를 명확히하기 위해 new int[0](첫 번째 매개 변수 목록의 요소로) 길이가 0이며 기본 색상 설정을 나타냅니다. 여기에서 유일한 요소입니다. 즉, 색조가 버튼의 모든 상태에 적용됩니다 . 이것은 new int[]{}Roger Alien의 답변 과 동일합니다 .
ToolmakerSteve
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.