Android-Benutzeroberfläche für Absender anpassen

Du kannst Streaming-Widgets anpassen, indem du die Farben festlegst, die Schaltflächen, den Text und das Thumbnail stylst und die angezeigten Schaltflächentypen auswählst.

App-Design anpassen

In diesem Beispiel wird ein benutzerdefinierter Themenstil Theme.CastVideosTheme erstellt, mit dem benutzerdefinierte Farben, ein Einführungs-Overlay-Stil, ein Mini-Controller-Stil und ein erweiterter Controller-Stil 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 Themas definieren. In den folgenden Abschnitten finden Sie Beispiele.

Streamingschaltfläche anpassen

So fügen Sie dem Design Ihrer App eine benutzerdefinierte 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 dein 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 Version der Supportbibliothek höher als 26.0.0 ist. Verwenden Sie für ältere Versionen der Supportbibliothek stattdessen buttonTint.

Design des Einführungs-Overlays anpassen

Die Klasse IntroductoryOverlay unterstützt verschiedene Stilattribute, die in Ihrer App in einem benutzerdefinierten Design überschrieben werden können. In diesem Beispiel wird gezeigt, wie Sie die Textdarstellung sowohl der Schaltfläche als auch des Titels über dem Overlay-Widget ü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 in Ihrer App in einem benutzerdefinierten Design überschrieben werden können. In diesem Beispiel wird gezeigt, wie du die Anzeige des Thumbnails aktivierst, die Textdarstellung sowohl für den Zwischentitel als auch für die Untertitel überschreibst, die Farben festlegst und die Schaltflächen anpasst:

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

Auswahl-Schaltflächen

Ein MiniControllerFragment hat drei Slots, in denen das Albumcover und zwei Schaltflächen angezeigt werden können, oder drei Steuerschaltflächen, wenn das Albumcover nicht vorhanden ist.

SLOT  SLOT  SLOT
  1     2     3

Standardmäßig wird im Fragment eine Schaltfläche zum Ein- und Ausschalten der Wiedergabe angezeigt. Entwickler können mit dem Attribut castControlButtons festlegen, welche Schaltflächen angezeigt werden sollen. Die unterstützten Steuerschaltflächen werden als ID-Ressourcen definiert:

Schaltflächenart Beschreibung
@id/cast_button_type_empty Platzieren Sie keine Schaltfläche in diesem Bereich.
@id/cast_button_type_custom Benutzerdefinierte Schaltfläche
@id/cast_button_type_play_pause_toggle Zwischen Wiedergabe und Pause wechseln
@id/cast_button_type_skip_previous Springt zum vorherigen Element in der Warteschlange
@id/cast_button_type_skip_next Springt zum nächsten Element in der Warteschlange
@id/cast_button_type_rewind_30_seconds Die Wiedergabe wird um 30 Sekunden zurückgespult.
@id/cast_button_type_forward_30_seconds Die Wiedergabe wird um 30 Sekunden vorgespult.
@id/cast_button_type_mute_toggle Stummschaltung des Empfängers
@id/cast_button_type_closed_caption Öffnet ein Dialogfeld zum Auswählen von Text- und Audiotracks

Hier ist ein Beispiel, in dem von links nach rechts in dieser Reihenfolge das Albumcover, eine Schaltfläche zum Ein-/Ausschalten der Wiedergabe und eine Schaltfläche zum Vorspulen 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 lassen möchten, verwenden Sie @id/cast_button_type_empty.

Benutzerdefinierte Schaltflächen hinzufügen

Ein MiniControllerFragment unterstützt das Hinzufügen benutzerdefinierter Steuerelemente, die nicht vom SDK bereitgestellt werden, z. B. eine „Mag ich“-Schaltfläche. Folgende Schritte sind auszuführen:

  1. Geben Sie einen Slot an, der eine benutzerdefinierte Schaltfläche enthalten soll, indem Sie @id/cast_button_type_custom im castControlButtons-Attribut des MiniControllerFragment angeben.

  2. Implementieren Sie eine untergeordnete Klasse von UIController. UIController enthält Methoden, die vom SDK aufgerufen werden, wenn sich der Status der Übertragungs- oder Mediensitzung ändert. Ihre Unterklasse von UIController sollte einen ImageView als einen der Parameter annehmen und den 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 Ihrer benutzerdefinierten UIController zu verknüpfen.

  4. Informationen zum Umgang mit der Aktion Ihrer benutzerdefinierten Schaltfläche finden Sie unter Benutzerdefinierte Aktionen hinzufügen auf Seite MediaIntentReceiver.

    Hier ein Beispiel für die Verknüpfung einer Taste an Steckplatz 2 mit einer UIController namens 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 die Symbolleiste der Aktivität eines maximierten Steuerfelds ein dunkles Design verwendet, können Sie ein Design für die Symbolleiste festlegen, das hellen Text und eine helle Symbolfarbe verwendet:

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

Auswahl-Schaltflächen

Der maximierte Controller hat fünf Slots für Steuerschaltflächen. Im mittleren Slot wird immer eine Schaltfläche zum Ein-/Ausschalten der Wiedergabe angezeigt. Dieser Slot kann nicht konfiguriert werden. Die anderen vier Slots können von der Absender-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 eine Schaltfläche für Untertitel, eine Schaltfläche zum Überspringen des vorherigen Elements, eine Schaltfläche zum Überspringen des nächsten Elements und eine Stummschaltungsschaltfläche angezeigt. Mit dem Attribut castControlButtons können Entwickler 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 Schaltfläche zum Zurückspulen im zweiten Slot und eine 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 Laufzeitausnahme ausgelöst. Wenn Sie in einem Slot keine Schaltfläche anzeigen lassen 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

Eine ExpandedControllerActivity unterstützt das Hinzufügen benutzerdefinierter Steuerelemente, die nicht vom SDK bereitgestellt werden, z. B. eine „Mag ich“-Schaltfläche. Folgende Schritte sind auszuführen:

  1. Geben Sie einen Slot an, der eine benutzerdefinierte Schaltfläche enthalten soll, indem Sie @id/cast_button_type_custom im castControlButtons-Attribut des ExpandedControllerActivity angeben. Anschließend können Sie mit getButtonImageViewAt(int) die ImageView für diese benutzerdefinierte Schaltfläche abrufen.

  2. Implementieren Sie eine untergeordnete Klasse von UIController. UIController enthält Methoden, die vom SDK aufgerufen werden, wenn sich der Status der Übertragungs- oder Mediensitzung ändert. Die Unterklasse von UIController sollte einen ImageView als einen der Parameter annehmen und den Status bei Bedarf aktualisieren.

  3. Erstellen Sie eine untergeordnete Klasse von ExpandedControllerActivity, überschreiben Sie dann onCreate und rufen Sie getButtonImageViewAt(int) auf, um das Ansichtsobjekt der Schaltfläche abzurufen. Rufen Sie dann bindViewToUIController(View, UIController) auf, um die Ansicht mit Ihrem benutzerdefinierten UIController zu verknüpfen.

  4. Informationen zum Umgang mit der Aktion Ihrer benutzerdefinierten Schaltfläche finden Sie unter Benutzerdefinierte Aktionen hinzufügen auf der Seite MediaIntentReceiver.

Hier ein Beispiel für die Verknüpfung einer Taste an Steckplatz 2 mit einer UIController namens 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);
        ...
    }
}