Làm cách nào để đặt màu văn bản của thanh snack trong thư viện hỗ trợ thành màu khác với android: textColor?


94

Vì vậy, tôi đã bắt đầu sử dụng Snackbar mới trong Thư viện hỗ trợ thiết kế, nhưng tôi thấy rằng khi bạn xác định "android: textColor" trong chủ đề của mình, nó sẽ áp dụng cho màu văn bản của thanh snack. Đây rõ ràng là một vấn đề nếu màu văn bản chính của bạn tối.

nhập mô tả hình ảnh ở đây

Có ai biết cách giải quyết vấn đề này hoặc có lời khuyên cho cách tôi nên tô màu văn bản của mình không?

CHỈNH SỬA tháng 1 năm 2017: (Trả lời sau)

Mặc dù có một số giải pháp tùy chỉnh để khắc phục sự cố bên dưới, nhưng có lẽ bạn nên cung cấp cách chính xác để tạo chủ đề Snackbars.

Thứ nhất, bạn có thể không nên xác định android:textColorchủ đề của mình (trừ khi bạn thực sự biết phạm vi của những gì đang sử dụng chủ đề). Điều này đặt màu văn bản về cơ bản của mọi chế độ xem kết nối với chủ đề của bạn. Nếu bạn muốn xác định màu văn bản trong các chế độ xem không phải là màu mặc định, thì hãy sử dụng android:primaryTextColorvà tham chiếu thuộc tính đó trong các chế độ xem tùy chỉnh của bạn.

Tuy nhiên, để áp dụng chủ đề Snackbar, vui lòng tham khảo hướng dẫn chất lượng này từ tài liệu tài liệu của bên thứ ba: http://www.materialdoc.com/snackbar/ (Thực hiện theo cách triển khai chủ đề có lập trình để không dựa vào kiểu xml)

Để tham khảo:

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

(Bạn cũng có thể tạo Snackbarbố cục tùy chỉnh của riêng mình , hãy xem liên kết ở trên. Làm như vậy nếu phương pháp này cảm thấy quá khó và bạn muốn một cách chắc chắn đáng tin cậy để có Snackbar tùy chỉnh của mình tồn tại thông qua các bản cập nhật thư viện hỗ trợ có thể có).

Và cách khác, hãy xem các câu trả lời bên dưới để biết các câu trả lời tương tự và có lẽ nhanh hơn để giải quyết vấn đề của bạn.


cảm ơn cho giải pháp! tài sản được thực sự gọi làandroid:textColorPrimary
muetzenflo

Cảm ơn bạn đã giải thích toàn diện này.
Lỗi xảy ra

"Bạn có thể không nên xác định android: textColor trong các chủ đề của mình ..." đó là chìa khóa cho tôi, cảm ơn bạn!
Tyler

Câu trả lời:


41

Tôi biết điều này đã được trả lời rồi nhưng cách dễ nhất mà tôi tìm thấy là trực tiếp sử dụng Html.fromHtmlphương pháp và fontthẻ

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

3
Tôi thích giải pháp này vì nó là một dòng.
Lahiru Chandima

1
Đây không phải là giải pháp thực tế của câu hỏi đó. Sử dụng: snackbar.setActionTextColor (Color.WHITE) .show ();
Ahamadullah Saikat

Có / có một lỗi trong cài đặt Snackbar, màu không làm gì cả. Cách này không có hiệu quả nhưng có thể không phải là giải pháp tối ưu cho những người khác.
JPM

Điều này yêu cầu cấp API> 24.
Frank17

171

Tôi tìm thấy điều này tại Thư viện hỗ trợ thiết kế Android có những tính năng mới nào và cách sử dụng Snackbar của nó là gì?

Điều này phù hợp với tôi khi thay đổi màu văn bản trong 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();



CẬP NHẬT: ANDROIDX: Như dblackker đã chỉ ra trong các nhận xét, với thư viện hỗ trợ AndroidX mới, mã để tìm ID của Snackbar TextView sẽ thay đổi thành:

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

2
Đề phòng bất kỳ ai khác đang tìm cách thay đổi kích thước văn bản của Snackbar một cách vô ích, thì đây chính là nó!
Janis Peisenieks

