Dostosowanie interfejsu nadawcy w Androidzie

Możesz dostosować widżety przesyłania, ustawiając kolory, styl przycisków, tekst i wygląd miniatur, a także wybierając typy przycisków, które mają być wyświetlane.

Dostosuj motyw aplikacji

W tym przykładzie tworzymy styl motywu niestandardowego Theme.CastVideosTheme, który może określać kolory niestandardowe, początkowy styl nakładki, 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 pozwalają zdefiniować style charakterystyczne dla nakładki wprowadzającej, minikontrolera i rozwiniętego kontrolera. Przykłady podano w sekcjach poniżej.

Dostosuj przycisk Cast

Aby dodać niestandardowy obiekt 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>

Opcji setTint należy używać, jeśli biblioteka pomocy jest w wersji nowszej niż 26.0.0. W przypadku starszych wersji biblioteki pomocy użyj zamiast tego buttonTint.

Dostosuj motyw nakładki wprowadzającej

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 na 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. Z tego przykładu dowiesz się, 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 gniazda, w których można wyświetlić okładkę albumu i 2 przyciski. Jeśli okładka albumu nie jest wypełniona, 3 przyciski sterujące.

SLOT  SLOT  SLOT
  1     2     3

Domyślnie we fragmencie znajduje się przycisk przełączania odtwarzania/wstrzymania. Deweloperzy mogą użyć atrybutu castControlButtons, aby zastąpić, które przyciski mają być widoczne. 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 Przewija odtwarzanie do przodu o 30 sekund.
@id/cast_button_type_mute_toggle Wycisza i wyłącza wyciszenie odbiornika
@id/cast_button_type_closed_caption Otwiera okno wyboru ścieżki tekstu i ścieżki audio

Oto przykład, w którym okładka albumu, przycisk przełączania odtwarzania/wstrzymywania i przycisk przechodzenia 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 danym boksie, użyj @id/cast_button_type_empty.

Dodaj przyciski niestandardowe

MiniControllerFragment umożliwia dodawanie niestandardowych przycisków sterujących, których nie udostępnia pakiet SDK, np. przycisku „kciuk w górę”. Kroki:

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

  2. Zaimplementuj podklasę UIController. Obiekt UIController zawiera metody wywoływane przez pakiet SDK w przypadku zmiany stanu sesji przesyłania lub sesji multimediów. Twoja podklasa klasy UIController powinna przyjmować ImageView jako jeden z parametrów i aktualizować swój stan zgodnie z potrzebami.

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

  4. Instrukcje obsługi działań z przycisku niestandardowego znajdziesz w sekcji MediaIntentReceiver artykułu Dodawanie działań niestandardowych.

    Oto przykład powiązania przycisku w boksie 2 z elementem 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 w sekcji Aktywność na rozwiniętym kontrolerze używany jest pasek narzędzi z ciemnym motywem, możesz ustawić na pasku narzędzi jasny tekst i jasny kolor ikon:

<style name="Theme.CastVideosTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="castExpandedControllerToolbarStyle">
        @style/ThemeOverlay.AppCompat.Dark.ActionBar
    </item>
</style>

Możesz wybrać 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ść na rozwiniętej kontrolerze ma 5 przedziałów, w których wyświetlają się przyciski sterujące. Środkowy boks zawsze zawiera przycisk przełączania odtwarzania/wstrzymywania i nie można go konfigurować. Pozostałe 4 przedziały można skonfigurować przez aplikację nadawcy (od lewej do prawej).

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

Domyślnie w aktywności widać przycisk napisów, przycisk przejścia do poprzedniego elementu, przycisk przejścia do następnego elementu oraz przycisk przełączania wyciszenia w tych 4 miejscach (od lewej do prawej). Deweloperzy mogą użyć atrybutu castControlButtons, aby zastąpić, które przyciski mają się wyświetlać w poszczególnych boksach. Lista obsługiwanych przycisków sterujących jest definiowana jako zasoby identyfikatorów identyczne z typami przycisków minikontrolerów.

Oto przykład, w którym w drugim boksie umieszczamy przycisk przewijania do tyłu, w trzecim – przycisk przechodzenia do przodu, a pierwszy i ostatni boks 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 środowiska wykonawczego. Jeśli nie chcesz wyświetlać przycisku w danym boksie, użyj @id/cast_button_type_empty. CastContext może zarządzać cyklem życia i prezentowaniem tej aktywności.

Dodaj przyciski niestandardowe

ExpandedControllerActivity umożliwia dodawanie niestandardowych przycisków sterujących, których nie udostępnia pakiet SDK, np. przycisku „kciuk w górę”. Kroki:

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

  2. Zaimplementuj podklasę UIController. UIController zawiera metody wywoływane przez pakiet SDK w przypadku zmiany stanu sesji przesyłania lub sesji multimediów. Twoja podklasa klasy UIController powinna przyjmować ImageView jako jeden z parametrów i aktualizować swój stan zgodnie z potrzebami.

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

  4. Instrukcje obsługi działania z przycisku niestandardowego znajdziesz w sekcji MediaIntentReceiver artykułu Dodawanie działań niestandardowych.

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