מעקב אחרי חשיפה ב"פיתוח נייטיב"

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

  • ‫onVisibilityChanged – המשתנה הזה מודיע לכם כשהחשיפה של composable משתנה. הוא אידיאלי להפעלת פעולה או תופעת לוואי בכל פעם שהרכיב ה-composable הופך לגלוי.
  • ‫onLayoutRectChanged – המשתנה הזה מספק מידע על הגבולות של רכיב ה-composable ביחס לרכיב הבסיס, לחלון ולמסך. הוא מציע שליטה ברמה נמוכה, והוא ה-API הבסיסי של onVisibilityChanged. המשתנה דומה ל-onGloballyPositioned, אבל הוא מציע ביצועים טובים יותר וגמישות רבה יותר.

אפשר להשתמש בממשקי ה-API האלה עם כל רכיב Composable כחלק משרשרת ה-modifier.

מעקב אחרי שינויים בחשיפה באמצעות onVisibilityChanged

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

כדי לקבל התראה כשהחשיפה של פריט משתנה, משתמשים ב-modifier‏ onVisibilityChanged, כמו בדוגמה הבאה:

Text(
    text = "Some text",
    modifier = Modifier
        .onVisibilityChanged { visible ->
            if (visible) {
                // Do something if visible.
            } else {
                // Do something if not visible.
            }
        }
        .padding(vertical = 8.dp)
)

העיבוד onVisibilityChanged מספק ערך בוליאני שמשקף את מצב החשיפה הנוכחי של הפונקציה הקומפוזבילית. בנוסף, הוא מציע פרמטרים כמו minFractionVisible ו-minDurationMs, שמאפשרים לכם לקבוע בצורה מדויקת יותר מתי להפעיל את פונקציית ה-callback של החשיפה.

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

הגדרת מגבלת זמן לרכיב קומפוזבילי לפני הפעלת קריאה חוזרת (callback) לחשיפה

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

כדי להפעיל פעולה אחרי שפריט גלוי למשך פרק זמן מוגדר, משתמשים בפרמטר minDurationMs ב-modifier‏ onVisibilityChanged. הפרמטר הזה מציין את משך הזמן המינימלי שבו רכיב Composable צריך להיות גלוי ברציפות כדי שהקריאה החוזרת תופעל. אם הרכיב הניתן לקיבוץ מפסיק להיות גלוי לפני שחלף משך הזמן, הטיימר מתאפס. ערך ברירת המחדל הוא 0 אלפיות השנייה.

קטע הקוד הבא משנה את הרקע לסגול אחרי שהפונקציה הקומפוזבילית גלויה למשתמש במשך 3 שניות:

var background by remember { mutableStateOf(PalePink) }
Card(
    modifier = modifier
        // ...
        .onVisibilityChanged(minDurationMs = 3000) {
            if (it) {
                background = MutedPlum
            }
        }
) {

    Box(
        modifier = Modifier
            // ...
            .background(background),
        contentAlignment = Alignment.Center,
    ) {
        // ...
    }
}

איור 1. הרקע משתנה מוורוד לשזיף אחרי שהפונקציה הקומפוזבילית מופיעה במסך במשך 3 שניות ברציפות.

הגדרת שיעור חשיפה מינימלי

הגדרת שיעור חשיפה מינימלי לקריאה החוזרת (callback) של הרכיב הניתן לשינוי שימושית כשעובדים עם תוכן שניתן לגלילה (לדוגמה, LazyColumn) כדי לשפר את אחזור הנתונים של פריטים שחורגים מגודל המסך.

במקרים כאלה, משתמשים בפרמטר minFractionVisible ב-modifier‏ onVisibilityChanged כדי להגדיר את החלק שצריך להופיע במסך כדי שה-composable יסומן כגלוי. אפשר להזין ערכים מסוג float בטווח שבין 0.0f ל-1.0f, והערך שמוגדר כברירת מחדל הוא 1.0f. ‫1.0f פירושו שהרכיב הניתן להרכבה צריך להיות גלוי לחלוטין במסך, או למלא את כל אזור התצוגה אם הוא גדול יותר מאזור התצוגה.

הקריאה החוזרת מקבלת את הערך true כשהחלק הגלוי גדול מ-minFractionVisible, או כשהפונקציה הקומפוזבילית גלויה לגמרי או ממלאת את אזור התצוגה. אחרת, הוא מקבל false.

LazyColumn(
    modifier = modifier.fillMaxSize()
) {
    item {
        Box(
            modifier = Modifier
                // ...
                // Here `visible` is `true` when more than 20% of the composable is visible.
                .onVisibilityChanged(
                    minFractionVisible = 0.2f,
                ) { visible ->
                    if (visible) {
                        // Call specific logic here.
                        // viewModel.fetchDataFromNetwork()
                    }
                }
                .padding(vertical = 16.dp)
        ) {
            Text(
                text = "Sample Text",
                modifier = Modifier.padding(horizontal = 16.dp)
            )
        }
    }
}

איור 2. בלי להגדיר את minFractionVisible. איור 3. כאשר minFractionVisible מוגדר כ-0.2f.

בדוגמה הקודמת, הבוטים של Androidify נטענים מראש מהרשת לפני שהרכיב הקומפוזבילי גלוי לחלוטין. באיור 2, הבוט השלישי לא נטען כי הרכיב הניתן לשילוב לא גלוי במלואו. באיור 3, minFractionVisible מוגדר, והבוט השלישי נטען לפני שהוא גלוי לחלוטין במסך.

הסתרה של רכיב Composable ושמירה על המקום שלו

כדי להסתיר רכיב Composable בלי לשנות את הפריסה מסביב, משתמשים במשנה visible. כשמעבירים את הערך false, התוכן הקומפוזבילי עדיין נמדד אבל לא ממוקם או משורטט. בניגוד להגדרה של alpha לערך 0f, הערך visible(false) גם מסיר את הרכיב מעץ הנגישות ומשבית את האינטראקציות במגע, תוך שמירה על שטח הפריסה שלו.

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

Row(modifier, verticalAlignment = Alignment.CenterVertically) {
    Icon(
        painter = painterResource(R.drawable.check),
        contentDescription = "Saved",
        modifier = Modifier
            // The icon keeps its space while it's hidden, so the text doesn't move.
            .visible(isSaved)
    )
    Text("Draft", Modifier.padding(start = 8.dp))
}

משתמשים ב-visible כשהפריסה מסביב לתוכן הקומפוזבילי לא צריכה לזוז כשהתוכן הקומפוזבילי מופיע ונעלם. כדי להסיר את הפונקציה הקומפוזבילית ואת המקום שלה, אל תקראו לה, או השתמשו ב-AnimatedVisibility כדי להוסיף לה אנימציה פנימה והחוצה.