ปรับแต่ง UI ผู้ส่งของ 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>

3 บรรทัดสุดท้ายด้านบนช่วยให้คุณกำหนดรูปแบบเฉพาะสำหรับการวางซ้อนเบื้องต้น ตัวควบคุมขนาดเล็ก และตัวควบคุมแบบขยายเป็นส่วนหนึ่งของธีมนี้ได้ โดยมีตัวอย่างรวมอยู่ในส่วนต่างๆ ที่จะกล่าวถึงต่อไป

ปรับแต่งปุ่ม Cast

วิธีเพิ่ม 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 มี 3 ช่องที่สามารถแสดงภาพปกอัลบั้มและปุ่ม 2 ปุ่ม หรือปุ่มควบคุม 3 ปุ่มหากไม่มีภาพปกอัลบั้ม

SLOT  SLOT  SLOT
  1     2     3

โดยค่าเริ่มต้น Fragment จะแสดงปุ่มสลับเล่น/หยุดชั่วคราว นักพัฒนาแอปสามารถใช้แอตทริบิวต์ 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">

คำเตือน: อาร์เรย์นี้ต้องมีรายการ 3 รายการเท่านั้น มิฉะนั้นระบบจะแสดงข้อยกเว้นรันไทม์ หากไม่ต้องการแสดงปุ่มในช่องใดช่องหนึ่ง ให้ใช้ @id/cast_button_type_empty

เพิ่มปุ่มที่กำหนดเอง

MiniControllerFragment รองรับการเพิ่มปุ่มควบคุมที่กำหนดเองซึ่ง SDK ไม่ได้ให้มา เช่น ปุ่ม "ถูกใจ" โดยมีขั้นตอนดังนี้

  1. ระบุช่องที่จะมีปุ่มที่กำหนดเองโดยใช้ @id/cast_button_type_custom ในแอตทริบิวต์ castControlButtons ของ MiniControllerFragment

  2. ใช้คลาสย่อยของ UIController UIController มีเมธอดที่ SDK เรียกใช้เมื่อสถานะของเซสชัน Cast หรือเซสชันสื่อมีการเปลี่ยนแปลง คลาสย่อยของ 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);
        ...
    }
}

ปรับแต่งตัวควบคุมแบบขยาย

ปรับแต่งธีม

หากกิจกรรมของตัวควบคุมแบบขยายใช้แถบเครื่องมือธีมสีเข้ม คุณสามารถตั้งค่าธีมในแถบเครื่องมือให้ใช้ข้อความสีอ่อนและสีไอคอนสีอ่อนได้

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

เลือกปุ่ม

กิจกรรมของตัวควบคุมแบบขยายมี 5 ช่องสำหรับแสดงปุ่มควบคุม ช่องตรงกลางจะแสดงปุ่มสลับเล่น/หยุดชั่วคราวเสมอและกำหนดค่าไม่ได้ ส่วนช่องอื่นๆ 4 ช่องจะกำหนดค่าได้จากซ้ายไปขวาโดยแอปผู้ส่ง

SLOT  SLOT  PLAY/PAUSE  SLOT  SLOT
  1     2     BUTTON      3     4

โดยค่าเริ่มต้น กิจกรรมจะแสดงปุ่มคำบรรยายแทนเสียง ปุ่มข้ามไปยังรายการก่อนหน้า ปุ่มข้ามไปยังรายการถัดไป และปุ่มสลับปิดเสียงใน 4 ช่องนี้จากซ้ายไปขวา นักพัฒนาแอปสามารถใช้แอตทริบิวต์ castControlButtons เพื่อลบล้างปุ่มที่จะแสดงในช่องต่างๆ รายการปุ่มควบคุมที่รองรับจะกำหนดเป็น ทรัพยากรรหัสที่เหมือนกับ ประเภทปุ่มสำหรับปุ่มตัวควบคุมขนาดเล็ก

ตัวอย่างต่อไปนี้แสดงการวางปุ่มกรอกลับในช่องที่ 2 ปุ่มข้ามไปข้างหน้าในช่องที่ 3 และปล่อยให้ช่องแรกและช่องสุดท้ายว่างไว้

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

อาร์เรย์ต้องมีรายการ 4 รายการเท่านั้น มิฉะนั้นระบบจะแสดงข้อยกเว้นรันไทม์ หากไม่ต้องการแสดงปุ่มในช่องใดช่องหนึ่ง ให้ใช้ @id/cast_button_type_empty CastContext สามารถจัดการวงจรการทำงานและการนำเสนอกิจกรรมนี้ได้

เพิ่มปุ่มที่กำหนดเอง

An ExpandedControllerActivity รองรับการเพิ่มปุ่มควบคุมที่กำหนดเองซึ่ง SDK ไม่ได้ให้มา เช่น ปุ่ม "ถูกใจ" โดยมีขั้นตอนดังนี้

  1. ระบุช่องที่จะมีปุ่มที่กำหนดเองโดยใช้ @id/cast_button_type_custom ในแอตทริบิวต์ castControlButtons ของ ExpandedControllerActivity จากนั้นคุณสามารถใช้ getButtonImageViewAt(int) เพื่อรับ ImageView สำหรับปุ่มที่กำหนดเองนั้น

  2. ใช้คลาสย่อยของ UIController UIController มีเมธอดที่ SDK เรียกใช้เมื่อสถานะของเซสชัน Cast หรือเซสชันสื่อมีการเปลี่ยนแปลง คลาสย่อยของ 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);
        ...
    }
}