Как настроить интерфейс отправителя на устройстве 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>

Если версия библиотеки поддержки новее, чем 26.0.0, используйте setTint. Для более ранних версий библиотеки поддержки используйте 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);
        ...
    }
}