วิธีตั้งค่าสีข้อความแถบสนับสนุนไลบรารีเป็นอย่างอื่นที่ไม่ใช่ android: textColor?


96

ดังนั้นฉันจึงเริ่มใช้ Snackbar ใหม่ใน Design Support Library แต่ฉันพบว่าเมื่อคุณกำหนด "android: textColor" ในธีมของคุณจะมีผลกับสีข้อความของสแน็คบาร์ เห็นได้ชัดว่าเป็นปัญหาหากสีข้อความหลักของคุณมืด

ป้อนคำอธิบายภาพที่นี่

มีใครรู้วิธีแก้ปัญหานี้หรือมีคำแนะนำว่าฉันควรระบายสีข้อความอย่างไร

แก้ไขมกราคม 2560: (หลังคำตอบ)

แม้ว่าจะมีวิธีแก้ไขปัญหาแบบกำหนดเองบางอย่างเพื่อแก้ไขปัญหาด้านล่าง แต่ก็น่าจะดีที่จะจัดหาวิธีที่ถูกต้องในการจัดธีม Snackbars

ประการแรกคุณอาจไม่ควรกำหนดandroid:textColorธีมของคุณเลย (เว้นแต่คุณจะทราบขอบเขตของสิ่งที่ใช้ธีม) สิ่งนี้จะกำหนดสีข้อความของทุกมุมมองที่เชื่อมต่อกับธีมของคุณ หากคุณต้องการกำหนดสีข้อความในมุมมองที่ไม่ใช่ค่าเริ่มต้นให้ใช้android:primaryTextColorและอ้างอิงแอตทริบิวต์นั้นในมุมมองแบบกำหนดเองของคุณ

อย่างไรก็ตามสำหรับการนำธีมไปใช้Snackbarโปรดอ้างอิงคู่มือคุณภาพนี้จากเอกสารของบุคคลที่สาม: http://www.materialdoc.com/snackbar/ (ปฏิบัติตามการใช้ธีมแบบเป็นโปรแกรมเพื่อให้มันไม่ต้องพึ่งพารูปแบบ xml)

สำหรับการอ้างอิง:

// create instance
Snackbar snackbar = Snackbar.make(view, text, duration);

// set action button color
snackbar.setActionTextColor(getResources().getColor(R.color.indigo));

// get snackbar view
View snackbarView = snackbar.getView();

// change snackbar text color
int snackbarTextId = android.support.design.R.id.snackbar_text;  
TextView textView = (TextView)snackbarView.findViewById(snackbarTextId);  
textView.setTextColor(getResources().getColor(R.color.indigo));

// change snackbar background
snackbarView.setBackgroundColor(Color.MAGENTA);  

(คุณสามารถสร้างเลย์เอาต์Snackbarแบบกำหนดเองของคุณเองได้เช่นกันดูลิงก์ด้านบนหากวิธีนี้รู้สึกว่าแฮ็คเกินไปและคุณต้องการวิธีที่เชื่อถือได้อย่างแน่นอนเพื่อให้ Snackbar ที่กำหนดเองของคุณอยู่ได้นานผ่านการอัปเดตไลบรารีการสนับสนุนที่เป็นไปได้)

หรือดูคำตอบด้านล่างสำหรับคำตอบที่คล้ายกันและอาจเร็วกว่าเพื่อแก้ปัญหาของคุณ


ขอบคุณสำหรับการแก้ปัญหา! มีการเรียกทรัพย์สินจริงandroid:textColorPrimary
muetzenflo

ขอบคุณสำหรับคำอธิบายที่ครอบคลุมนี้
Bugs เกิดขึ้น

"คุณอาจไม่ควรกำหนด android: textColor ในธีมของคุณเลย ... " นั่นคือกุญแจสำคัญสำหรับฉันขอบคุณ!
Tyler

คำตอบ:


40

