התאמה אישית של ממשק המשתמש של השולח ב-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 מכיל methods שה-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>
קוטלין
// 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) כדי לקבל את אובייקט View של הלחצן. לאחר מכן קוראים ל-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>
קוטלין
// 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);
        ...
    }
}