2
FYI, bạn có thể làm tương tự với văn bản Hành động bằng cách sử dụng snackbar_actionthay vì snackbar_text. Hãy xem câu trả lời này để biết ví dụ: stackoverflow.com/a/36800101/293280
Joshua Pinter

7
Đây là một bản hack tốt nhất - điều gì sẽ xảy ra khi ID cho android.support.design.R.id.snackbar_text thay đổi trong bản phát hành trong tương lai của thư viện hỗ trợ? Có phải không có một số loại kiểu SnackBar mặc định có thể được ghi đè trong styles.xml?
DiscDev

7
ID đó thực sự đã được thay đổi trong bản phát hành tương lai của thư viện hỗ trợ, tôi đang nhận được một con trỏ null.
CaptainForge

3
Cập nhật - với androidx, id tại là như sau:snack.view.findViewById(com.google.android.material.R.id.snackbar_text) as TextView
dblackker

15

Lấy cắp dữ liệu android.support.design.R.id.snackbar_textlà mong manh, một cách tốt hơn hoặc ít hack hơn để làm điều đó sẽ là:

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

Đã tạo hàm mở rộng kotlin này mà tôi sử dụng trong các dự án của mình:

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

    return this
}

Cách sử dụng như bạn mong đợi:

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


Yêu thích việc sử dụng đơn giản các phương pháp mở rộng Kotlin! ;-)
Patrick Kuijpers

12
Sử dụng com.google.android.material.R.id.snackbar_textnếu bạn chuyển sang AndroidX.
Rishabh876

14

Được rồi, tôi đã sửa nó bằng cách sắp xếp lại cơ bản cách tôi tạo màu văn bản.

Trong chủ đề ánh sáng của tôi, tôi đặt android:textColorPrimarycho normal dark texttôi muốn, và tôi đặt android:textColorđểwhite .

Tôi đã cập nhật tất cả các chế độ xem văn bản và các nút của mình để có android:textColor="?android:attr/textColorPrimary".

Vì vậy, vì thanh ăn nhanh lấy từ textColor, tôi chỉ đặt tất cả các văn bản khác của tôi thành textColorPrimary.

CHỈNH SỬA THÁNG 1 NĂM 2017: ---------------------------------------------- ------

Vì vậy, như các nhận xét đã nói, và như đã nêu trong câu hỏi ban đầu đã chỉnh sửa ở trên, bạn có thể không nên xác định android:textColortrong chủ đề của mình, vì điều này sẽ thay đổi màu văn bản của mọi chế độ xem bên trong chủ đề.


Tôi vừa hoàn thành nhiệm vụ này, phew, mất một lúc! Tuy nhiên, tôi cần sử dụng phương thức "m vai's" bên dưới cho hoạt động Tùy chọn cổ xưa của mình (sử dụng tùy chọn .xml). Tôi nghĩ rằng nó để lại phong cách ứng dụng của tôi đúng hơn chủ đề dựa trên đó là tốt đẹp. +1
OceanLife

1
Không phải là một giải pháp tốt IMO, I Wanna giữ chủ đề thực tế của tôi cho TextView và chỉ cần thay đổi màu sắc văn bản snakbar ...
issamux

1
Bạn không cần phải xác định android:textColorchủ đề của mình. Đó là một thuộc tính phong cách của TextView. Nếu bạn xác định nó trong chủ đề của mình, bạn sẽ ghi đè màu văn bản của mọi TextViewhoặc màu Buttonkhông chỉ định màu văn bản của nó trong XML. Điều đó cũng xảy ra với thông báo trên thanh nhanh thường lấy màu từ lớp phủ chủ đề tối của nó .
Eugen Pechanec

12

Một cách tiếp cận là sử dụng các nhịp:

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

Với các nhịp, bạn cũng có thể thêm nhiều màu sắc và kiểu bên trong một Snackbar. Đây là một hướng dẫn hay:

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


9

Nếu bạn đã chuyển sang sử dụng androidX com.google.android.material.R.id.snackbar_textthay vì thay android.support.design.R.id.snackbar_textđổi màu văn bản trên thanh nhanh.