ฉันรู้ว่ามีคำตอบแล้ว แต่วิธีที่ง่ายที่สุดที่ฉันพบคือการสร้างโดยตรงโดยใช้Html.fromHtmlวิธีการและfontแท็ก

Snackbar.make(view, 
       Html.fromHtml("<font color=\"#ffffff\">Tap to open</font>").show()

3
ฉันชอบโซลูชันนี้เนื่องจากเป็นบรรทัดเดียว
Lahiru Chandima

1
นี่ไม่ใช่คำตอบที่แท้จริงของคำถามนั้น ใช้: snackbar.setActionTextColor (Color.WHITE) .show ();
Ahamadullah Saikat

มี / มีข้อผิดพลาดในแถบสแน็คบาร์การตั้งค่าสีไม่ได้ทำอะไรเลย วิธีนี้ใช้ได้ผลไม่ว่าจะเกิดอะไรขึ้น แต่อาจไม่ใช่ทางออกที่ดีที่สุดสำหรับผู้อื่น
JPM

สิ่งนี้ต้องการระดับ API> 24
frank17

171

ฉันพบสิ่งนี้ที่คุณลักษณะใหม่ของ Android Design Support Library คืออะไรและจะใช้ Snackbar ได้อย่างไร

สิ่งนี้ใช้ได้ผลสำหรับฉันในการเปลี่ยนสีข้อความในแถบสแน็คบาร์

Snackbar snack = Snackbar.make(view, R.string.message, Snackbar.LENGTH_LONG);
View view = snack.getView();
TextView tv = (TextView) view.findViewById(android.support.design.R.id.snackbar_text);
tv.setTextColor(Color.WHITE);
snack.show();



อัปเดต: ANDROIDX: ตามที่ dblackker ชี้ให้เห็นในความคิดเห็นด้วยไลบรารีการสนับสนุน AndroidX ใหม่รหัสเพื่อค้นหา ID ของ Snackbar TextView จะเปลี่ยนเป็น:

TextView tv = view.findViewById(com.google.android.material.R.id.snackbar_text);
tv.setTextColor(ContextCompat.getColor(requireContext(), R.color.someColor))

2
ในกรณีที่คนอื่นกำลังค้นหาวิธีเปลี่ยนขนาดตัวอักษรของ Snackbar อย่างไร้ประโยชน์นี่แหล่ะ!
Janis Peisenieks

2
FYI คุณสามารถทำได้เช่นเดียวกันกับข้อความ Action โดยใช้snackbar_actionแทนsnackbar_textไฟล์. ดูคำตอบนี้สำหรับตัวอย่าง: stackoverflow.com/a/36800101/293280
Joshua Pinter

7
นี่เป็นการแฮ็กที่ดีที่สุด - จะเกิดอะไรขึ้นเมื่อ ID สำหรับ android.support.design.R.id.snackbar_text มีการเปลี่ยนแปลงในไลบรารีการสนับสนุนในอนาคต ไม่มีสไตล์ SnackBar เริ่มต้นบางประเภทที่สามารถแทนที่ใน styles.xml ได้หรือไม่?
DiscDev

8
ID นั้นมีการเปลี่ยนแปลงอย่างแน่นอนในไลบรารีการสนับสนุนในอนาคตตอนนี้ฉันได้รับตัวชี้ค่าว่าง
CaptainForge

3
อัปเดต - ด้วย androidx ตอนนี้ id เป็นดังนี้:snack.view.findViewById(com.google.android.material.R.id.snackbar_text) as TextView
dblackker

15

การแฮ็กandroid.support.design.R.id.snackbar_textเป็นเรื่องที่เปราะบางวิธีที่ดีกว่าหรือน้อยกว่าในการแฮ็กจะเป็น:

String snackText = getResources().getString(YOUR_RESOURCE_ID);
SpannableStringBuilder ssb = new SpannableStringBuilder()
    .append(snackText);
ssb.setSpan(
    new ForegroundColorSpan(Color.WHITE),
    0,
    snackText.length(),
    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
Snackbar.make(
        getView(),
        ssb,
        Snackbar.LENGTH_SHORT)
        .show();

15

เอาล่ะฉันแก้ไขโดยการจัดระเบียบวิธีการสร้างสีข้อความใหม่

ในรูปแบบแสงของฉันฉันตั้งandroid:textColorPrimaryกับnormal dark textที่ฉันต้องการและผมตั้งไปandroid:textColorwhite

ฉันอัปเดตมุมมองข้อความและปุ่มทั้งหมดที่มี android:textColor="?android:attr/textColorPrimary".

เนื่องจากสแน็คบาร์ดึงมาจากtextColorฉันจึงตั้งค่าข้อความอื่น ๆtextColorPrimaryทั้งหมดเป็น

แก้ไขมกราคม 2017: ---------------------------------------------- ------

ดังที่ความคิดเห็นกล่าวและตามที่ระบุไว้ในคำถามต้นฉบับที่แก้ไขด้านบนคุณไม่ควรกำหนดandroid:textColorในธีมของคุณเนื่องจากจะเปลี่ยนสีข้อความของทุกมุมมองภายในธีม


ฉันเพิ่งทำงานนี้เสร็จเอาล่ะใช้เวลาสักครู่! อย่างไรก็ตามฉันจำเป็นต้องใช้เมธอด "m vai's" ด้านล่างสำหรับกิจกรรมการตั้งค่าแบบโบราณของฉัน (โดยใช้ค่ากำหนด. xml) ฉันคิดว่ามันทำให้สไตล์ของแอพของฉันถูกต้องตามธีมที่ดีกว่า +1
BrantApps

1
ไม่ใช่วิธีแก้ปัญหาที่ดี IMO ฉันต้องการเก็บชุดรูปแบบที่แท้จริงของฉันไว้สำหรับ textview และเพียงแค่เปลี่ยนสีข้อความ snakbar ...
issamux

1
คุณไม่ควรกำหนดandroid:textColorในธีมของคุณเลย มันเป็นรูปแบบTextViewแอตทริบิวต์ของ หากคุณกำหนดในธีมของคุณคุณจะแทนที่สีข้อความของทุกๆTextViewหรือButtonที่ไม่ได้ระบุสีข้อความใน XML ที่ยังเกิดขึ้นเป็นข้อความ Snackbar ซึ่งปกติจะใช้เวลาสีจากสีเข้มซ้อนทับธีม
Eugen Pechanec

15

สร้างฟังก์ชันขยาย kotlin นี้ที่ฉันใช้ในโครงการของฉัน:

fun Snackbar.setTextColor(color: Int): Snackbar {
    val tv = view.findViewById(com.google.android.material.R.id.snackbar_text) as TextView
    tv.setTextColor(color)

    return this
}

การใช้งานอย่างที่คุณคาดหวัง:

Snackbar.make (ดู, R.string.your_string, Snackbar.LENGTH_LONG) .setTextColor (Color.WHITE) .show ()


ชอบการใช้วิธีการขยาย Kotlin แบบง่ายๆ! ;-)
Patrick Kuijpers

14
ใช้com.google.android.material.R.id.snackbar_textหากคุณย้ายไปใช้ AndroidX
Rishabh876

เปลี่ยน @ Rishabh876 :)
Richard

