Android-Benutzeroberfläche für Absender anpassen

Du kannst Cast-Widgets anpassen, indem du die Farben festlegst, die Darstellung von Schaltflächen, Text und Thumbnails gestaltest und die anzuzeigenden Schaltflächentypen auswählst.

App-Design anpassen

In diesem Beispiel wird ein benutzerdefinierter Designstil Theme.CastVideosTheme erstellt, in dem benutzerdefinierte Farben, ein Stil für das Einführungs-Overlay, ein Stil für den Mini-Controller und ein Stil für den erweiterten Controller definiert werden können.

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

In den letzten drei Zeilen oben können Sie Stile für das Intro-Overlay, den Mini-Controller und den erweiterten Controller als Teil dieses Designs definieren. Beispiele finden Sie in den folgenden Abschnitten.

Cast-Button anpassen

So fügen Sie dem Design Ihrer App einen benutzerdefinierten mediaRouteTheme hinzu:

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

Deklariere dein benutzerdefiniertes Media Router-Design und ein benutzerdefiniertes 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 sollte verwendet werden, wenn die Support-Bibliotheksversion neuer als 26.0.0 ist. Für ältere Support-Bibliotheksversionen verwenden Sie stattdessen buttonTint.

Design des Intro-Overlays anpassen

Die Klasse IntroductoryOverlay unterstützt verschiedene Stilattribute, die Ihre App in einem benutzerdefinierten Theme überschreiben kann. In diesem Beispiel wird gezeigt, wie Sie die Darstellung des Texts für die Schaltfläche und den Titel des Overlay-Widgets überschreiben:

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

Mini-Controller anpassen

Design anpassen

Die Klasse MiniControllerFragment unterstützt verschiedene Stilattribute, die Ihre App in einem benutzerdefinierten Theme überschreiben kann. In diesem Beispiel wird gezeigt, wie Sie die Anzeige des Vorschaubilds aktivieren, die Darstellung des Texts für Unterüberschrift und Untertitel überschreiben, die Farben festlegen und die Schaltflächen anpassen:

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

Schaltflächen auswählen

Eine MiniControllerFragment hat drei Slots, in denen das Albumcover und zwei Schaltflächen angezeigt werden können. Wenn das Albumcover nicht angezeigt wird, sind drei Steuerungsschaltflächen vorhanden.

SLOT  SLOT  SLOT
  1     2     3

Standardmäßig wird im Fragment eine Ein/Aus-Schaltfläche für die Wiedergabe/Pause angezeigt. Entwickler können mit dem Attribut castControlButtons festlegen, welche Schaltflächen angezeigt werden sollen. Die unterstützten Steuertasten werden als ID-Ressourcen definiert:

Schaltflächenart Beschreibung
@id/cast_button_type_empty In diesem Slot darf kein Button platziert werden
@id/cast_button_type_custom Benutzerdefinierter Button
@id/cast_button_type_play_pause_toggle Wechselt zwischen Wiedergabe und Pause.
@id/cast_button_type_skip_previous Zum vorherigen Element in der Warteschlange springen
@id/cast_button_type_skip_next Zum nächsten Element in der Warteschlange springen
@id/cast_button_type_rewind_30_seconds Spult die Wiedergabe um 30 Sekunden zurück
@id/cast_button_type_forward_30_seconds Spult die Wiedergabe um 30 Sekunden vor
@id/cast_button_type_mute_toggle Stummschaltung des Empfängers aktivieren oder deaktivieren
@id/cast_button_type_closed_caption Öffnet ein Dialogfeld zum Auswählen von Text- und Audiotracks

Hier ist ein Beispiel, in dem das Albumcover, eine Schaltfläche zum Umschalten zwischen Wiedergabe und Pause und eine Schaltfläche zum Überspringen nach vorn in dieser Reihenfolge von links nach rechts verwendet werden:

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

Warnung: Dieses Array muss genau drei Elemente enthalten. Andernfalls wird eine Laufzeitausnahme ausgelöst. Wenn Sie in einem Slot keine Schaltfläche anzeigen möchten, verwenden Sie @id/cast_button_type_empty.

Benutzerdefinierte Schaltflächen hinzufügen