Bạn xứng đáng được huy chương.
Frank17

@ Frank17, nó đã được đề cập trong một số bình luận ở đây.
CoolMind

6

Cách duy nhất tôi thấy là sử dụng getView()và đạp xe qua đứa con của nó. Tôi không biết nó có hiệu quả không và nó có tệ như vẻ ngoài của nó. Tôi hy vọng họ sẽ sớm thêm một số API về vấn đề này.

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

Nếu bạn sẽ di chuyển mã của mình sang AndroidX, thuộc tính TextView bây giờ là:

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

2

Đây là những gì tôi sử dụng khi tôi cần màu tùy chỉnh

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

Và được tiêu thụ như:

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

2

Tôi đã thay đổi chủ đề của mình

Theme.AppCompat.Light.NoActionBar

đến

Theme.AppCompat.NoActionBar 

Nó hoạt động. Hãy thử sử dụng chủ đề đơn giản thay vì chủ đề ánh sáng hoặc chủ đề khác.


2

Nếu bạn quyết định sử dụng giải pháp bẩn thỉu và hacky với việc tìm TextView trong Snackbar theo id và bạn đã chuyển sang androidx, thì đây là mã:

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)


1

Tìm theo id không hoạt động với tôi vì vậy tôi đã tìm thấy một giải pháp khác:

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

Sử dụng Snackbarbao gồm trong Thư viện Thành phần Vật liệu và áp dụng

  • setTextColor để xác định màu văn bản
  • setActionTextColorđể xác định màu văn bản được sử dụng bởi hành động. Bạn có thể sử dụng một màu hoặc một bộ chọn màu
  • setBackgroundTint để xác định màu nền của Snackbar

Cái gì đó như:

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

nhập mô tả hình ảnh ở đây


0

Tôi có một mã đơn giản sẽ giúp lấy một phiên bản của cả textview của Snackbar, sau đó bạn có thể gọi tất cả các phương thức có thể áp dụng trên 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

Chỉ để tiết kiệm thời gian phát triển quý báu của bạn, đây là phương pháp tĩnh mà tôi đang sử dụng:

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

Cái này nó thì trông như thế nào:

thanh ăn nhẹ màu vàng với văn bản màu đen


0

Nếu bạn đang ở Kotlin , bạn có thể tạo tiện ích mở rộng:

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
}

Cách sử dụng :

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

cùng câu trả lời như tôi 😉
Richard

0

Theo các thành phần AndroidX Jitpack mới

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

Sử dụng tiện ích mở rộng này mà tôi đã tạo

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

Sử dụng nó như thế này

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

Đây là giải pháp của tôi để giải quyết loại vấn đề này trong androidxviệc sử dụngkotlin

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

Bạn cần khởi tạo phương thức mContentbên trong onViewCreatednhư bên dưới

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

0

Hiện tại (tháng 1 năm 2020) với com.google.android.material:material:1.2.0và có thể cũng1.1.0

Chắc chắn là cách tốt nhất để làm điều đó bằng cách ghi đè các kiểu này:

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

Nếu bạn sử dụng chủ đề material .Bridgeở cuối, vì một số lý do, cả hai kiểu này đều không được xác định. Vì vậy, Snackar sẽ sử dụng một số bố cục kế thừa mà không có các phong cách này.

Tôi đã tìm thấy trong mã nguồn cả hai snackbarButtonStylesnackbarTextViewStylephải được xác định nếu không nó sẽ không được sử dụng.


-1

Tôi cũng nhận thấy vấn đề tương tự. Nhờ các câu trả lời ở đây, tôi đã tạo một lớp nhỏ, có thể giúp giải quyết vấn đề này dễ dàng hơn, chỉ bằng cách thay thế lớp này:

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

Với cái này:

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

Đây là lớp học của tôi:

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
Đây là một cuộc tấn công và dựa vào id của các chế độ xem thư viện hỗ trợ khác nhau là tĩnh. Tôi sẽ tránh giải pháp này bằng mọi giá.
DiscDev
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.