Làm cách nào để tạo ColorStateList theo chương trình?


157

Tôi đang cố gắng tạo một ColorStateListchương trình bằng cách sử dụng này:

ColorStateList stateList = new ColorStateList(states, colors); 

Nhưng tôi không chắc hai thông số là gì.

Theo tài liệu:

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

Đã thêm trong API cấp 1

Tạo một ColorStateList trả về ánh xạ được chỉ định từ trạng thái sang màu.

Ai đó có thể vui lòng giải thích cho tôi làm thế nào để tạo ra điều này?

Ý nghĩa của mảng hai chiều cho các trạng thái là gì?

Câu trả lời:


341

Xem http://developer.android.com/reference/android/R.attr.html#state_above_anchor để biết danh sách các trạng thái khả dụng.

Nếu bạn muốn đặt màu cho các trạng thái bị vô hiệu hóa, không tập trung, không được kiểm tra, v.v. chỉ cần phủ định các trạng thái:

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
Cảm ơn thông tin liên quan đến trạng thái "đối diện"!
BVB

Điều này có thể được sử dụng thay đổi màu sắc của một fab từ thư viện thiết kế.
Tapirboy

5
THẬN TRỌNG: Xem câu trả lời của Roger Alien (và nhận xét đầu tiên của nó) để hiểu rằng thứ tự các trạng thái ở đây kém: vì "đã bật" trước, nó sẽ ghi đè các trạng thái khác thường xảy ra trong khi bật nút. Tốt hơn là đặt "kích hoạt" cuối cùng. (Hoặc thay vì "đã bật", một mục trống / mặc định cuối cùng.)
ToolmakerSteve

2
Một danh sách cơ bản của các quốc gia cho một nút mà không giữ được trạng thái (KHÔNG phải là một chuyển đổi / hộp) có thể là {pressed}, {focused}, {-enabled}, {}. Đối với một chuyển đổi nó có thể là {checked, pressed}, {pressed}, {checked, focused}, {focused}, {checked}, {-enabled}, {}. Hoặc một chuyển đổi mà bỏ qua tập trung: {checked, pressed}, {pressed}, {checked}, {-enabled}, {}.
ToolmakerSteve

Trong trường hợp nếu ai đó sẽ thử bất kỳ giải pháp nào trong số đó, hãy chú ý đến thứ tự các trạng thái như trong selector.xml!
Anton Makov

75

Thứ nguyên thứ nhất là một mảng các tập trạng thái, thứ hai là trạng thái tự đặt. Mảng màu liệt kê các màu cho từng bộ trạng thái khớp, do đó độ dài của mảng màu phải khớp với thứ nguyên đầu tiên của mảng trạng thái (hoặc nó sẽ bị sập khi trạng thái được "sử dụng"). Ở đây và ví dụ:

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

hi vọng điêu nay co ich.

Ví dụ EDIT: danh sách trạng thái màu xml như:

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

sẽ trông như thế này

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

Bạn có thể cho biết cách biểu diễn xml bên dưới "<selector xmlns: android =" schemas.android.com/apk/res/android "> <item android: state_pressed =" true "android: color =" @ color / white "/ > <item android: color = "@ color / black" /> </ selector> "bằng cách sử dụng colorstatelist.
Satish

@SatishKumar kiểm tra chỉnh sửa của tôi, mặc dù tôi chưa kiểm tra nó.
Su-Au Hwang

3
Đáng nói là để chỉ định trạng thái sai, bạn có thể phủ nhận giá trị của nó, vì vậy nếu bạn muốn chỉ định màu khi không được nhấn, bạn nên sử dụng: new int [] {- ​​android.R.attr.state_pressed}
tinsukE

1
Để thêm vào những gì @tinsukE đã nói: Tuy nhiên, để tránh việc vô tình triệt tiêu một mục sau này trong danh sách, đối với hầu hết các trạng thái, sẽ không có ý nghĩa gì khi đặt phủ định - thay vào đó xử lý tất cả các khả năng "khác" với một mục mặc định (trống) new int[]{}cuối cùng - như được hiển thị trong khối mã cuối cùng của câu trả lời này. Giá trị phủ định duy nhất tôi thường sử dụng là "đã bật". Một ví dụ khác, nếu bạn muốn có ba màu khác nhau: "tập trung + ép", "tập trung + không ép", "ép + không tập trung", bạn có thể dễ dàng đặt {focused, pressed}, {focused}, {pressed}. Cái "thật" đầu tiên sẽ được sử dụng.
ToolmakerSteve

2
... Sai lầm bạn có thể làm là phải có một loạt như {pressed}, {-pressed}, {focused}, {-focused}. Vấn đề là {pressed}{-pressed}bao gồm TẤT CẢ các khả năng (nút được nhấn hoặc không được nhấn), do đó, không có màu nào được liệt kê sau này sẽ được sử dụng.!
ToolmakerSteve

64

Đôi khi điều này là đủ:

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

20

Thật không may, không có giải pháp nào hiệu quả với tôi.

  1. Nếu bạn không đặt trạng thái nhấn lúc đầu, nó sẽ không phát hiện ra.
  2. Nếu bạn đặt nó, thì bạn cần xác định trạng thái trống để thêm màu mặc định
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
        }
);

Đây là constructor từ mã nguồn:

/**
 * 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
Cũng như một sidenote: Bạn phải coi nó như là một if-otherif. Nó chọn trạng thái đầu tiên là đúng. Vì vậy, nếu bạn có trạng thái_en bật là trạng thái đầu tiên, nó sẽ được chọn trước trạng thái_pressed - trừ khi chế độ xem bị tắt.
LeoFarage

FWIW, vì bạn đã có một yếu tố mặc định cuối cùng, tôi không nghĩ rằng yếu tố "được kích hoạt" đầu tiên đang làm tốt cho bạn cả. Tại sao không loại bỏ nó hoàn toàn?
ToolmakerSteve

18

Đây là một ví dụ về cách tạo một ColorList lập trình trong 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
        )
)

Ngoài ra, hãy xem câu trả lời của tôi dưới đây để biết chức năng của trình trợ giúp Kotlin.
arekolek

7

Từ bỏ câu trả lời của Jonathan Ellis , trong Kotlin, bạn có thể định nghĩa hàm trợ giúp để làm cho mã trở nên đơn giản hơn và dễ đọc hơn, vì vậy bạn có thể viết điều này thay thế:

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

colorStateListOf có thể được thực hiện như thế này:

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

Tôi cũng có:

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

Vì vậy, tôi có thể gọi cùng tên hàm, bất kể đó là bộ chọn hay màu đơn.


3

Lớp xây dựng của tôi để tạo 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;
    }
}

Ví dụ sử dụng

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

nếu bạn sử dụng tài nguyên thì 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
như getResources()bị phản đối, hiện tại ContextCompat.getColor(this,R.color.colorname);hoặc ContextCompat.getColor(getActivity(),R.color.colorname);để sử dụng trong một mảnh
iBobb 28/03/2016

Để làm rõ cho những người đọc khác, new int[0](như một thành phần trong danh sách của tham số đầu tiên) là một mảng có độ dài bằng không và biểu thị cài đặt màu mặc định. Đây là yếu tố duy nhất, có nghĩa là màu được áp dụng cho tất cả các trạng thái của nút. Điều này tương đương với new int[]{}câu trả lời của Roger Alien.
ToolmakerSteve
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.