Android-Benutzeroberfläche für Absender anpassen

Sie können Streaming-Widgets anpassen, indem Sie die Farben, Stile für Schaltflächen, Text und Darstellung der Miniaturansichten festlegen und die Schaltflächentypen auswählen, die angezeigt werden sollen.

App-Design anpassen

In diesem Beispiel wird ein benutzerdefinierter Designstil Theme.CastVideosTheme erstellt, mit dem benutzerdefinierte Farben, ein einführender 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 kannst du Stile definieren, die spezifisch für Einführungs-Overlays, Mini-Controller und maximierte Controller im Rahmen dieses Designs sind. In den folgenden Abschnitten finden Sie Beispiele.

Cast-Symbol anpassen

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

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

Geben Sie Ihr benutzerdefiniertes Media Router-Design und ein benutzerdefiniertes mediaRouteButtonStyle an:

<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 Support Library neuer als 26.0.0 ist. Verwenden Sie für ältere Versionen der Supportbibliothek stattdessen buttonTint.

Einleitendes Overlay-Design anpassen

Die Klasse IntroductoryOverlay unterstützt verschiedene Stilattribute, die Ihre App in einem benutzerdefinierten Design überschreiben kann. In diesem Beispiel wird gezeigt, wie die Textdarstellung der Schaltfläche und des Titels über dem Overlay-Widget überschrieben werden kann:

<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 Design überschreiben kann. In diesem Beispiel wird gezeigt, wie Sie die Anzeige der Miniaturansicht aktivieren, um die Textdarstellung der Zwischenüberschrift und der Untertitel zu überschreiben, die Farben festzulegen und die Schaltflächen anzupassen:

<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 Bereiche, in denen das Albumcover angezeigt werden kann, und zwei Schaltflächen. Wenn das Albumcover nicht ausgefüllt ist, gibt es drei Steuerschaltflächen.

SLOT  SLOT  SLOT
  1     2     3

Standardmäßig wird für das Fragment eine Schaltfläche zum Wechseln zwischen Wiedergabe und Pause angezeigt. Entwickler können mit dem Attribut castControlButtons überschreiben, welche Schaltflächen angezeigt werden sollen. Die unterstützten Steuerschaltflächen sind als ID-Ressourcen definiert:

Schaltflächenart Beschreibung
@id/cast_button_type_empty Platziere keine Taste in diesem Steckplatz
@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 Wechselt zum vorherigen Element in der Warteschlange
@id/cast_button_type_skip_next Wechselt zum nächsten Element in der Warteschlange
@id/cast_button_type_rewind_30_seconds Spule die Wiedergabe um 30 Sekunden zurück
@id/cast_button_type_forward_30_seconds Spule die Wiedergabe 30 Sekunden vor
@id/cast_button_type_mute_toggle Schaltet den Empfänger stumm und die Stummschaltung auf
@id/cast_button_type_closed_caption Öffnet ein Dialogfeld zur Auswahl von Text- und Audiotracks

In diesem Beispiel werden das Albumcover, eine Schaltfläche zum Ein-/Ausschalten der Wiedergabe/Pause und eine Schaltfläche zum Vorspulen in dieser Reihenfolge von links nach rechts verwendet:

<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 in einem Slot keine Schaltfläche angezeigt werden soll, verwenden Sie @id/cast_button_type_empty.

Benutzerdefinierte Schaltflächen hinzufügen

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

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

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

  3. Erstellen Sie eine Unterklasse von MiniControllerFragment, überschreiben Sie 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. Unter MediaIntentReceiver unter Benutzerdefinierte Aktionen hinzufügen erfahren Sie, wie die Aktion über Ihre benutzerdefinierte Schaltfläche verarbeitet wird.

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

Erweiterten Controller anpassen

Design anpassen

Wenn für die Aktivität eines maximierten Controllers eine dunkle Designsymbolleiste verwendet wird, können Sie in der Symbolleiste ein Design für hellen Text und eine helle Symbolfarbe festlegen:

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

Schaltflächen auswählen

Der Bereich „Aktivität“ des erweiterten Controllers hat fünf Stellen, an denen die Steuerungsschaltflächen zu sehen sind. Der mittlere Slot zeigt immer eine Schaltfläche zum Wechseln zwischen Wiedergabe und Pause an und 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 zeigt die Aktivität eine Schaltfläche für Untertitel, eine Schaltfläche zum Überspringen zum vorherigen Element, eine Schaltfläche zum Überspringen zum nächsten Element sowie eine Schaltfläche zum Ein-/Ausschalten der Stummschaltung in diesen vier Slots (von links nach rechts). Entwickler können mit dem Attribut castControlButtons überschreiben, welche Schaltflächen in welchen Slots angezeigt werden sollen. Die unterstützten Steuerschaltflächen sind als ID-Ressourcen definiert, die mit den Schaltflächentypen für Mini-Controller-Schaltflächen identisch sind.

Im folgenden Beispiel wird eine Schaltfläche zum Zurückspulen im zweiten Slot und eine Schaltfläche zum Überspringen im dritten Slot platziert. Die ersten und letzten Slots 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 in einem Slot keine Schaltfläche angezeigt werden soll, 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 können benutzerdefinierte Steuerschaltflächen hinzugefügt werden, die nicht vom SDK bereitgestellt werden, z. B. die Schaltfläche „Mag ich“. Folgende Schritte sind auszuführen:

  1. Geben Sie einen Slot für eine benutzerdefinierte Schaltfläche an. Verwenden Sie dazu @id/cast_button_type_custom im Attribut castControlButtons von ExpandedControllerActivity. Anschließend können Sie mit getButtonImageViewAt(int) den ImageView für diese benutzerdefinierte Schaltfläche abrufen.

  2. Implementieren Sie eine abgeleitete Klasse von UIController. UIController enthält Methoden, die vom SDK aufgerufen werden, wenn sich der Status der Streamingsitzung oder der Mediensitzung ändert. Ihre abgeleitete Klasse von UIController sollte einen ImageView als einen der Parameter verwenden und seinen Status nach Bedarf aktualisieren.

  3. Erstellen Sie eine Unterklasse für ExpandableControllerActivity, ü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 dem benutzerdefinierten UIController zu verknüpfen.

  4. Unter MediaIntentReceiver unter Benutzerdefinierte Aktionen hinzufügen erfahren Sie, wie Sie die Aktion über Ihre benutzerdefinierte Schaltfläche verarbeiten können.

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