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, mit dem benutzerdefinierte Farben, ein Stil für das Einführungs-Overlay, ein Stil für die Mini-Steuerung und ein Stil für die erweiterte Steuerung 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>

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

Cast-Schaltfläche anpassen

So fügen Sie dem Theme Ihrer App ein benutzerdefiniertes mediaRouteTheme hinzu:

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

Deklarieren Sie Ihr benutzerdefiniertes Media Router-Design und eine benutzerdefinierte 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 Versionen der Support-Bibliothek 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 Textes 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

Ein MiniControllerFragment hat drei Slots, in denen das Albumcover und zwei Schaltflächen angezeigt werden können. Wenn das Albumcover nicht ausgefüllt ist, werden drei Steuerungsschaltflächen angezeigt.

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 Steuerelemente sind als ID-Ressourcen definiert:

Schaltflächenart Beschreibung
@id/cast_button_type_empty In diesem Bereich darf keine Schaltfläche platziert werden
@id/cast_button_type_custom Benutzerdefinierte Schaltfläche
@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 Spielt 30 Sekunden vor
@id/cast_button_type_mute_toggle Stummschaltung des Empfängers und Aufhebung der Stummschaltung
@id/cast_button_type_closed_caption Öffnet ein Dialogfeld, in dem Sie Text- und Audio-Tracks auswählen können.

Hier ist ein Beispiel, in dem das Albumcover, eine Ein/Aus-Schaltfläche für die Wiedergabe/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 Laufzeit-Ausnahme 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 einen Slot für eine benutzerdefinierte Schaltfläche mit @id/cast_button_type_custom im Attribut castControlButtons des MiniControllerFragment 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 Mediensitzung ändert. Ihre Unterklasse von UIController sollte ein ImageView als einen der Parameter verwenden und ihren Status nach Bedarf aktualisieren.

  3. Erstelle eine Unterklasse von MiniControllerFragment, überschreibe dann onCreateView und rufe 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. Informationen dazu, wie Sie die Aktion über Ihre benutzerdefinierte Schaltfläche verarbeiten, finden Sie unter Benutzerdefinierte Aktionen hinzufügen im Abschnitt MediaIntentReceiver.

    Hier sehen Sie 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 für die Aktivität eines maximierten 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

Der maximierte Controller hat fünf Slots für Steuertasten. Im mittleren Slot wird immer eine Ein/Aus-Schaltfläche für die Wiedergabe angezeigt. Er kann nicht konfiguriert werden. 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 der Aktivität in diesen vier Slots von links nach rechts eine Schaltfläche für Untertitel, eine Schaltfläche zum Überspringen zum vorherigen Element, eine Schaltfläche zum Überspringen zum nächsten Element und eine Schaltfläche 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, bei dem die Schaltfläche zum Zurückspulen im zweiten Slot und die Schaltfläche zum Überspringen im dritten Slot platziert wird. 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 Laufzeit-Ausnahme 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 Steuerungsschaltflächen hinzufügen, die nicht vom SDK bereitgestellt werden, z. B. eine Schaltfläche „Mag ich“. Folgende Schritte sind auszuführen:

  1. Geben Sie einen Slot für eine benutzerdefinierte Schaltfläche mit @id/cast_button_type_custom im Attribut castControlButtons des ExpandedControllerActivity 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- oder Mediensitzung ändert. Ihre Unterklasse von UIController sollte ein ImageView als einen der Parameter annehmen und ihren Status nach Bedarf aktualisieren.

  3. Erstellen Sie eine Unterklasse von ExpandedControllerActivity, überschreiben Sie onCreate und rufen Sie 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. Informationen dazu, wie Sie die Aktion über Ihre benutzerdefinierte Schaltfläche ausführen, finden Sie unter Benutzerdefinierte Aktionen hinzufügen im Abschnitt MediaIntentReceiver.

Hier sehen Sie 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
        ...
    }
}

// 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);
        ...
    }
}