Możesz dostosować widżety Cast, ustawiając kolory, stylizując przyciski, tekst i wygląd miniatury oraz wybierając typy przycisków do wyświetlania.
Dostosowywanie motywu aplikacji
W tym przykładzie tworzymy styl motywu niestandardowego Theme.CastVideosTheme
, który może definiować niestandardowe kolory, styl nakładki wprowadzającej, styl minikontrolera i styl rozwiniętego kontrolera.
<style name="Theme.CastVideosTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Set AppCompat's color theming attrs -->
<item name="colorPrimary">@color/primary</item>
<item name="colorPrimaryDark">@color/primary_dark</item>
<item name="colorAccent">@color/accent</item>
<item name="android:textColorPrimary">@color/primary_text</item>
<item name="android:textColorSecondary">@color/secondary_text</item>
<item name="castIntroOverlayStyle">@style/CustomCastIntroOverlay</item>
<item name="castMiniControllerStyle">@style/CustomCastMiniController</item>
<item name="castExpandedControllerStyle">@style/CustomCastExpandedController</item>
</style>
Ostatnie 3 wiersze powyżej umożliwiają zdefiniowanie stylów specyficznych dla nakładki wprowadzającej, minikontrolera i rozwiniętego kontrolera w ramach tego motywu. Przykłady znajdziesz w dalszej części tego artykułu.
Dostosowywanie przycisku przesyłania
Aby dodać niestandardowy mediaRouteTheme
do motywu aplikacji:
<style name="Theme.CastVideosTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- ... -->
<item name="mediaRouteTheme">@style/CustomMediaRouterTheme</item>
</style>
Zadeklaruj niestandardowy motyw Media Routera i niestandardowy element 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>
setTint
należy używać, jeśli wersja biblioteki pomocy jest nowsza niż 26.0.0. W przypadku starszych wersji biblioteki pomocy użyj buttonTint
.
Dostosowywanie motywu nakładki wprowadzającej
Klasa
IntroductoryOverlay
obsługuje różne atrybuty stylu, które aplikacja może zastąpić w niestandardowym motywie. Ten przykład pokazuje, jak zastąpić wygląd tekstu zarówno przycisku, jak i tytułu w widżecie nakładki:
<style name="CustomCastIntroOverlay" parent="CastIntroOverlay">
<item name="castButtonTextAppearance">@style/TextAppearance.CustomCastIntroOverlay.Button</item>
<item name="castTitleTextAppearance">@style/TextAppearance.CustomCastIntroOverlay.Title</item>
</style>
<style name="TextAppearance.CustomCastIntroOverlay.Button" parent="android:style/TextAppearance">
<item name="android:textColor">#FFFFFF</item>
</style>
<style name="TextAppearance.CustomCastIntroOverlay.Title"parent="android:style/TextAppearance.Large">
<item name="android:textColor">#FFFFFF</item>
</style>
Dostosowywanie minikontrolera
Dostosowanie motywu
Klasa
MiniControllerFragment
obsługuje różne atrybuty stylu, które aplikacja może zastąpić w niestandardowym motywie. Ten przykład pokazuje, jak włączyć wyświetlanie miniatury, zastąpić wygląd tekstu podtytułu i napisów, ustawić kolory i dostosować przyciski:
<style name="CustomCastMiniController" parent="CastMiniController">
<item name="castShowImageThumbnail">true</item>
<item name="castTitleTextAppearance">@style/TextAppearance.AppCompat.Subhead</item>
<item name="castSubtitleTextAppearance">@style/TextAppearance.AppCompat.Caption</item>
<item name="castBackground">#FFFFFF</item>
<item name="castProgressBarColor">#FFFFFF</item>
<item name="castPlayButtonDrawable">@drawable/cast_ic_mini_controller_play</item>
<item name="castPauseButtonDrawable">@drawable/cast_ic_mini_controller_pause</item>
<item name="castStopButtonDrawable">@drawable/cast_ic_mini_controller_stop</item>
<item name="castLargePlayButtonDrawable">@drawable/cast_ic_mini_controller_play_large</item>
<item name="castLargePauseButtonDrawable">@drawable/cast_ic_mini_controller_pause_large</item>
<item name="castLargeStopButtonDrawable">@drawable/cast_ic_mini_controller_stop_large</item>
<item name="castSkipPreviousButtonDrawable">@drawable/cast_ic_mini_controller_skip_prev</item>
<item name="castSkipNextButtonDrawable">@drawable/cast_ic_mini_controller_skip_next</item>
<item name="castRewind30ButtonDrawable">@drawable/cast_ic_mini_controller_rewind30</item>
<item name="castForward30ButtonDrawable">@drawable/cast_ic_mini_controller_forward30</item>
<item name="castMuteToggleButtonDrawable">@drawable/cast_ic_mini_controller_mute</item>
<item name="castClosedCaptionsButtonDrawable">@drawable/cast_ic_mini_controller_closed_caption</item
</style>
Wybierz przyciski
MiniControllerFragment
ma 3 miejsca, w których może wyświetlać okładkę albumu, i 2 przyciski lub 3 przyciski sterujące, jeśli okładka albumu nie jest wypełniona.
SLOT SLOT SLOT
1 2 3
Domyślnie fragment zawiera przycisk przełączania odtwarzania/wstrzymywania. Programiści mogą użyć atrybutu castControlButtons
, aby zastąpić wyświetlane przyciski.
Obsługiwane przyciski sterujące są zdefiniowane jako zasoby identyfikatorów:
Typ przycisku | Opis |
---|---|
@id/cast_button_type_empty |
Nie umieszczaj przycisku w tym miejscu |
@id/cast_button_type_custom |
Przycisk niestandardowy |
@id/cast_button_type_play_pause_toggle |
Przełącza między odtwarzaniem i wstrzymaniem |
@id/cast_button_type_skip_previous |
Przejście do poprzedniego elementu w kolejce |
@id/cast_button_type_skip_next |
Przejście do następnego elementu w kolejce |
@id/cast_button_type_rewind_30_seconds |
przewija odtwarzanie o 30 sekund do tyłu; |
@id/cast_button_type_forward_30_seconds |
Przewija odtwarzanie o 30 sekund do przodu |
@id/cast_button_type_mute_toggle |
Wycisza i wyłącza wyciszenie odbiornika |
@id/cast_button_type_closed_caption |
Otwiera okno wyboru ścieżek tekstowych i audio |
Oto przykład, w którym w kolejności od lewej do prawej użyto okładki albumu, przycisku odtwarzania/wstrzymywania i przycisku przewijania do przodu:
<array name="cast_mini_controller_control_buttons">
<item>@id/cast_button_type_empty</item>
<item>@id/cast_button_type_play_pause_toggle</item>
<item>@id/cast_button_type_forward_30_seconds</item>
</array>
...
<fragment
android:id="@+id/cast_mini_controller"
...
app:castControlButtons="@array/cast_mini_controller_control_buttons"
class="com.google.android.gms.cast.framework.media.widget.MiniControllerFragment">
Ostrzeżenie: ta tablica musi zawierać dokładnie 3 elementy. W przeciwnym razie zostanie zgłoszony wyjątek w czasie działania. Jeśli nie chcesz wyświetlać przycisku w miejscu docelowym, użyj kodu
@id/cast_button_type_empty
.
Dodawanie niestandardowych przycisków
Obiekt MiniControllerFragment
umożliwia dodawanie niestandardowych przycisków sterujących, które nie są dostępne w pakiecie SDK, np. przycisku „Lubię to”. Kroki:
Określ miejsce na przycisk niestandardowy, używając
@id/cast_button_type_custom
w atrybuciecastControlButtons
elementuMiniControllerFragment
.Zaimplementuj podklasę
UIController
. InterfejsUIController
zawiera metody wywoływane przez pakiet SDK, gdy zmieni się stan sesji przesyłania lub sesji multimedialnej. Twoja podklasaUIController
powinna przyjmowaćImageView
jako jeden z parametrów i w razie potrzeby aktualizować jego stan.Utwórz podklasę
MiniControllerFragment
, a następnie zastąponCreateView
i wywołajgetButtonImageViewAt(int)
, aby uzyskaćImageView
dla tego niestandardowego przycisku. Następnie wywołaj funkcjębindViewToUIController(View, UIController)
aby powiązać widok z niestandardowymUIController
.Więcej informacji o obsłudze działania z poziomu przycisku niestandardowego znajdziesz w artykule Dodawanie działań niestandardowych.
MediaIntentReceiver
Oto przykład przypisywania przycisku w slocie 2 do elementu
UIController
o nazwieMyCustomUIController
:
// arrays.xml
<array name="cast_expanded_controller_control_buttons">
<item>@id/cast_button_type_empty</item>
<item>@id/cast_button_type_rewind_30_seconds</item>
<item>@id/cast_button_type_custom</item>
<item>@id/cast_button_type_empty</item>
</array>
// MyCustomUIController.kt class MyCustomUIController(private val mView: View) : UIController() { override fun onMediaStatusUpdated() { // Update the state of mView based on the latest the media status. ... mView.visibility = View.INVISIBLE ... } } // MyMiniControllerFragment.kt class MyMiniControllerFragment : MiniControllerFragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { super.onCreateView(inflater, container, savedInstanceState) val customButtonView = getButtonImageViewAt(2) val myCustomUiController = MyCustomUIController(customButtonView) uiMediaController.bindViewToUIController(customButtonView, myCustomUiController) ... } }
// MyCustomUIController.java class MyCustomUIController extends UIController { private final View mView; public MyCustomUIController(View view) { mView = view; } @Override public onMediaStatusUpdated() { // Update the state of mView based on the latest the media status. ... mView.setVisibility(View.INVISIBLE); ... } } // MyMiniControllerFragment.java class MyMiniControllerFragment extends MiniControllerFragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { super.onCreateView(inflater, container, savedInstanceState); ImageView customButtonView = getButtonImageViewAt(2); MyCustomUIController myCustomUiController = new MyCustomUIController(customButtonView); getUIMediaController().bindViewToUIController(customButtonView, myCustomUiController); ... } }
Dostosowywanie rozszerzonego kontrolera
Dostosowanie motywu
Jeśli rozwinięty kontroler aktywności korzysta z paska narzędzi z ciemnym motywem, możesz ustawić motyw paska narzędzi, aby używać jasnego tekstu i jasnego koloru ikony:
<style name="Theme.CastVideosTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="castExpandedControllerToolbarStyle">
@style/ThemeOverlay.AppCompat.Dark.ActionBar
</item>
</style>
Możesz określić własne obrazy, które będą używane do rysowania przycisków na rozwiniętym kontrolerze:
<style name="CustomCastExpandedController" parent="CastExpandedController">
<item name="castButtonColor">@null</item>
<item name="castPlayButtonDrawable">@drawable/cast_ic_expanded_controller_play</item>
<item name="castPauseButtonDrawable">@drawable/cast_ic_expanded_controller_pause</item>
<item name="castStopButtonDrawable">@drawable/cast_ic_expanded_controller_stop</item>
<item name="castSkipPreviousButtonDrawable">@drawable/cast_ic_expanded_controller_skip_previous</item>
<item name="castSkipNextButtonDrawable">@drawable/cast_ic_expanded_controller_skip_next</item>
<item name="castRewind30ButtonDrawable">@drawable/cast_ic_expanded_controller_rewind30</item>
<item name="castForward30ButtonDrawable">@drawable/cast_ic_expanded_controller_forward30</item>
</style>
Wybierz przyciski
Rozszerzony kontroler ma 5 miejsc na przyciski sterujące. Środkowe gniazdo zawsze zawiera przycisk przełączania odtwarzania i pauzy i nie można go konfigurować. Pozostałe 4 miejsca są konfigurowane od lewej do prawej przez aplikację nadawcy.
SLOT SLOT PLAY/PAUSE SLOT SLOT
1 2 BUTTON 3 4
Domyślnie w tych 4 miejscach od lewej do prawej wyświetlają się przycisk napisów, przycisk pomijania do poprzedniego elementu, przycisk pomijania do następnego elementu i przycisk przełączania wyciszenia. Deweloperzy mogą używać atrybutu castControlButtons
, aby zastąpić przyciski, które mają być wyświetlane w poszczególnych miejscach. Lista obsługiwanych przycisków sterujących jest zdefiniowana jako zasoby identyfikatorów identyczne z typami przycisków mini kontrolera.
Oto przykład, w którym przycisk przewijania do tyłu znajduje się w drugim slocie, przycisk przewijania do przodu w trzecim slocie, a pierwszy i ostatni slot są puste:
// arrays.xml
<array name="cast_expanded_controller_control_buttons">
<item>@id/cast_button_type_empty</item>
<item>@id/cast_button_type_rewind_30_seconds</item>
<item>@id/cast_button_type_forward_30_seconds</item>
<item>@id/cast_button_type_empty</item>
</array>
...
// styles.xml
<style name="Theme.MyTheme">
<item name="castExpandedControllerStyle">
@style/CustomCastExpandedController
</item>
</style>
...
<style name="CustomCastExpandedController" parent="CastExpandedController">
<item name="castControlButtons">
@array/cast_expanded_controller_control_buttons
</item>
</style>
Tablica musi zawierać dokładnie 4 elementy. W przeciwnym razie zostanie zgłoszony wyjątek czasu działania. Jeśli nie chcesz wyświetlać przycisku w miejscu docelowym, użyj kodu
@id/cast_button_type_empty
. CastContext
może zarządzać cyklem życia i sposobem prezentacji tej aktywności.
Dodawanie niestandardowych przycisków
ExpandedControllerActivity
umożliwia dodawanie niestandardowych przycisków sterujących, które nie są dostępne w pakiecie SDK, np. przycisku „Lubię to”. Kroki:
Określ miejsce na przycisk niestandardowy, używając
@id/cast_button_type_custom
w atrybuciecastControlButtons
elementuExpandedControllerActivity
. Następnie możesz użyć kodugetButtonImageViewAt(int)
do uzyskania koduImageView
dla tego niestandardowego przycisku.Zaimplementuj podklasę
UIController
.UIController
zawiera metody wywoływane przez pakiet SDK, gdy zmieni się stan sesji przesyłania lub sesji multimedialnej. PodklasaUIController
powinna przyjmować jako jeden z parametrów obiektImageView
i w razie potrzeby aktualizować jego stan.Utwórz podklasę ExpandedControllerActivity, a następnie zastąp
onCreate
i wywołajgetButtonImageViewAt(int)
, aby uzyskać obiekt widoku przycisku. Następnie wywołajbindViewToUIController(View, UIController)
aby powiązać widok z niestandardowymUIController
.Więcej informacji o obsłudze działania z poziomu przycisku niestandardowego znajdziesz w sekcji Dodawanie działań niestandardowych.
MediaIntentReceiver
Oto przykład przypisywania przycisku w slocie 2 do elementu UIController
o nazwie MyCustomUIController
:
// arrays.xml
<array name="cast_expanded_controller_control_buttons">
<item>@id/cast_button_type_empty</item>
<item>@id/cast_button_type_rewind_30_seconds</item>
<item>@id/cast_button_type_custom</item>
<item>@id/cast_button_type_empty</item>
</array>
// MyCustomUIController.kt class MyCustomUIController(private val mView: View) : UIController() { override fun onMediaStatusUpdated() { // Update the state of mView based on the latest the media status. ... mView.visibility = View.INVISIBLE ... } } // MyExpandedControllerActivity.kt internal class MyExpandedControllerActivity : ExpandedControllerActivity() { public override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val customButtonView = getButtonImageViewAt(2) val myCustomUiController = MyCustomUIController(customButtonView) uiMediaController.bindViewToUIController(customButtonView, myCustomUiController) ... } }
// MyCustomUIController.java class MyCustomUIController extends UIController { private final View mView; public MyCustomUIController(View view) { mView = view; } @Override public onMediaStatusUpdated() { // Update the state of mView based on the latest the media status. ... mView.setVisibility(View.INVISIBLE); ... } } // MyExpandedControllerActivity.java class MyExpandedControllerActivity extends ExpandedControllerActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ImageView customButtonView = getButtonImageViewAt(2); MyCustomUIController myCustomUiController = new MyCustomUIController(customButtonView); getUIMediaController().bindViewToUIController(customButtonView, myCustomUiController); ... } }