Android-Benutzeroberfläche für Absender anpassen

Sie können Cast-Widgets anpassen, indem Sie die Farben, die Schaltflächen, den Text und die Darstellung von Miniaturansichten festlegen sowie die Arten von Schaltflächen auswählen, die angezeigt werden sollen.

App-Design anpassen

In diesem Beispiel wird der benutzerdefinierte 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 spezielle Stile für das einführende Overlay, den Mini-Controller und den erweiterten Controller im Rahmen dieses Themas definieren. Beispiele finden Sie in den folgenden Abschnitten.

Cast-Symbol anpassen

So fügen Sie dem Design Ihrer App ein benutzerdefiniertes mediaRouteTheme-Element 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 Supportbibliothek neuer als 26.0.0 ist. Für ältere Versionen der Supportbibliothek verwende stattdessen buttonTint.

Einführendes Overlay-Design anpassen

Die Klasse IntroductoryOverlay unterstützt verschiedene Stilattribute, die von Ihrer App in einem benutzerdefinierten Design überschrieben werden können. 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 von Ihrer App in einem benutzerdefinierten Design überschrieben werden können. In diesem Beispiel wird gezeigt, wie Sie die Anzeige der Miniaturansicht aktivieren, die Textdarstellung der Zwischenüberschrift und der 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 Bereiche, auf denen das Albumcover angezeigt werden kann, und zwei Schaltflächen. Wenn das Albumcover nicht dargestellt wird, sind drei Steuerungsschaltflächen vorhanden.

SLOT  SLOT  SLOT
  1     2     3

Standardmäßig zeigt das Fragment eine Schaltfläche zum Wechseln zwischen Wiedergabe und Pause. Entwickler können das Attribut castControlButtons verwenden, um zu ü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 Platzieren Sie keine Schaltfläche in diesem Slot
@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 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 Spult die Wiedergabe 30 Sekunden zurück
@id/cast_button_type_forward_30_seconds Spult 30 Sekunden vor
@id/cast_button_type_mute_toggle Schaltet den Empfänger stumm und hebt die Stummschaltung auf
@id/cast_button_type_closed_caption Öffnet ein Dialogfeld zum Auswählen von Text- und Audiotracks

Hier ist ein Beispiel, bei dem das Albumcover, eine Schaltfläche für Wiedergabe/Pause und eine Schaltfläche zum Vorspulen in dieser Reihenfolge von links nach rechts verwendet werden würden:

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

Benutzerdefinierte Schaltflächen hinzufügen

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

  1. Gib mithilfe von @id/cast_button_type_custom im Attribut castControlButtons des MiniControllerFragment einen Slot an, der eine benutzerdefinierte Schaltfläche enthalten soll.

  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 ImageView als einen der Parameter verwenden und ihren Status nach Bedarf aktualisieren.

  3. Erstellen Sie abgeleitete Klassen 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. Unter MediaIntentReceiver unter Benutzerdefinierte Aktionen hinzufügen findest du weitere Informationen zur Verarbeitung der Aktion über deine benutzerdefinierte Schaltfläche.

    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 erweiterten Controllers eine Symbolleiste mit dunklem Design verwendet wird, kannst du für die Symbolleiste ein Design mit hellem Text und einer hellen 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

Die Aktivität des erweiterten Controllers hat fünf Plätze zum Anzeigen der Steuerungstasten. Der mittlere Slot zeigt immer eine Ein/Aus-Schaltfläche für Wiedergabe/Pause 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 Untertitelschaltfläche, eine Schaltfläche zum Überspringen des vorherigen Elements, eine Schaltfläche zum Überspringen des nächsten Elements und eine Ein-/Aus-Schaltfläche zum Stummschalten in diesen vier Slots (von links nach rechts). Entwickler können das Attribut castControlButtons verwenden, um zu überschreiben, welche Schaltflächen in welchen Slots angezeigt werden sollen. Die Liste der unterstützten Steuerschaltflächen ist als ID-Ressourcen definiert, die mit den Tastentypen für Mini-Controller-Tasten identisch sind.

Im folgenden Beispiel wird im zweiten Slot eine Schaltfläche zum Zurückspulen und im dritten Slot eine Schaltfläche zum Vorspulen platziert, während der erste und letzte Slot leer bleiben:

// 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 eine Schaltfläche in einem Slot nicht 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

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

  1. Gib mithilfe von @id/cast_button_type_custom im Attribut castControlButtons des ExpandedControllerActivity einen Slot an, der eine benutzerdefinierte Schaltfläche enthalten soll. Anschließend können Sie mit getButtonImageViewAt(int) das ImageView-Objekt 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 Streaming- oder Mediensitzung ändert. Ihre abgeleitete Klasse von UIController sollte eine ImageView als einen der Parameter annehmen und ihren Status nach Bedarf aktualisieren.

  3. Erstellen Sie eine abgeleitete Klasse von ExtendedControllerActivity, überschreiben Sie 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. Unter MediaIntentReceiver unter Benutzerdefinierte Aktionen hinzufügen findest du weitere Informationen zur Verarbeitung der Aktion über deine benutzerdefinierte Schaltfläche.

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