Dostosowanie interfejsu nadawcy w Androidzie

Możesz dostosować widżety przesyłania, ustawiając kolory, styl przycisków, tekst i wygląd miniatur oraz wybierając typy wyświetlanych przycisków.

Dostosuj motyw aplikacji

Ten przykład tworzy niestandardowy styl motywu Theme.CastVideosTheme, który może definiować kolory niestandardowe, styl nakładki wprowadzającej, styl minikontrolera i rozwinięty styl 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 powitalnej, minikontrolera i rozszerzonego kontrolera w ramach tego motywu. W poniższych sekcjach znajdziesz przykłady.

Dostosuj przycisk Cast

Aby dodać niestandardowy element mediaRouteTheme do motywu aplikacji:

<style name="Theme.CastVideosTheme" parent="Theme.AppCompat.Light.NoActionBar">
  <!-- ... -->
  <item name="mediaRouteTheme">@style/CustomMediaRouterTheme</item>
</style>

Zadeklaruj niestandardowy motyw routera multimediów i zadeklaruj niestandardowy 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 biblioteka pomocy w wersji nowszej niż 26.0.0. W przypadku starszych wersji biblioteki pomocy użyj buttonTint.

Dostosuj wprowadzający motyw nakładki

Klasa IntroductoryOverlay obsługuje różne atrybuty stylu, które aplikacja może zastąpić w motywie niestandardowym. Ten przykład pokazuje, jak zastąpić wygląd tekstu przycisku 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>

Dostosuj minikontroler

Dostosowanie motywu

Klasa MiniControllerFragment obsługuje różne atrybuty stylu, które aplikacja może zastąpić w motywie niestandardowym. Ten przykład pokazuje, jak włączyć wyświetlanie miniatury, zastąpić wygląd tekstu zarówno podtytułu, jak 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 boksy, na których można wyświetlać okładkę albumu i 2 przyciski. Jeśli okładka albumu nie jest wypełniona, to 3 przyciski sterujące.

SLOT  SLOT  SLOT
  1     2     3

Domyślnie fragment zawiera przycisk przełączania odtwarzania/wstrzymania. Deweloperzy mogą użyć atrybutu castControlButtons, aby zastąpić przyciski, które mają być wyświetlane. Obsługiwane przyciski sterujące są zdefiniowane jako zasoby identyfikatora:

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 wstrzymywaniem
@id/cast_button_type_skip_previous Przechodzi do poprzedniego elementu w kolejce
@id/cast_button_type_skip_next Przechodzi do następnego elementu w kolejce
@id/cast_button_type_rewind_30_seconds Przewija odtwarzanie do tyłu o 30 sekund.
@id/cast_button_type_forward_30_seconds Przeskoczy o 30 sekund do przodu.
@id/cast_button_type_mute_toggle Wycisza i wyłącza wyciszenie odbiorcy.
@id/cast_button_type_closed_caption Otwiera okno wyboru ścieżek tekstowych i audio

Oto przykład, w którym możemy użyć okładki albumu, przycisku przełączania odtwarzania/wstrzymywania i przycisku przewijania do przodu w tej kolejności od lewej do prawej:

<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 środowiska wykonawczego. Jeśli nie chcesz wyświetlać przycisku w boksie, użyj właściwości @id/cast_button_type_empty.

Dodawanie przycisków niestandardowych

