Personalizzazione dell'interfaccia utente di Android Sender

Puoi personalizzare i widget Cast impostando i colori, lo stile dei pulsanti, del testo e dell'aspetto delle miniature e scegliendo i tipi di pulsanti da visualizzare.

Personalizzare il tema dell'app

Questo esempio crea uno stile di tema personalizzato Theme.CastVideosTheme che può definire colori personalizzati, uno stile di overlay introduttivo, uno stile di mini controller e uno stile di controller espanso.

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

Le ultime tre righe sopra ti consentono di definire stili specifici per l'overlay introduttivo, il mini controller e il controller espanso come parte di questo tema. Gli esempi sono inclusi nelle sezioni seguenti.

Personalizzare il pulsante Cast

Per aggiungere un mediaRouteTheme personalizzato al tema della tua app:

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

Dichiara il tema personalizzato di Media Router e un mediaRouteButtonStyle personalizzato:

<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 deve essere utilizzato se la versione della libreria di supporto è più recente della 26.0.0. Per le versioni precedenti della libreria di supporto, utilizza invece buttonTint.

Personalizzare il tema dell'overlay introduttivo

La classe IntroductoryOverlay supporta vari attributi di stile che la tua app può sostituire in un tema personalizzato. Questo esempio mostra come sostituire l'aspetto del testo sia del pulsante sia del titolo sul widget di overlay:

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

Personalizzare il mini controller

Personalizzare tema

La MiniControllerFragment classe supporta vari attributi di stile che la tua app può sostituire in un tema personalizzato. Questo esempio mostra come attivare la visualizzazione dell'immagine miniatura, sostituire l'aspetto del testo sia del sottotitolo sia dei sottotitoli codificati, impostare i colori e personalizzare i pulsanti:

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

Scegliere i pulsanti

Un MiniControllerFragment ha tre slot che possono visualizzare la copertina dell'album e due pulsanti o tre pulsanti di controllo se la copertina dell'album non è compilata.

SLOT  SLOT  SLOT
  1     2     3

Per impostazione predefinita, il fragment mostra un pulsante di attivazione/disattivazione della riproduzione/pausa. Gli sviluppatori possono utilizzare l'attributo castControlButtons per sostituire i pulsanti da mostrare. I pulsanti di controllo supportati sono definiti come risorse ID:

Tipo pulsante Descrizione
@id/cast_button_type_empty Non inserire un pulsante in questo slot
@id/cast_button_type_custom Pulsante personalizzato
@id/cast_button_type_play_pause_toggle Alterna tra riproduzione e pausa
@id/cast_button_type_skip_previous Passa all'elemento precedente nella coda
@id/cast_button_type_skip_next Passa all'elemento successivo nella coda
@id/cast_button_type_rewind_30_seconds Riavvolge la riproduzione di 30 secondi
@id/cast_button_type_forward_30_seconds Avanza la riproduzione di 30 secondi
@id/cast_button_type_mute_toggle Attiva e disattiva l'audio del ricevitore
@id/cast_button_type_closed_caption Apre una finestra di dialogo per selezionare le tracce audio e di testo

Ecco un esempio che utilizzerebbe la copertina dell'album, un pulsante di attivazione/disattivazione della riproduzione/pausa e un pulsante di avanzamento, in questo ordine da sinistra a destra:

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

Avviso: questo array deve contenere esattamente tre elementi, altrimenti verrà generata un'eccezione di runtime. Se non vuoi mostrare un pulsante in uno slot, utilizza @id/cast_button_type_empty.

Aggiungere pulsanti personalizzati

