Настройте пользовательский интерфейс Android Sender

Вы можете настроить виджеты 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>
Котлин
// 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);
        ...
    }
}

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

Настроить тему

Если активность расширенного контроллера использует панель инструментов темной темы, вы можете установить тему на панели инструментов, чтобы использовать светлый текст и светлый цвет значка:

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

Выберите кнопки

Расширенная активность контроллера имеет пять слотов для отображения кнопок управления. В среднем слоте всегда отображается кнопка переключения воспроизведения/паузы, и его нельзя настроить. Остальные четыре слота настраиваются приложением-отправителем слева направо.

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>
Котлин
// 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);
        ...
    }
}