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

מצהירים על העיצוב המותאם אישית של 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 יש שלוש משבצות שיכולות להציג את עטיפת האלבום ושני לחצנים, או שלושה לחצני בקרה אם עטיפת האלבום לא מאוכלסת.

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

התאמה אישית של השלט המורחב

התאמה אישית של העיצוב

אם ב-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 כדי לשנות את הלחצנים שמוצגים במיקומים השונים. רשימת לחצני הבקרה הנתמכים מוגדרת כמשאבי מזהה זהים לסוגי הלחצנים של לחצני הבקר המיני.

הנה דוגמה שבה לחצן ההרצה אחורה ממוקם במשבצת השנייה, לחצן הדילוג קדימה ממוקם במשבצת השלישית, והמשבצת הראשונה והאחרונה נשארות ריקות:

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