Un MiniControllerFragment supporta l'aggiunta di pulsanti di controllo personalizzati non forniti dall'SDK, ad esempio un pulsante "Mi piace". I passaggi sono:

  1. Specifica uno slot per contenere un pulsante personalizzato utilizzando @id/cast_button_type_custom nell'attributo castControlButtons di MiniControllerFragment.

  2. Implementa una sottoclasse di UIController. UIController contiene metodi chiamati dall'SDK quando lo stato della sessione Cast o della sessione multimediale cambia. La sottoclasse di UIController deve accettare un ImageView come uno dei parametri e aggiornarne lo stato in base alle esigenze.

  3. Sottoclassifica MiniControllerFragment, quindi sostituisci onCreateView e chiama getButtonImageViewAt(int) per ottenere ImageView per il pulsante personalizzato. Quindi chiama bindViewToUIController(View, UIController) per associare la visualizzazione al tuo UIControllerpersonalizzato.

  4. Per scoprire come gestire l'azione dal pulsante personalizzato, consulta MediaIntentReceiver in Aggiungere azioni personalizzate.

    Ecco un esempio di associazione di un pulsante nello slot 2 a un UIController chiamato 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);
        ...
    }
}

Personalizzare il controller espanso

Personalizzare tema

Se l'attività di un controller espanso utilizza una barra degli strumenti con tema scuro, puoi impostare un tema sulla barra degli strumenti per utilizzare testo chiaro e un colore dell'icona chiaro:

<style name="Theme.CastVideosTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="castExpandedControllerToolbarStyle">
        @style/ThemeOverlay.AppCompat.Dark.ActionBar
    </item>
</style>

Puoi specificare le tue immagini utilizzate per disegnare i pulsanti sul controller espanso:

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

Scegliere i pulsanti

L'attività del controller espanso ha cinque slot per mostrare i pulsanti di controllo. Lo slot centrale mostra sempre un pulsante di attivazione/disattivazione della riproduzione/pausa e non è configurabile. Gli altri quattro slot sono configurabili, da sinistra a destra, dall'app del mittente.

SLOT  SLOT  PLAY/PAUSE  SLOT  SLOT
  1     2     BUTTON      3     4

Per impostazione predefinita, l'attività mostra un pulsante per i sottotitoli codificati, un pulsante per passare all'elemento precedente, un pulsante per passare all'elemento successivo e un pulsante di attivazione/disattivazione dell'audio in questi quattro slot, da sinistra a destra. Gli sviluppatori possono utilizzare l'attributo castControlButtons per sostituire i pulsanti da mostrare negli slot. L'elenco dei pulsanti di controllo supportati è definito come risorse ID identiche ai tipi di pulsanti per i pulsanti del mini controller.

Ecco un esempio che inserisce un pulsante di riavvolgimento nel secondo slot, un pulsante di avanzamento nel terzo slot e lascia vuoti il primo e l'ultimo slot:

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

L'array deve contenere esattamente quattro elementi, altrimenti verrà generata un'eccezione di runtime. Se non vuoi mostrare un pulsante in uno slot, utilizza @id/cast_button_type_empty. CastContext può gestire il ciclo di vita e la presentazione di questa attività.

Aggiungere pulsanti personalizzati

Un ExpandedControllerActivity supporta l'aggiunta di pulsanti di controllo personalizzati non forniti dall'SDK, ad esempio un pulsante "Mi piace". I passaggi sono:

  1. Specifica uno slot per contenere un pulsante personalizzato utilizzando @id/cast_button_type_custom nell'attributo castControlButtons di ExpandedControllerActivity. Puoi quindi utilizzare getButtonImageViewAt(int) per ottenere ImageView per il pulsante personalizzato.

  2. Implementa una sottoclasse di UIController. UIController contiene metodi chiamati dall'SDK quando lo stato della sessione Cast o della sessione multimediale cambia. La sottoclasse di UIController deve accettare un ImageView come uno dei parametri e aggiornarne lo stato in base alle esigenze.

  3. Sottoclassifica ExpandedControllerActivity, quindi sostituisci onCreate e chiama getButtonImageViewAt(int) per ottenere l'oggetto di visualizzazione del pulsante. Quindi chiama bindViewToUIController(View, UIController) per associare la visualizzazione al tuo UIController.

  4. Per scoprire come gestire l'azione dal pulsante personalizzato, consulta MediaIntentReceiver in Aggiungere azioni personalizzate.

Ecco un esempio di associazione di un pulsante nello slot 2 a un UIController chiamato 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);
        ...
    }
}