Вы можете настраивать виджеты Cast, задавая цвета, стили кнопок, текста и значков, а также выбирая типы кнопок для отображения.
Как настроить тему приложения
В этом примере создается собственный стиль темы Theme.CastVideosTheme, в котором можно задать пользовательские цвета, стиль вводного оверлея, стиль мини-контроллера и стиль развернутого контроллера.
<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>
Последние три строки позволяют определить стили, характерные для вводного оверлея, мини-контроллера и расширенного контроллера, как часть этой темы. Примеры приведены в разделах ниже.
Как настроить кнопку трансляции
Чтобы добавить пользовательский mediaRouteTheme в тему приложения, выполните следующие действия:
<style name="Theme.CastVideosTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- ... -->
<item name="mediaRouteTheme">@style/CustomMediaRouterTheme</item>
</style>
Объявите собственную тему Media Router и объявите собственный элемент 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
следует использовать, если версия библиотеки поддержки новее 26.0.0. Для более ранних версий библиотеки поддержки используйте buttonTint.
Как настроить тему оверлея с информацией о канале
Класс IntroductoryOverlay поддерживает различные атрибуты стиля, которые ваше приложение может переопределить в пользовательской теме. В примере показано, как переопределить внешний вид текста кнопки и заголовка над виджетом оверлея.
<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>
Как настроить мини-контроллер
Настройте тему
Класс MiniControllerFragment поддерживает различные атрибуты стиля, которые ваше приложение может переопределить в пользовательской теме. В этом примере показано, как включить показ значка, переопределить внешний вид текста подзаголовка и субтитров, задать цвета и настроить кнопки.
<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>
Выбрать кнопки
У MiniControllerFragment три слота, в которых может показываться обложка альбома и две кнопки или три кнопки управления, если обложка альбома не добавлена.
SLOT SLOT SLOT
1 2 3
По умолчанию в фрагменте показывается переключатель воспроизведения/паузы. Разработчики могут использовать атрибут castControlButtons, чтобы переопределить кнопки, которые будут показываться.
Поддерживаемые кнопки управления определяются как ресурсы идентификаторов:
| Тип кнопки | Описание |
|---|---|
@id/cast_button_type_empty |
Не размещайте кнопку в этом слоте. |
@id/cast_button_type_custom |
Кнопка "Свое значение" |
@id/cast_button_type_play_pause_toggle |
Переключает воспроизведение и паузу. |
@id/cast_button_type_skip_previous |
Перейти к предыдущему элементу в очереди. |
@id/cast_button_type_skip_next |
Перейти к следующему элементу в очереди. |
@id/cast_button_type_rewind_30_seconds |
Перемотать на 30 секунд назад |
@id/cast_button_type_forward_30_seconds |
Перемотать вперед на 30 секунд |
@id/cast_button_type_mute_toggle |
Включение и отключение звука на приемнике. |
@id/cast_button_type_closed_caption |
Открывает диалоговое окно для выбора текстовых и аудиодорожек. |
Вот пример, в котором слева направо расположены обложка альбома, переключатель воспроизведения/паузы и кнопка перехода вперед:
<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">
Внимание! Этот массив должен содержать ровно три элемента, иначе будет вызвано исключение времени выполнения. Если вы не хотите показывать кнопку в слоте, используйте тег @id/cast_button_type_empty.
Как добавить кнопки
Элемент MiniControllerFragment позволяет добавлять собственные кнопки управления, не предусмотренные в SDK, например кнопку "Нравится". Выполните следующие действия:
Чтобы указать слот для специальной кнопки, используйте тег
@id/cast_button_type_customв атрибутеcastControlButtonsэлементаMiniControllerFragment.Реализуйте подкласс
UIController. КлассUIControllerсодержит методы, которые вызываются SDK при изменении состояния сеанса трансляции или медиасеанса. ПодклассUIControllerдолжен приниматьImageViewв качестве одного из параметров и обновлять свое состояние по мере необходимости.Создайте подкласс
MiniControllerFragment, переопределите методonCreateViewи вызовите методgetButtonImageViewAt(int), чтобы получить объектImageViewдля этой кнопки. Затем вызовите функциюbindViewToUIController(View, UIController)чтобы связать представление с вашим специальнымUIController.Информацию о том, как обрабатывать действия с помощью специальной кнопки, можно найти в разделе
MediaIntentReceiverстатьи Как добавить специальные действия.Вот пример того, как связать кнопку в слоте 2 с элементом
UIController, который называется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 ... } } // 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); ... } }
Настроить расширенный контроллер
Настройте тему
Если в Activity расширенного контроллера используется панель инструментов с тёмной темой, вы можете задать для нее тему со светлым текстом и светлым цветом значков:
<style name="Theme.CastVideosTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="castExpandedControllerToolbarStyle">
@style/ThemeOverlay.AppCompat.Dark.ActionBar
</item>
</style>
Вы можете указать собственные изображения, которые будут использоваться для кнопок на развернутом контроллере:
<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>
Выберите кнопки
В развернутом контроллере Activity есть пять слотов для кнопок управления. В среднем слоте всегда показывается переключатель воспроизведения/паузы, и его нельзя настроить. Остальные четыре слота настраиваются приложением-отправителем слева направо.
SLOT SLOT PLAY/PAUSE SLOT SLOT
1 2 BUTTON 3 4
По умолчанию в этих четырех ячейках слева направо находятся кнопка субтитров, кнопка перехода к предыдущему элементу, кнопка перехода к следующему элементу и кнопка включения/отключения звука. Разработчики могут использовать атрибут castControlButtons, чтобы переопределить, какие кнопки будут показываться в каких слотах. Список поддерживаемых кнопок управления определяется как ресурсы идентификаторов, идентичные типам кнопок для мини-контроллера.
Вот пример, в котором кнопка перемотки назад находится во втором слоте, кнопка перемотки вперед – в третьем, а первый и последний слоты остаются пустыми:
// 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>
Массив должен содержать ровно четыре элемента, иначе будет вызвано исключение времени выполнения. Если вы не хотите показывать кнопку в слоте, используйте тег @id/cast_button_type_empty. CastContext может управлять жизненным циклом и представлением этого действия.
Как добавить собственные кнопки
ExpandedControllerActivity позволяет добавлять кнопки, не предусмотренные в SDK, например кнопку "Нравится". Выполните следующие действия:
Чтобы указать слот для специальной кнопки, используйте тег
@id/cast_button_type_customв атрибутеcastControlButtonsэлементаExpandedControllerActivity. Затем вы можете использоватьgetButtonImageViewAt(int), чтобы получитьImageViewдля этой кнопки.Реализуйте подкласс
UIController.UIControllerсодержит методы, которые вызываются SDK при изменении состояния сеанса трансляции или медиасеанса. Ваш подклассUIControllerдолжен приниматьImageViewв качестве одного из параметров и обновлять свое состояние по мере необходимости.Создайте подкласс ExpandedControllerActivity, переопределите метод
onCreateи вызовите методgetButtonImageViewAt(int), чтобы получить объект представления кнопки. Затем вызовите функциюbindViewToUIController(View, UIController)чтобы связать представление с вашим специальнымUIController.Информацию о том, как обрабатывать действия, выполняемые с помощью настраиваемой кнопки, вы найдете в разделе Добавление настраиваемых действий (см.
MediaIntentReceiver).
Вот пример того, как связать кнопку в слоте 2 с UIController под названием 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); ... } }