تخصيص واجهة مستخدم Android Sender

يمكنك تخصيص التطبيقات المصغّرة للبث. من خلال ضبط الألوان وتصميم الأزرار والنص والصورة المصغّرة ومظهره، ومن خلال اختيار أنواع الأزرار التي سيتم عرضها.

تخصيص مظهر التطبيق

ينشئ هذا المثال نمط مظهر مخصصًا 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>

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>
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 لإلغاء الأزرار التي يتم عرضها الخانات. يتم تعريف قائمة أزرار التحكم المتوافقة كما يلي: تتطابق موارد المعرفات مع أنواع الأزرار الخاصة بأزرار وحدة التحكّم الصغيرة.

إليك مثال يضع زر ترجيع في الخانة الثانية، زر التخطي زر للأمام في الخانة الثالثة، وترك الخانتين الأولى والأخيرة فارغتين:

// 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. الفئة الفرعية ExtendedControllerActivity، ثم تجاوز 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);
        ...
    }
}