I'm using Google's method to add a Cast button to my app, but it's defaulted to the white icon, which is invisible against my white menu bar. How do I go about changing the color of the Cast icon to black?
8 Answers
I've just extended MediaRouteActionProvider like this:
public class ThemeableMediaRouteActionProvider extends MediaRouteActionProvider {
public ThemeableMediaRouteActionProvider(Context context) {
super(context);
}
@Override
public MediaRouteButton onCreateMediaRouteButton() {
MediaRouteButton button = super.onCreateMediaRouteButton();
colorWorkaroundForCastIcon(button);
return button;
}
@Nullable
@Override
public MediaRouteButton getMediaRouteButton() {
MediaRouteButton button = super.getMediaRouteButton();
colorWorkaroundForCastIcon(button);
return button;
}
private void colorWorkaroundForCastIcon(MediaRouteButton button) {
if (button == null) return;
Context castContext = new ContextThemeWrapper(getContext(), androidx.mediarouter.R.style.Theme_MediaRouter);
TypedArray a = castContext.obtainStyledAttributes(null, androidx.mediarouter.R.styleable.MediaRouteButton, androidx.mediarouter.R.attr.mediaRouteButtonStyle, 0);
Drawable drawable = a.getDrawable(androidx.mediarouter.R.styleable.MediaRouteButton_externalRouteEnabledDrawable);
a.recycle();
DrawableCompat.setTint(drawable, getContext().getResources().getColor(R.color.primary));
drawable.setState(button.getDrawableState());
button.setRemoteIndicatorDrawable(drawable);
}
}
R.color.primary is what color i wanted.
then just replace actionProviderClass in menu from MediaRouteActionProvider to your like that:
<item
android:id="@+id/media_route_menu_item"
android:title="@string/media_route_menu_title"
bwq:actionProviderClass="tv.test.playback.chromecast.ThemeableMediaRouteActionProvider"
bwq:showAsAction="always">
</item>
-
I tried this official solution ([https://developers.google.com/cast/docs/android_sender_advanced#customize_cast_button](https://developers.google.com/cast/docs/android_sender_advanced#customize_cast_button)) but suddenly it stopped working. So, I found your clever solution and I really like it as a temporary fix, thanks :) – hannojg Dec 05 '17 at 21:52
-
1This is the best solution if you are using CastButtonFactory and just need to apply tint – Marek Teuchner May 31 '18 at 13:25
The official answer is here:
https://developers.google.com/cast/docs/android_sender/customize_ui#customize_cast_button
Customize Cast Button
To add a custom
mediaRouteTheme
to your app's Theme:<style name="Theme.CastVideosTheme" parent="Theme.AppCompat.Light.NoActionBar"> <!-- ... --> <item name="mediaRouteTheme">@style/CustomMediaRouterTheme</item> </style>
Declare your custom Media Router theme and declare a custom
mediaRouteButtonStyle
:<style name="CustomMediaRouterTheme" parent="Theme.MediaRouter"> <item name="mediaRouteButtonStyle">@style/CustomMediaRouteButtonStyle</item> </style> <style name="CustomMediaRouteButtonStyle" parent="Widget.MediaRouter.Light.MediaRouteButton"> <item name="mediaRouteButtonTint">#EEFF41</item> </style>
mediaRouteButtonTint
should be used if the support library version is newer than 26.0.0. For older support library versions, please usebuttonTint
instead.

- 7,549
- 8
- 45
- 86
If you have a one color for the cast icon for a view use a theme for the fragment or activity.
<item name="mediaRouteButtonTint">@color/red</item>
If you want to programmatically set the color use the following code.
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/menu_item"
android:title="@string/media_route_menu_title"
app:actionProviderClass="androidx.mediarouter.app.MediaRouteActionProvider" />
</menu>
import androidx.core.content.ContextCompat
import androidx.appcompat.view.ContextThemeWrapper
import androidx.core.graphics.drawable.DrawableCompat
...
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater?) {
val tintColor = ContextCompat.getColor(context, R.color.my_color)
val item = menu.findItem(R.id.menu_item)
val button = item.actionView
val castContext = ContextThemeWrapper(context, androidx.mediarouter.R.style.Theme_MediaRouter)
val attrs = castContext.obtainStyledAttributes(null, androidx.mediarouter.R.styleable.MediaRouteButton, androidx.mediarouter.R.attr.mediaRouteButtonStyle, 0)
val drawable = attrs.getDrawable(androidx.mediarouter.R.styleable.MediaRouteButton_externalRouteEnabledDrawable)
attrs.recycle()
DrawableCompat.setTint(drawable, tintColor)
drawable.state = button.getDrawableState()
button.setRemoteIndicatorDrawable(drawable)

- 3,942
- 2
- 25
- 21
I extended MediaRouteButton. See code below. Then I can just call applyTint() and it applies the color to all states of the RemoteIndicatorDrawable
public class ColorableMediaRouteButton extends MediaRouteButton {
protected Drawable mRemoteIndicatorDrawable;
public ColorableMediaRouteButton(Context context) {
super(context);
}
public ColorableMediaRouteButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ColorableMediaRouteButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public void setRemoteIndicatorDrawable(Drawable d) {
mRemoteIndicatorDrawable = d;
super.setRemoteIndicatorDrawable(d);
}
public void applyTint(int color) {
Drawable wrapDrawable = DrawableCompat.wrap(mRemoteIndicatorDrawable);
DrawableCompat.setTint(wrapDrawable, color);
}
}

- 472
- 4
- 12
-
This worked great, but I was seeing a NPE being thrown when I attempted to apply the color tint right away. Simply calling, `your_button_view.post() -> { your_button_view.applyTint(color); });` will resolve it as it will trigger as soon as the `setRemoteIndicatorDrawable()` finishes its received drawable. – PGMacDesign Oct 20 '20 at 06:23
If it is just due to the style (dark vs light), you should be fine if the style is defined correctly (i.e. extending the right theme in terms of dark vs light). For general styling, check out this post and if that doesn't solve your issue, come back and let us know.

- 1
- 1

- 16,951
- 2
- 21
- 28
-
Thanks! Managed to fix it by changing the theme to Theme.AppCompat.Light. However, this changed the default text color in my app to black. How can I override it to set the default text color back to white? – opticon Jun 19 '14 at 18:35
-
Sounds like you have some conflicting styling. Theme.AppCompat.Light means you are using a light theme, hence text of colors turn into black to make them visible on light background. If your background theme is dark, then you shouldn't use that theme. If you can't fix the theme due to requirements that you have, you then need to use the other approach in that same post in terms of providing the PNG's for the appropriate color or putting the xml in your app but switching the pointers to dar vs light. – Ali Naddaf Jun 19 '14 at 18:46
I experienced this issue myself, and solved it by changing the android:theme
and app:popuptheme
values to @style/ThemeOverlay.AppCompat.Dark.ActionBar
.
See example code below:
<android.support.v7.widget.Toolbar
android:id="@+id/my_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="#4dffffff"
android:elevation="4dp"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"/>

- 4,241
- 10
- 40
- 81

- 566
- 7
- 20
Absolutely simple answer's here:
https://developers.google.com/cast/docs/android_sender_advanced#customize_cast_button
So just copy mediaRouteTheme from that link to your app's theme and next two styles to the styles.xml.

- 21
- 1
- 4
If none of the above solution work, try what has been explained here. You might need to use the colorFilter property instead of tint.
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.some_menu, menu);
setColorForCast(menu);
}
private void setColorForCast(@NonNull Menu menu) {
MediaRouteButton castButton = (MediaRouteButton) menu.findItem(R.id.cast_button).getActionView();
if (castButton != null) {
Drawable drawable = getResources().getDrawable(R.drawable.chromecast);
int color = ContextCompat.getColor(getContext(), R.color.colorPrimary);
drawable.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
drawable.setState(castButton.getDrawableState());
castButton.setRemoteIndicatorDrawable(drawable);
}
}

- 579
- 2
- 10
- 30