ฉันจะสร้าง ColorStateList โดยทางโปรแกรมได้อย่างไร


158

ฉันพยายามสร้างColorStateListโปรแกรมโดยใช้สิ่งนี้:

ColorStateList stateList = new ColorStateList(states, colors); 

แต่ฉันไม่แน่ใจว่าพารามิเตอร์สองตัวคืออะไร

ตามเอกสาร:

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

เพิ่มในระดับ API 1

สร้าง ColorStateList ที่ส่งคืนการแม็พที่ระบุจากสถานะเป็นสี

มีใครช่วยอธิบายวิธีสร้างสิ่งนี้ให้ฉันได้บ้าง

ความหมายของอาเรย์สองมิติสำหรับรัฐคืออะไร?

คำตอบ:


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

สิ่งนี้สามารถใช้เปลี่ยนสีของ fab จากไลบรารีการออกแบบ
Tapirboy

5
ข้อควรระวัง: ดูคำตอบของ Roger Alien (และความคิดเห็นแรก) เพื่อทำความเข้าใจว่าลำดับของรัฐที่นี่ไม่ดี: เนื่องจาก "เปิดใช้งาน" เป็นอันดับแรกจึงจะแทนที่สถานะอื่น ๆ ที่มักจะเกิดขึ้นในขณะที่ปุ่มเปิดใช้งาน ดีกว่าที่จะใส่ "เปิดใช้งาน" ล่าสุด (หรือแทนที่จะ "เปิดใช้งาน" รายการว่าง / ค่าเริ่มต้นสุดท้าย)
ToolmakerSteve

2
รายการพื้นฐานของรัฐสำหรับปุ่มที่ไม่รักษาของรัฐ (ไม่สลับ / ช่องทำเครื่องหมาย) อาจจะมี{pressed}, {focused}, ,{-enabled} {}สำหรับสลับมันอาจจะ{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 "/ > <item android: color = "@ color / black" /> </selector> "โดยใช้ colorstatelist
Satish

@SatishKumar ตรวจสอบการแก้ไขของฉันฉันยังไม่ได้ทดสอบ
Su-Au Hwang

3
น่าจะบอกว่าเพื่อระบุสถานะที่ผิดพลาดคุณสามารถปฏิเสธค่าของมันได้ดังนั้นหากคุณต้องการระบุสีเมื่อไม่ได้กดคุณควรใช้: new int [] {- ​​android.R.attr.state_pressed}
tinsukE

1
หากต้องการเพิ่มสิ่งที่ @tinsukE กล่าวไว้: อย่างไรก็ตามเพื่อหลีกเลี่ยงการระงับรายการในภายหลังโดยไม่ตั้งใจสำหรับรัฐส่วนใหญ่จะไม่เหมาะสมที่จะปฏิเสธ - แทนที่จะจัดการความเป็นไปได้ทั้งหมด "อื่น ๆ " ด้วยรายการเริ่มต้น (ว่าง) new int[]{}สุดท้าย - ตามที่แสดงในบล็อกรหัสสุดท้ายของคำตอบนี้ ค่าเมื่อตะกี้เท่านั้นที่ฉันมักจะใช้คือ "- เปิดใช้งาน" อีกตัวอย่างหนึ่งถ้าคุณต้องการสามสีที่แตกต่างกัน: "มุ่งเน้น + กด", "มุ่งเน้น + ไม่ได้กด", "กด + ไม่ได้มุ่งเน้น" คุณสามารถใส่เพียง{focused, pressed}, ,{focused} {pressed}อันแรก "จริง" จะถูกนำมาใช้
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
เช่นเดียวกับ sidenote: คุณต้องปฏิบัติต่อคุณเหมือนเป็น if-elseif มันเลือกสถานะแรกที่เป็นจริง ดังนั้นถ้าคุณมี state_enabled เป็นสถานะแรกมันจะถูกเลือกก่อน state_pressed - เว้นแต่ว่ามุมมองนั้นจะปิดการใช้งาน
LeoFarage

FWIW เนื่องจากคุณมีองค์ประกอบเริ่มต้นที่ผ่านมาฉันไม่คิดว่าองค์ประกอบ "เปิดใช้งาน" ตัวแรกจะทำให้คุณทำได้ดี ทำไมไม่ลบออกอย่างสมบูรณ์?
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);สำหรับการใช้งานใน Fragment
iBobb

เพื่อชี้แจงสำหรับผู้อ่านอื่น ๆnew int[0](เป็นองค์ประกอบในรายการของพารามิเตอร์แรก) คืออาร์เรย์ที่มีความยาวเป็นศูนย์และแสดงถึงการตั้งค่าสีเริ่มต้น ที่นี่เป็นองค์ประกอบเดียวซึ่งหมายถึงแต้มสีจะใช้กับสถานะทั้งหมดของปุ่ม สิ่งนี้เทียบเท่ากับnew int[]{}คำตอบของ Roger Alien
ToolmakerSteve
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.