התאמה אישית של ממשק המשתמש של השולח ב-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.

התאמה אישית של העיצוב של שכבת-העל של ההקדמה

המחלקות 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 כשהמצב של סשן ה-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>

בחירת כפתורים

בבקר המורחב יש חמישה מקומות להצגת לחצני בקרה. במשבצת האמצעית תמיד מופיע כפתור הפעלה או השהיה, ואי אפשר להגדיר אותו. ארבעת המשבצות האחרות ניתנות להגדרה על ידי אפליקציית השולח, משמאל לימין.

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 כשהמצב של סשן ה-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);
        ...
    }
}