12

แนวทางหนึ่งคือการใช้ช่วง:

final ForegroundColorSpan whiteSpan = new ForegroundColorSpan(ContextCompat.getColor(this, android.R.color.white));
SpannableStringBuilder snackbarText = new SpannableStringBuilder("Hello, I'm white!");
snackbarText.setSpan(whiteSpan, 0, snackbarText.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);

Snackbar.make(view, snackbarText, Snackbar.LENGTH_LONG)
                .show();

นอกจากนี้คุณยังสามารถเพิ่มสีและสไตล์ได้หลายสีในแถบเดียว นี่เป็นคำแนะนำที่ดี:

https://androidbycode.wordpress.com/2015/06/06/material-design-snackbar-using-the-design-support-library/


9

หากคุณย้ายไปยัง androidX ให้ใช้com.google.android.material.R.id.snackbar_textแทน android.support.design.R.id.snackbar_textการเปลี่ยนสีของข้อความบนสแน็คบาร์


คุณสมควรได้รับเหรียญ
frank17

@ frank17 มีการพูดถึงในหลาย ๆ ความคิดเห็นที่นี่
CoolMind

6

วิธีเดียวที่ฉันเห็นคือใช้getView()และขี่จักรยานผ่านลูกของมัน ฉันไม่รู้ว่ามันจะได้ผลไหมและมันก็แย่อย่างที่เห็น ฉันหวังว่าพวกเขาจะเพิ่ม API เกี่ยวกับปัญหานี้ในไม่ช้า

