自訂 Android Sender UI

您可以自訂投放小工具,方法是設定顏色、設定按鈕、文字和縮圖的外觀樣式,以及選擇要顯示的按鈕類型。

自訂應用程式主題

這個範例會建立自訂主題樣式 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 資源

按鈕類型 說明
@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. MiniControllerFragmentcastControlButtons 屬性中使用 @id/cast_button_type_custom,指定要用來容納自訂按鈕的空格。

  2. 實作 UIController 的子類別。UIController 包含 SDK 在投放工作階段或媒體工作階段狀態變更時呼叫的方法。UIController 的子類別應將 ImageView 做為其中一個參數,並視需要更新其狀態。

  3. 建立 MiniControllerFragment 子類別,然後覆寫 onCreateView 並呼叫 getButtonImageViewAt(int),以便取得該自訂按鈕的 ImageView。接著呼叫 bindViewToUIController(View, UIController),將檢視區塊與自訂 UIController 建立關聯。

  4. 如要瞭解如何處理自訂按鈕的動作,請參閱「新增自訂動作」一節中的 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
        ...
    }
}

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

自訂展開的控制器

自訂主題

如果展開的控制器活動使用深色主題工具列,您可以在工具列上設定主題,以便使用淺色文字和淺色圖示顏色:

<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 覆寫要在哪個版位顯示哪些按鈕。支援的控制按鈕清單會定義為 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 可管理此活動的生命週期和呈現方式。

新增自訂按鈕

ExpandedControllerActivity 支援新增 SDK 未提供的自訂控制按鈕,例如「喜歡」按鈕。步驟如下:

  1. ExpandedControllerActivitycastControlButtons 屬性中使用 @id/cast_button_type_custom,指定要用來容納自訂按鈕的空格。接著,您可以使用 getButtonImageViewAt(int) 取得該自訂按鈕的 ImageView

  2. 實作 UIController 的子類別。UIController 包含 SDK 在投放工作階段或媒體工作階段狀態變更時呼叫的方法。UIController 的子類別應將 ImageView 做為其中一個參數,並視需要更新其狀態。

  3. 建立 ExpandedControllerActivity 子類別,然後覆寫 onCreate 並呼叫 getButtonImageViewAt(int),以取得按鈕的 View 物件。接著呼叫 bindViewToUIController(View, UIController),將檢視區塊與自訂 UIController 建立關聯。

  4. 如要瞭解如何處理自訂按鈕的動作,請參閱「新增自訂動作」一文中的 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);
        ...
    }
}