Benutzeroberfläche von Android Sender anpassen

Mit Sammlungen den Überblick behalten Sie können Inhalte basierend auf Ihren Einstellungen speichern und kategorisieren.

Du kannst Cast-Widgets anpassen, indem du die Farben, die Gestaltung der Schaltflächen, den Text und die Darstellung der Miniaturansichten festlegst und die gewünschten Schaltflächen auswählst.

App-Design anpassen

In diesem Beispiel wird ein benutzerdefinierter Stil Theme.CastVideosTheme erstellt, der benutzerdefinierte Farben, ein Einführungs-Overlay-Stil, einen Mini-Controller-Stil und einen erweiterten Controller-Stil definieren kann.

<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 Overlay-Overlay, einen Minicontroller und einen maximierten Controller als Teil dieses Designs definieren. Beispiele finden Sie in den folgenden Abschnitten.

Cast-Symbol anpassen

So fügst du deiner App ein benutzerdefiniertes mediaRouteTheme-Design 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 geben Sie 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. Verwenden Sie für ältere Versionen der Supportbibliothek buttonTint.

Einführungs-Overlay-Design anpassen

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

<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 Anwendung in einem benutzerdefinierten Design überschreiben kann. In diesem Beispiel wird gezeigt, wie die Anzeige des Thumbnail-Bilds aktiviert, die Textdarstellung sowohl des Untertitels als auch des Untertitels überschrieben, die Farben festgelegt und die Schaltflächen angepasst werden:

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

Tasten auswählen

MiniControllerFragment hat drei Slots für das Albumcover und zwei Schaltflächen oder drei Steuerschaltflächen, wenn das Albumcover nicht ausgefüllt ist.

SLOT  SLOT  SLOT
  1     2     3

Standardmäßig zeigt das Fragment eine Schaltfläche zum Wechseln zwischen Wiedergabe und Pause an. 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 Keine Taste in diesem Slot platzieren
@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 Springt 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 Die Wiedergabe wird 30 Sekunden vorgespult.
@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 siehst du ein Beispiel, bei dem das Albumcover, eine Schaltfläche zum Umschalten zwischen Wiedergabe und Pause und eine Schaltfläche zum Überspringen 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 Laufzeitausnahme ausgelöst. Wenn du keine Schaltfläche in einem Slot anzeigen möchtest, verwende @id/cast_button_type_empty.

Benutzerdefinierte Schaltflächen hinzufügen

Ein MiniControllerFragment unterstützt das Hinzufügen benutzerdefinierter Steuerschaltflächen, die nicht vom SDK bereitgestellt werden, z. B. eine Daumen-hoch-Schaltfläche. 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 von MiniControllerFragment an.

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

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

  4. Weitere Informationen zur Verarbeitung der Aktion über die benutzerdefinierte Schaltfläche finden Sie unter MediaIntentReceiver unter Benutzerdefinierte Aktionen hinzufügen.

    Hier ist ein Beispiel für das Verknüpfen 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 dunkle Designsymbolleiste verwendet wird, können Sie ein Design in der Symbolleiste so einstellen, dass ein 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, mit denen die Schaltflächen auf dem maximierten Controller gezeichnet 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>

Tasten auswählen

Die Aktivität des maximierten Controllers hat fünf Bereiche, in denen die Steuerungstasten zu sehen sind. Im mittleren Bereich wird immer die Ein-/Aus-Schaltfläche für die Wiedergabe/Pause angezeigt, die nicht konfiguriert werden kann. 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 sehen Sie dort eine Schaltfläche mit Untertiteln, eine Schaltfläche zum Überspringen der Schaltfläche zum vorherigen Element, eine Schaltfläche zum Überspringen zum nächsten Element und eine Schaltfläche zum Stummschalten, wenn Sie von links nach rechts zwischen den vier Bereichen wechseln. Entwickler können mit dem Attribut castControlButtons überschreiben, welche Schaltflächen in welchen Slots angezeigt werden sollen. Die Liste der unterstützten Steuerschaltflächen ist als ID-Ressource definiert, die mit den Schaltflächentypen für Mini-Controller-Schaltflächen identisch ist.

In diesem Beispiel wird eine Schaltfläche zum Zurückspulen im zweiten und eine Schaltfläche zum Überspringen im dritten Slot platziert. Der erste und der letzte Slot werden dabei leer gelassen:

// 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 du keine Schaltfläche in einem Slot anzeigen möchtest, verwende @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 Steuerschaltflächen, die nicht vom SDK bereitgestellt werden, z. B. eine „Mag ich“-Schaltfläche. 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 von ExpandedControllerActivity an. Anschließend können Sie mit getButtonImageViewAt(int) den ImageView für diese benutzerdefinierte Schaltfläche abrufen.

  2. Implementieren Sie eine Unterklasse von UIController. UIController enthält Methoden, die vom SDK aufgerufen werden, wenn sich der Status der Streamingsitzung oder der Mediensitzung ändert. Ihre Unterklasse von UIController sollte eine ImageView als einen der Parameter verwenden und ihren 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. Weitere Informationen zur Verarbeitung der Aktion über die benutzerdefinierte Schaltfläche finden Sie unter MediaIntentReceiver unter Benutzerdefinierte Aktionen hinzufügen.

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