É possível personalizar os widgets do Google Cast definindo as cores, estilizando os botões, o texto e a aparência da miniatura e escolhendo os tipos de botões que serão exibidos.
Personalizar o tema do app
Este exemplo cria um estilo de tema personalizado Theme.CastVideosTheme
, que
pode definir cores personalizadas, um estilo de sobreposição introdutório, um estilo de minicontrolador
e um estilo de controle expandido.
<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>
As três últimas linhas acima permitem definir estilos específicos para a sobreposição introdutória, o minicontrolador e o controlador expandido como parte deste tema. Confira exemplos nas seções a seguir.
Personalizar o botão do Google Cast
Para adicionar um mediaRouteTheme
personalizado ao tema do app:
<style name="Theme.CastVideosTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- ... -->
<item name="mediaRouteTheme">@style/CustomMediaRouterTheme</item>
</style>
Declare seu tema personalizado do Media Router e declare um
mediaRouteButtonStyle
personalizado:
<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 ser usado se a versão da biblioteca de suporte for mais recente que 26.0.0. Para versões
mais antigas da biblioteca de suporte, use
buttonTint
.
Personalizar o tema da sobreposição introdutória
A classe
IntroductoryOverlay
oferece suporte a vários atributos de estilo que o app pode substituir em um tema
personalizado. Este exemplo mostra como substituir a aparência do texto do botão
e do título sobre o widget de sobreposição:
<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>
Personalizar o minicontrole
Personalizar tema
A classe
MiniControllerFragment
oferece suporte a vários atributos de estilo que o app pode substituir em um tema
personalizado. Este exemplo mostra como ativar a exibição da imagem em miniatura,
substituir a aparência do texto do subtítulo e do closed caption, definir
as cores e personalizar os botões:
<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>
Escolher botões
Um MiniControllerFragment
tem três slots que podem exibir a arte do álbum
e dois botões ou três botões de controle se a arte do álbum não estiver preenchida.
SLOT SLOT SLOT
1 2 3
Por padrão, o fragmento mostra um botão de ativação de reprodução/pausa. Os desenvolvedores podem usar
o atributo castControlButtons
para substituir quais botões serão mostrados.
Os botões de controle com suporte são definidos como
recursos de ID:
Tipo de botão | Descrição |
---|---|
@id/cast_button_type_empty |
Não coloque um botão neste slot |
@id/cast_button_type_custom |
Botão personalizado |
@id/cast_button_type_play_pause_toggle |
Alternar entre reprodução e pausa |
@id/cast_button_type_skip_previous |
Volta para o item anterior na fila |
@id/cast_button_type_skip_next |
Pula para o próximo item na fila |
@id/cast_button_type_rewind_30_seconds |
Voltar a reprodução 30 segundos |
@id/cast_button_type_forward_30_seconds |
Avançar a reprodução em 30 segundos |
@id/cast_button_type_mute_toggle |
Desativa e ativa o som do receptor |
@id/cast_button_type_closed_caption |
Abre uma caixa de diálogo para selecionar faixas de texto e áudio |
Confira um exemplo que usaria a arte do álbum, um botão de ativar/desativar a reprodução e um botão de avançar nessa ordem da esquerda para a direita:
<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">
Aviso: essa matriz precisa conter exatamente três itens. Caso contrário, uma exceção
de execução será gerada. Se você não quiser mostrar um botão em um slot, use
@id/cast_button_type_empty
.
Adicionar botões personalizados
Um MiniControllerFragment
oferece suporte à adição de botões de controle personalizados que não
são fornecidos pelo SDK, como um botão "Gostei". Essas etapas são:
Especifique um slot para conter um botão personalizado usando
@id/cast_button_type_custom
no atributocastControlButtons
doMiniControllerFragment
.Implemente uma subclasse de
UIController
. OUIController
contém métodos chamados pelo SDK quando o estado da sessão de transmissão ou de mídia muda. Sua subclasse deUIController
precisa usar umImageView
como um dos parâmetros e atualizar o estado conforme necessário.Crie uma subclasse de
MiniControllerFragment
, substituaonCreateView
e chamegetButtonImageViewAt(int)
para receber oImageView
para esse botão personalizado. Em seguida, chamebindViewToUIController(View, UIController)
para associar a visualização à suaUIController
personalizada.Consulte
MediaIntentReceiver
em Adicionar ações personalizadas para saber como processar a ação do botão personalizado.Confira um exemplo de associação de um botão no slot 2 a um
UIController
chamadoMyCustomUIController
:
// 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>
// 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) ... } }
// 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); ... } }
Personalizar o controle expandido
Personalizar tema
Se a atividade de um controlador aberto usar uma barra de ferramentas de tema escuro, você poderá definir um tema na barra de ferramentas para usar texto claro e uma cor de ícone clara:
<style name="Theme.CastVideosTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="castExpandedControllerToolbarStyle">
@style/ThemeOverlay.AppCompat.Dark.ActionBar
</item>
</style>
Você pode especificar suas próprias imagens que são usadas para desenhar os botões no controlador aberto:
<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>
Escolher botões
A atividade do controle expandido tem cinco slots para mostrar botões de controle. O slot do meio sempre mostra um botão de alternância de reprodução/pausa e não pode ser configurado. Os outros quatro slots são configuráveis, da esquerda para a direita, pelo app de envio.
SLOT SLOT PLAY/PAUSE SLOT SLOT
1 2 BUTTON 3 4
Por padrão, a atividade mostra um botão de legenda, um botão de pular para o
item anterior, um botão de pular para o item seguinte e um botão de ativar/desativar o som
nesses quatro slots, da esquerda para a direita. Os desenvolvedores podem usar o
atributo castControlButtons
para substituir quais botões mostrar em
quais slots. A lista de botões de controle com suporte é definida como
recursos de ID idênticos aos
tipos de botões para botões de minicontrolador.
Confira um exemplo que coloca um botão de retroceder no segundo slot, um botão de avançar para frente no terceiro slot e deixa o primeiro e o último slots vazios:
// 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>
A matriz precisa conter exatamente quatro itens. Caso contrário, uma exceção de execução será
gerada. Se você não quiser mostrar um botão em um slot, use
@id/cast_button_type_empty
. O CastContext
pode gerenciar o ciclo de vida e
a apresentação dessa atividade.
Adicionar botões personalizados
Um ExpandedControllerActivity
oferece suporte à adição de botões de controle personalizados que não são fornecidos pelo SDK,
como um botão "Gostei". Essas etapas são:
Especifique um slot para conter um botão personalizado usando
@id/cast_button_type_custom
no atributocastControlButtons
doExpandedControllerActivity
. Em seguida, usegetButtonImageViewAt(int)
para receber oImageView
para esse botão personalizado.Implemente uma subclasse de
UIController
. OUIController
contém métodos chamados pelo SDK quando o estado da sessão de transmissão ou de mídia muda. Sua subclasse deUIController
precisa usar umImageView
como um dos parâmetros e atualizar o estado conforme necessário.Crie uma subclasse de ExpandedControllerActivity, substitua
onCreate
e chamegetButtonImageViewAt(int)
para acessar o objeto de visualização do botão. Em seguida, chamebindViewToUIController(View, UIController)
para associar a visualização aoUIController
personalizado.Consulte
MediaIntentReceiver
em Adicionar ações personalizadas para saber como processar a ação do botão personalizado.
Confira um exemplo de associação de um botão no slot 2 a um
UIController
chamado 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>
// 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) ... } }
// 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); ... } }