Как настроить интерфейс отправителя на устройстве Android

Вы можете настраивать виджеты 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, например кнопку "Нравится". Выполните следующие действия:

  1. Чтобы указать слот для специальной кнопки, используйте тег @id/cast_button_type_custom в атрибуте castControlButtons элемента MiniControllerFragment.

  2. Реализуйте подкласс UIController. Класс UIController содержит методы, которые вызываются SDK при изменении состояния сеанса трансляции или медиасеанса. Подкласс UIController должен принимать ImageView в качестве одного из параметров и обновлять свое состояние по мере необходимости.

  3. Создайте подкласс MiniControllerFragment, переопределите метод onCreateView и вызовите метод getButtonImageViewAt(int), чтобы получить объект ImageView для этой кнопки. Затем вызовите функцию bindViewToUIController(View, UIController) чтобы связать представление с вашим специальным UIController.

  4. Информацию о том, как обрабатывать действия с помощью специальной кнопки, можно найти в разделе 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>
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);
        ...
    }
}

Настроить расширенный контроллер

Настройте тему

Если в 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, например кнопку "Нравится". Выполните следующие действия:

  1. Чтобы указать слот для специальной кнопки, используйте тег @id/cast_button_type_custom в атрибуте castControlButtons элемента ExpandedControllerActivity. Затем вы можете использовать getButtonImageViewAt(int), чтобы получить ImageView для этой кнопки.

  2. Реализуйте подкласс UIController. UIController содержит методы, которые вызываются SDK при изменении состояния сеанса трансляции или медиасеанса. Ваш подкласс UIController должен принимать ImageView в качестве одного из параметров и обновлять свое состояние по мере необходимости.

  3. Создайте подкласс ExpandedControllerActivity, переопределите метод onCreate и вызовите метод getButtonImageViewAt(int), чтобы получить объект представления кнопки. Затем вызовите функцию bindViewToUIController(View, UIController) чтобы связать представление с вашим специальным UIController.

  4. Информацию о том, как обрабатывать действия, выполняемые с помощью настраиваемой кнопки, вы найдете в разделе Добавление настраиваемых действий (см. 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>
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);
        ...
    }
}