Snackbar snack = Snackbar.make(...);
ViewGroup group = (ViewGroup) snack.getView();
for (int i = 0; i < group.getChildCount(); i++) {
    View v = group.getChildAt(i);
    if (v instanceof TextView) {
        TextView t = (TextView) v;
        t.setTextColor(...)
    }
}
snack.show();

6

หากคุณจะย้ายรหัสของคุณไปยัง AndroidX ตอนนี้คุณสมบัติ TextView คือ:

com.google.android.material.R.id.snackbar_text

2

นี่คือสิ่งที่ฉันใช้เมื่อฉันต้องการสีที่กำหนดเอง

    @NonNull
    public static Snackbar makeSnackbar(@NonNull View layout, @NonNull CharSequence  text, int duration, int backgroundColor, int textColor/*, int actionTextColor*/){
        Snackbar snackBarView = Snackbar.make(layout, text, duration);
        snackBarView.getView().setBackgroundColor(backgroundColor);
        //snackBarView.setActionTextColor(actionTextColor);
        TextView tv = (TextView) snackBarView.getView().findViewById(android.support.design.R.id.snackbar_text);
        tv.setTextColor(textColor);
        return snackBarView;
    }

และบริโภคเป็น:

CustomView.makeSnackbar(view, "Hello", Snackbar.LENGTH_LONG, Color.YELLOW,Color.CYAN).setAction("DO IT", myAction).show();

2

ฉันเปลี่ยนธีมแล้ว

Theme.AppCompat.Light.NoActionBar

ถึง

Theme.AppCompat.NoActionBar 

มันใช้งานได้พยายามใช้ธีมธรรมดาแทนแสงหรือธีมอื่น ๆ


2

หากคุณตัดสินใจที่จะใช้โซลูชันที่สกปรกและแฮ็คโดยค้นหา TextView ใน Snackbar โดย id และคุณได้ย้ายไปที่ androidx แล้วนี่คือรหัส:

val textViewId = com.google.android.material.R.id.snackbar_text
val snackbar = Snackbar.make(view, "Text", Snackbar.LENGTH_SHORT)
val textView = snackbar.view.findViewById(textViewId) as TextView
textView.setTextColor(Color.WHITE)

2

ปัจจุบัน(มกราคม 2020)กับ com.google.android.material:material:1.2.0และอาจจะด้วย1.1.0

เป็นวิธีที่ดีที่สุดในการลบล้างสไตล์เหล่านี้:

<item name="snackbarStyle">@style/Widget.MaterialComponents.Snackbar</item>
<item name="snackbarButtonStyle">@style/Widget.MaterialComponents.Button.TextButton.Snackbar</item>
<item name="snackbarTextViewStyle">@style/Widget.MaterialComponents.Snackbar.TextView</item>