Mit einem MiniControllerFragment können benutzerdefinierte Steuerungsschaltflächen hinzugefügt werden, die nicht vom SDK bereitgestellt werden, z. B. eine Schaltfläche „Mag ich“. Folgende Schritte sind auszuführen:

  1. Geben Sie mit @id/cast_button_type_custom im Attribut castControlButtons des MiniControllerFragment einen Slot für eine benutzerdefinierte Schaltfläche an.

  2. Implementieren Sie eine abgeleitete Klasse von UIController. Die UIController enthält Methoden, die vom SDK aufgerufen werden, wenn sich der Status der Cast- oder Media Session ändert. Ihre Unterklasse von UIController sollte ein ImageView als einen der Parameter verwenden und ihren Status nach Bedarf aktualisieren.

  3. Erstellen Sie eine Unterklasse von MiniControllerFragment, überschreiben Sie dann onCreateView und rufen Sie getButtonImageViewAt(int) auf, um die ImageView für diese benutzerdefinierte Schaltfläche abzurufen. Rufen Sie dann bindViewToUIController(View, UIController) auf, um die Ansicht mit Ihrem benutzerdefinierten UIController zu verknüpfen.

  4. MediaIntentReceiver Unter Benutzerdefinierte Aktionen hinzufügen finden Sie Informationen dazu, wie Sie die Aktion über die benutzerdefinierte Schaltfläche verarbeiten.

    Hier ist ein Beispiel für die Zuordnung einer Schaltfläche an Position 2 zu einem UIController mit dem Namen 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);
        ...
    }
}

Maximierten Controller anpassen

Design anpassen

Wenn in der Aktivität eines erweiterten Controllers eine Symbolleiste mit dunklem Design verwendet wird, können Sie ein Design für die Symbolleiste festlegen, damit heller Text und eine helle Symbolfarbe verwendet werden:

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

Sie können eigene Bilder angeben, die zum Zeichnen der Schaltflächen auf dem erweiterten Controller verwendet werden:

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

Schaltflächen auswählen

Die erweiterte Controller-Aktivität hat fünf Slots für Steuerungsschaltflächen. Im mittleren Bereich wird immer eine Schaltfläche zum Umschalten zwischen Wiedergabe und Pause angezeigt. Dieser Bereich ist nicht konfigurierbar. Die anderen vier Slots können von der Sender-App von links nach rechts konfiguriert werden.

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

Standardmäßig werden in diesen vier Slots von links nach rechts ein Untertitel-Button, ein Button zum Überspringen zum vorherigen Element, ein Button zum Überspringen zum nächsten Element und ein Button zum Ein- und Ausschalten der Stummschaltung angezeigt. Entwickler können mit dem Attribut castControlButtons festlegen, welche Schaltflächen in welchen Slots angezeigt werden sollen. Die Liste der unterstützten Steuertasten wird als ID-Ressourcen definiert, die mit den Schaltflächentypen für Mini-Controller-Schaltflächen identisch sind.

Hier ist ein Beispiel, in dem eine Zurückspultaste im zweiten Slot und eine Vorspultaste im dritten Slot platziert werden. Der erste und der letzte Slot bleiben leer:

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

Das Array muss genau vier Elemente enthalten. Andernfalls wird eine Laufzeitausnahme ausgelöst. Wenn Sie in einem Slot keine Schaltfläche anzeigen möchten, verwenden Sie @id/cast_button_type_empty. CastContext kann den Lebenszyklus und die Darstellung dieser Aktivität verwalten.

Benutzerdefinierte Schaltflächen hinzufügen

Mit einem ExpandedControllerActivity lassen sich benutzerdefinierte Steuerelement-Schaltflächen hinzufügen, die nicht vom SDK bereitgestellt werden, z. B. eine Schaltfläche „Gefällt mir“. Folgende Schritte sind auszuführen:

  1. Geben Sie mit @id/cast_button_type_custom im Attribut castControlButtons des ExpandedControllerActivity einen Slot für eine benutzerdefinierte Schaltfläche an. Anschließend können Sie getButtonImageViewAt(int) verwenden, um die ImageView für diese benutzerdefinierte Schaltfläche abzurufen.

  2. Implementieren Sie eine abgeleitete Klasse von UIController. UIController enthält Methoden, die vom SDK aufgerufen werden, wenn sich der Status der Cast-Sitzung oder Media Session ändert. Ihre Unterklasse von UIController sollte ImageView als einen der Parameter verwenden und ihren Status nach Bedarf aktualisieren.

  3. Erstelle eine Unterklasse von ExpandedControllerActivity, überschreibe dann onCreate und rufe getButtonImageViewAt(int) auf, um das Ansichtsobjekt der Schaltfläche zu erhalten. Rufen Sie dann bindViewToUIController(View, UIController) auf, um die Ansicht mit Ihrem benutzerdefinierten UIController zu verknüpfen.

  4. Unter Benutzerdefinierte Aktionen hinzufügen finden Sie Informationen dazu, wie Sie die Aktion über Ihre benutzerdefinierte Schaltfläche ausführen.MediaIntentReceiver

Hier ist ein Beispiel für die Zuordnung einer Schaltfläche in Slot 2 zu einem UIController mit dem Namen 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);
        ...
    }
}