自訂 Android Sender UI

您可以自訂 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>

宣告自訂媒體路由器主題和自訂 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. 使用 MiniControllerFragment 的 castControlButtons 屬性中的 @id/cast_button_type_custom,指定要包含自訂按鈕的位置。

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

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

  4. 請參閱「新增自訂動作」中的 MediaIntentReceiver,瞭解如何處理自訂按鈕的動作。

    以下範例說明如何將版位 2 的按鈕與名為 MyCustomUIController 的 UIController 建立關聯:

// 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_empty。CastContext 可以管理這項活動的生命週期和呈現方式。

新增自訂按鈕

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

  1. 使用 ExpandedControllerActivity 的 castControlButtons 屬性中的 @id/cast_button_type_custom,指定要包含自訂按鈕的版位。接著,您可以使用 getButtonImageViewAt(int) 取得該自訂按鈕的 ImageView。

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

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

  4. 請參閱「新增自訂動作」中的 MediaIntentReceiver,瞭解如何處理自訂按鈕的動作。

以下範例說明如何將版位 2 的按鈕與名為 MyCustomUIController 的 UIController 建立關聯:

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