หากคุณใช้ธีมวัสดุ.Bridgeในตอนท้ายด้วยเหตุผลบางประการจะไม่มีการกำหนดสไตล์เหล่านี้ ดังนั้น Snackar จะใช้เลย์เอาต์ดั้งเดิมโดยไม่มีสไตล์เหล่านี้

ฉันพบในซอร์สโค้ดซึ่งต้องกำหนดทั้งคู่snackbarButtonStyleและsnackbarTextViewStyleต้องกำหนดมิฉะนั้นจะไม่ถูกใช้



1

Find by id ไม่ได้ผลสำหรับฉันดังนั้นฉันจึงพบวิธีแก้ปัญหาอื่น:

Snackbar snackbar = Snackbar.make(view, text, duration);//just ordinary creation

ViewGroup snackbarView = (ViewGroup) snackbar.getView();
SnackbarContentLayout contentLayout = (SnackbarContentLayout) snackbarView.getChildAt(0);
TextView tvText = contentLayout.getMessageView();
tvText.setTextColor(/*your color here*/);

//set another colors, show, etc

1

ใช้สิ่งที่Snackbarรวมอยู่ในไลบรารีส่วนประกอบวัสดุและใช้ไฟล์

  • setTextColor เพื่อกำหนดสีข้อความ
  • setActionTextColorเพื่อกำหนดสีข้อความที่ใช้โดยการกระทำ คุณสามารถใช้สีหรือตัวเลือกสี
  • setBackgroundTint เพื่อกำหนดสีพื้นหลังของแถบสแน็คบาร์

สิ่งที่ต้องการ:

Snackbar snackbar = Snackbar.make(view, "My custom Snackbar", Snackbar.LENGTH_LONG);        
snackbar.setTextColor(ContextCompat.getColor(this,R.color.xxxxx));
snackbar.setActionTextColor(ContextCompat.getColor(this,R.color.my_selector));
snackbar.setBackgroundTint(ContextCompat.getColor(this,R.color.xxxx));
snackbar.show();

ป้อนคำอธิบายภาพที่นี่


0

ฉันมีรหัสง่ายๆที่จะช่วยในการรับตัวอย่างทั้ง textview ของ Snackbar หลังจากนั้นคุณสามารถเรียกวิธีการทั้งหมดที่ใช้ได้กับ textview

Snackbar snackbar = Snackbar.make( ... )    // Create Snack bar


snackbar.setActionTextColor(getResources().getColor(R.color.white));  //if you directly want to apply the color to Action Text

TextView snackbarActionTextView = (TextView) snackbar.getView().findViewById( android.support.design.R.id.snackbar_action );

snackbarActionTextView.setTextColor(Color.RED);  //This is another way of doing it

snackbarActionTextView.setTypeface(snackbarActionTextView.getTypeface(), Typeface.BOLD);

//Below Code is to modify the Text in Snack bar
TextView snackbarTextView = (TextView) snackbar.getView().findViewById(android.support.design.R.id.snackbar_text);
snackbarTextView.setTextSize( 16 );
snackbarTextView.setTextColor(getResources().getColor(R.color.white));

0

เพื่อประหยัดเวลาในการพัฒนาอันมีค่าของคุณนี่คือวิธีการคงที่ที่ฉันใช้:

public static void snack(View view, String message) {
    if (!TextUtils.isEmpty(message)) {
        Snackbar snackbar = Snackbar.make(view, message, Snackbar.LENGTH_SHORT);
        snackbar.getView().setBackgroundColor(Color.YELLOW);
        TextView tv =  snackbar.getView().findViewById(android.support.design.R.id.snackbar_text); //snackbar_text
        tv.setTextColor(Color.BLACK);
        snackbar.show();
    }
}

นี่คือลักษณะ:

แถบสีเหลืองพร้อมข้อความสีดำ


0

หากคุณอยู่ในKotlinคุณสามารถสร้างส่วนขยายได้:

fun Snackbar.withTextColor(color: Int): Snackbar {
    val tv = this.view.findViewById(android.support.design.R.id.snackbar_text) as TextView
    tv.setTextColor(color)
    return this
}

การใช้งาน :

yourSnackBar.withTextColor(Color.WHITE).show()

คำตอบเดียวกับของฉัน😉
Richard

0

ตามส่วนประกอบ AndroidX Jitpack ใหม่

implementation 'com.google.android.material:material:1.0.0'

ใช้ส่วนขยายนี้ที่ฉันสร้างขึ้น

inline fun View.snack(message: String, length: Int = Snackbar.LENGTH_LONG,
 f: Snackbar.() -> Unit) {
val snack = Snackbar.make(this, message, length)
snack.f()
snack.show()
}

fun Snackbar.action(action: String, actionColor: Int? = null, textColor: Int? = null, listener: (View) -> Unit) {
setAction(action, listener)
actionColor?.let {
    setActionTextColor(it)
    }
textColor?.let {
    this.view.findViewById<TextView>(R.id.snackbar_text).setTextColor(it)
    }
}

ใช้แบบนี้ครับ

btn_login.snack(
        getString(R.string.fields_empty_login),
        ContextCompat.getColor(this@LoginActivity, R.color.whiteColor)
    ) {
        action(getString(R.string.text_ok), ContextCompat.getColor(this@LoginActivity, R.color.gray_300),ContextCompat.getColor(this@LoginActivity, R.color.yellow_400)) {
            this@snack.dismiss()
        }
    }

0

นี่เป็นวิธีแก้ปัญหาของฉันในการแก้ปัญหาประเภทนี้ในการandroidxใช้kotlin

 fun showSnackBar(message: String) {
        mContent?.let {
            val snackbar = Snackbar.make(it, message, Snackbar.LENGTH_LONG)
            val snackbarView = snackbar.view
            val tv = snackbarView.findViewById<TextView>(R.id.snackbar_text)
            tv.setTextColor(Color.WHITE) //change the color of text
            tv.maxLines = 3 //specify the limit of text line
            snackbar.duration = BaseTransientBottomBar.LENGTH_SHORT //specify the duraction of text message
            snackbar.show()
        }
    }

คุณต้องเริ่มต้นวิธีการmContentภายในonViewCreatedเช่นด้านล่าง

var mContent: View? = null
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        mContent = view
    }

-1

ฉันยังสังเกตเห็นปัญหาเดียวกัน ขอบคุณคำตอบที่นี่ฉันได้สร้างชั้นเรียนขนาดเล็กซึ่งสามารถช่วยแก้ปัญหานี้ได้ง่ายขึ้นเพียงแค่แทนที่สิ่งนี้:

Snackbar.make(view, "Error", Snackbar.LENGTH_LONG).show();

ด้วยสิ่งนี้:

Snackbar2.make(view, "Error", Snackbar.LENGTH_LONG).show();

นี่คือชั้นเรียนของฉัน:

public class Snackbar2 {
static public Snackbar make(View view, int resid, int duration){
    Snackbar result = Snackbar.make(view, resid, duration);
    process(result);
    return result;
}
static public Snackbar make(View view, String text, int duration){
    Snackbar result = Snackbar.make(view, text, duration);
    process(result);
    return result;
}
static private void process(Snackbar snackbar){
    try {
        View view1= snackbar.getView();

        TextView tv = (TextView) view1.findViewById(android.support.design.R.id.snackbar_text);
        tv.setTextColor(Color.WHITE);

    }catch (Exception ex)
    {
        //inform about error
        ex.printStackTrace();
    }
}

}


1
นี่เป็นการแฮ็กและอาศัย id ของมุมมองไลบรารีสนับสนุนต่างๆเพื่อให้เป็นแบบคงที่ ฉันจะหลีกเลี่ยงการแก้ปัญหานี้โดยเสียค่าใช้จ่ายทั้งหมด
DiscDev
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.