自定义 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>

上面的最后三行代码可让您定义此主题中特定于简介叠加层、迷你控制器和展开的控制器的样式。这些部分中包含示例。

自定义 Cast 按钮

如需将自定义 mediaRouteTheme 添加到应用的主题,请执行以下操作:

<style name="Theme.CastVideosTheme" parent="Theme.AppCompat.Light.NoActionBar">
  <!-- ... -->
  <item name="mediaRouteTheme">@style/CustomMediaRouterTheme</item>
</style>

声明自定义媒体路由器主题并声明自定义 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

自定义简介叠加层主题

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

自定义迷你控制器

自定义主题

The 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

默认情况下,该 fragment 会显示一个播放/暂停切换按钮。开发者可以使用属性 castControlButtons 替换要显示的按钮。 受支持的控制按钮定义为 ID 资源

按钮类型 说明
@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_customcastControlButtonsMiniControllerFragment 属性中指定包含自定义按钮的插槽。

  2. 实现 UIController的子类。 UIController 包含在 Cast 会话或媒体会话的状态发生变化时由 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

默认情况下,Activity 会在这四个插槽中从左到右显示字幕按钮、跳到上一个项按钮、跳到下一个项按钮和静音切换按钮。开发者可以使用属性 castControlButtons 替换要在哪些插槽中显示哪些按钮。受支持的控制按钮列表定义为 ID 资源,与 迷你控制器按钮的按钮类型相同

以下示例在第二个插槽中放置一个倒回按钮,在第三个插槽中放置一个快进按钮,并使第一个和最后一个插槽为空:

// 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_emptyCastContext 可以管理此 activity 的生命周期和呈现。

添加自定义按钮

ExpandedControllerActivity 支持添加 SDK 未提供的自定义控制按钮, 例如“赞”按钮。具体步骤包括:

  1. castControlButtonsExpandedControllerActivity 属性中使用 @id/cast_button_type_custom 指定包含自定义按钮的插槽。 然后,您可以使用 getButtonImageViewAt(int) 获取该自定义按钮的 ImageView

  2. 实现 UIController的子类。 UIController 包含在 Cast 会话或媒体会话的状态发生变化时由 SDK 调用的方法。UIController 的子类应将 ImageView 作为其中一个参数,并根据需要更新其状态。

  3. 对 ExpandedControllerActivity 进行子类化,然后替换 onCreate 并调用 getButtonImageViewAt(int) 以获取按钮的视图对象。然后调用 bindViewToUIController(View, UIController) 以将视图与自定义 UIController 相关联。

  4. 如需了解如何处理自定义按钮的操作,请参阅 MediaIntentReceiver 添加自定义操作 中的 `MediaIntentReceiver`。

以下示例展示了如何将插槽 2 中的按钮与名为 MyCustomUIControllerUIController相关联:

// 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);
        ...
    }
}