MiniControllerFragment umożliwia dodawanie niestandardowych przycisków sterujących, które nie są dostępne w pakiecie SDK, takich jak przycisk kciuka w górę. Kroki:

  1. Określ boks, w którym będzie umieszczony przycisk niestandardowy, za pomocą parametru @id/cast_button_type_custom w atrybucie castControlButtons elementu MiniControllerFragment.

  2. Zaimplementuj podklasę UIController. UIController zawiera metody wywoływane przez pakiet SDK po zmianie stanu sesji przesyłania lub sesji multimediów. Twoja podklasa UIController powinna przyjąć ImageView jako jeden z parametrów i w razie potrzeby aktualizować jej stan.

  3. Podklasę MiniControllerFragment, zastąp ją onCreateView i wywołaj getButtonImageViewAt(int), aby uzyskać przycisk ImageView dla tego niestandardowego przycisku. Następnie wywołaj bindViewToUIController(View, UIController), aby powiązać widok z niestandardowym UIController.

  4. Opis obsługi działań z przycisku niestandardowego znajdziesz w sekcji dotyczącej MediaIntentReceiver w artykule Dodawanie działań niestandardowych.

    Oto przykład powiązania przycisku w boksie 2 z 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>
Kotlin
// 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)
        ...
    }
}
Java
// 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);
        ...
    }
}

Dostosuj rozwinięty kontroler

Dostosowanie motywu

Jeśli aktywność na rozwiniętym kontrolerze korzysta z paska narzędzi z ciemnym motywem, możesz ustawić na nim jasny tekst i jasny kolor 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

Aktywność rozwiniętego kontrolera ma 5 przedziałów na przyciski sterujące. W środkowym boksie zawsze znajduje się przycisk przełączania odtwarzania/wstrzymania. Nie można go konfigurować. Pozostałe 4 boksy można skonfigurować (od lewej do prawej) przez aplikację nadawcy.

SLOT  SLOT  PLAY/PAUSE  SLOT  SLOT
  1     2     BUTTON      3     4

Domyślnie aktywność wyświetla przycisk napisów, przycisk przejścia do poprzedniego elementu, przycisk przejścia do następnego elementu oraz przycisk przełączania wyciszenia w tych 4 boksach, od lewej do prawej. Deweloperzy mogą użyć atrybutu castControlButtons, aby zastąpić przyciski, które mają być wyświetlane w poszczególnych boksach. Lista obsługiwanych przycisków sterowania jest zdefiniowana jako zasoby identyfikatorów identyczne z typami przycisków dla przycisków minikontrolera.

Oto przykład, w którym umieszcza się przycisk przewijania do tyłu w drugim boksie, a w trzecim – przycisk przewijania do przodu, a pierwsze i ostatnie miejsce jest 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 środowiska wykonawczego. Jeśli nie chcesz wyświetlać przycisku w boksie, użyj właściwości @id/cast_button_type_empty. CastContext może zarządzać cyklem życia i prezentacją tej aktywności.

Dodawanie przycisków niestandardowych

ExpandedControllerActivity umożliwia dodawanie niestandardowych przycisków sterujących, które nie są dostępne w pakiecie SDK, takich jak przycisk „kciuk w górę”. Kroki:

  1. Określ boks, w którym będzie umieszczony przycisk niestandardowy, za pomocą parametru @id/cast_button_type_custom w atrybucie castControlButtons elementu ExpandedControllerActivity. Następnie możesz użyć parametru getButtonImageViewAt(int), aby uzyskać przycisk ImageView dla tego przycisku niestandardowego.

  2. Zaimplementuj podklasę UIController. UIController zawiera metody wywoływane przez pakiet SDK po zmianie stanu sesji przesyłania lub multimediów. Podklasa UIController powinna przyjmować jako jeden z parametrów ImageView i w razie potrzeby aktualizować jej stan.

  3. Podklasa ExtendedControllerActivity, a następnie zastąp onCreate i wywołaj getButtonImageViewAt(int), aby uzyskać obiekt widoku przycisku. Następnie wywołaj bindViewToUIController(View, UIController), aby powiązać widok z niestandardowym elementem UIController.

  4. Informacje o obsłudze działań przycisku niestandardowego znajdziesz w sekcji dotyczącej MediaIntentReceiver w artykule Dodawanie działań niestandardowych.

Oto przykład powiązania przycisku w boksie 2 z 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>
Kotlin
// 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)
        ...
    }
}
Java
// 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);
        ...
    }
}