Android-Benutzeroberfläche für Absender anpassen

Sie können Cast-Widgets anpassen, indem Sie die Farben festlegen, die Darstellung der Schaltflächen, des Texts und der Miniaturansichten gestalten und die Arten der Schaltflächen auswählen, die angezeigt werden sollen.

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

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

Cast-Schaltfläche 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>

Deklarieren Sie Ihr benutzerdefiniertes Media Router-Design und deklarieren Sie einen benutzerdefinierten 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 Support-Bibliothek neuer als 26.0.0 ist. Bei älteren Versionen der Support-Bibliothek verwenden Sie stattdessen buttonTint.

Design des Einführungs-Overlays anpassen

Die IntroductoryOverlay Klasse unterstützt verschiedene Stilattribute, die Ihre App in einem benutzerdefinierten Design überschreiben kann. In diesem Beispiel wird gezeigt, wie Sie die Darstellung des Texts 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 MiniControllerFragment Klasse unterstützt verschiedene Stilattribute, die Ihre App in einem benutzerdefinierten Design überschreiben kann. In diesem Beispiel wird gezeigt, wie Sie die Anzeige des Miniaturbilds aktivieren, die Darstellung des Texts sowohl der Unterüberschrift als auch 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 Slots, in denen das Albumcover und zwei Schaltflächen oder drei Steuerungsschaltflächen angezeigt werden können, wenn das Albumcover nicht ausgefüllt ist.

SLOT  SLOT  SLOT
  1     2     3

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

Schaltflächenart Beschreibung
@id/cast_button_type_empty In diesem Slot keine Schaltfläche platzieren
@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 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 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 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 ein Beispiel, in dem das Albumcover, eine Schaltfläche zum Umschalten zwischen Wiedergabe und Pause und eine Schaltfläche zum Vorspringen 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

Ein MiniControllerFragment unterstützt das Hinzufügen benutzerdefinierter Steuerungsschaltflächen, die nicht vom SDK bereitgestellt werden, z. B. eine Schaltfläche „Gefällt mir“. So gehen Sie vor:

  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 Unterklasse von UIController. Der UIController enthält Methoden, die vom SDK aufgerufen werden, wenn sich der Status der Cast-Sitzung oder der Mediensitzung ändert. Ihre Unterklasse von UIController sollte ein ImageView als einen der Parameter verwenden und den Status nach Bedarf aktualisieren.

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

  4. MediaIntentReceiverUnter Benutzerdefinierte Aktionen hinzufügen finden Sie Informationen zum Verarbeiten der Aktion von Ihrer benutzerdefinierten Schaltfläche.

    Hier 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 die Aktivität eines erweiterten Controllers eine dunkle Design-Toolbar verwendet, können Sie ein Design für die Toolbar festlegen, um hellen Text und eine helle Symbolfarbe zu verwenden:

<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 Aktivität des erweiterten Controllers hat fünf Slots für Steuerungsschaltflächen. Im mittleren Slot wird immer eine Schaltfläche zum Umschalten zwischen Wiedergabe und Pause angezeigt. Dieser Slot 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 der Aktivität in diesen vier Slots von links nach rechts eine Schaltfläche für Untertitel, eine Schaltfläche zum Springen zum vorherigen Element, eine Schaltfläche zum Springen zum nächsten Element und eine Schaltfläche zum Umschalten 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 Steuerungsschaltflächen wird als ID-Ressourcen definiert, die mit den Schaltflächentypen für Mini-Controller-Schaltflächen identisch sind.

Hier ein Beispiel, in dem eine Schaltfläche zum Zurückspulen in den zweiten Slot und eine Schaltfläche zum Vorspringen in den dritten Slot platziert wird. 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 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

Eine ExpandedControllerActivity unterstützt das Hinzufügen benutzerdefinierter Steuerungsschaltflächen, die nicht vom SDK bereitgestellt werden, z. B. eine Schaltfläche „Gefällt mir“. So gehen Sie vor:

  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 mit getButtonImageViewAt(int) das ImageView für diese benutzerdefinierte Schaltfläche abrufen.

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

  3. Erstellen Sie eine Unterklasse 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. MediaIntentReceiver Unter Benutzerdefinierte Aktionen hinzufügen finden Sie Informationen zum Verarbeiten der Aktion von Ihrer benutzerdefinierten Schaltfläche.

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