התאמה אישית של ממשק המשתמש של השולח ב-Android

אתם יכולים להתאים אישית את ווידג'טים של העברה על ידי הגדרת הצבעים, עיצוב הלחצנים, הטקסט והתמונה הממוזערת, ובחירת סוגי הלחצנים שיוצגו.

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

בדוגמה הזו נוצר סגנון עיצוב מותאם אישית 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);
        ...
    }
}

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

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

אם בפעילות של אמצעי בקרה מורחב נעשה שימוש בסרגל כלים בעיצוב כהה, תוכלו להגדיר לעיצוב של סרגל הכלים טקסט בהיר וצבע סמל בהיר:

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

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

// 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. יוצרים תת-מחלקה של 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);
        ...
    }
}