אפליקציות ל-Android פועלות ביותר גורמי צורה מאשר רק בטלפונים שמחזיקים במצב לאורך. עם ההשקה של ממשק מחשב, מסכים מחוברים ומכשירים מתקפלים, אפליקציית המצלמה צריכה להתאים את עצמה לגדלים דינמיים של חלונות, ליחסי גובה-רוחב משתנים ולחומרה חיצונית.
למה הלוגיקה של הטלפון נכשלת
אפליקציות מצלמה מניחות לעיתים הנחות שגורמות לכשלים קריטיים בסביבות עם גורמי צורה מרובים.
כיוון טבעי
- הנחה: הכיוון הטבעי של המכשיר
ROTATION_0הוא תמיד לאורך - בפועל: בטאבלטים, בחלק מהמסכים הפנימיים של מכשירים מתקפלים ובמסכים של מחשבים שולחניים,
ROTATION_0הוא לרוב לרוחב - תוצאה: התצוגה המקדימה מסובבת ב-90 מעלות בצורה שגויה
יישור החיישן
- הנחה: הצד הארוך של חיישן המצלמה מיושר עם הצד הארוך של המסך
- מציאות: חלון שניתן לשינוי גודל יכול להיות ריבועי או לרוחב, בזמן שהחיישן נשאר קבוע (בדרך כלל 4:3)
- תוצאה: תמונות מתוחות או מעוותות
דחיסות וגודל המסך
- הנחה: הצפיפות והגודל של המסך לא משתנים בזמן הריצה
- המצב בפועל: בסביבות של מחשבים, המשתמשים יכולים לשנות את הגודל של החלונות באופן חופשי
- תוצאה: הפעלה מחדש של סשן המצלמה בכל אירוע גרירה משבשת את חוויית המשתמש ועלולה לגרום לקריסות
פתרון 1: שימוש בכוונות של המערכת
אם האפליקציה שלכם צריכה לצלם תמונה או סרטון, אבל לא נדרש ממשק מצלמה מותאם אישית, הדרך הכי טובה להתמודד עם גורמי צורה שונים היא להפעיל את מצלמת המערכת שהותקנה מראש במכשיר (ראו Camera intents).
שימוש ב-intent של המערכת מעביר את כל חוויית הצילום לאפליקציית המצלמה שפותחה על ידי יצרן הציוד המקורי (OEM) של המכשיר. המשמעות היא מיקור חוץ של המורכבות של תמיכה בגורם צורה, כולל:
- תמיכה מובנית בשינוי גודל ובסיבוב – אפליקציית המצלמה שמוגדרת כברירת מחדל בטאבלט או במכשיר מתקפל נבנית במפורש על ידי היצרן כדי לטפל בגיאומטריה הספציפית של המכשיר. האפליקציה מתוכננת להתנהג בצורה תקינה כשהמכשיר נפתח, מסובב או מועבר למצב ריבוי חלונות.
- גישה לתכונות מתקדמות של החומרה – לאפליקציות מצלמה של יצרן הציוד המקורי יש גישה בלעדית לאלגוריתמים מותאמים לחומרה (מצב לילה, HDR, החלפה של עדשה ספציפית) שקשה או בלתי אפשרי לשכפל באופן ידני.
פתרון 2: שימוש ב-Jetpack CameraX
CameraX היא ספריית Jetpack שנוצרה כדי להקל על פיתוח אפליקציות מצלמה. CameraX מודעת למחזור החיים ומכוונת למשטח. בניגוד ל-Camera2, שדורשת חישוב מחדש ידני של כיוון החיישן וגדלי המשטחים בכל פעם שמקפלים, מסובבים או משנים את הגודל של המכשיר, CameraX מטפלת אוטומטית בהגדרה מחדש של סשנים של המצלמה במהלך שינוי הגודל של ריבוי חלונות או כשמעבירים אפליקציה לתצוגה מחוברת, וכך מבטיחה שזרם התצוגה המקדימה יותאם בלי לגמגם או להימתח.
רכיבים כמו PreviewView מנהלים בצורה חכמה את יחס הגובה-רוחב ואת סוגי קנה המידה במצבים שונים, כמו מעבר של מכשיר מתקפל ממסך חיצוני למסך פנימי. כך אפשר לתמוך במגוון רחב של חומרה באמצעות הטמעה עקבית אחת, במקום אוסף מורכב של מקרים פרטיים שספציפיים למכשיר.
כתיבה
ב-Jetpack פיתוח נייטיב, משתמשים בספרייה הייעודית androidx.camera:camera-compose. הספרייה מספקת את הרכיב הקומפוזבילי CameraXViewfinder, שנועד במיוחד לטפל בגיאומטריה המורכבת של שינוי גודל, סיבוב ויחסי גובה-רוחב במסגרת מחזור החיים של Compose.
רכיב CameraXViewfinder מסיר את המקורות הנפוצים ביותר לשגיאות באפליקציות מצלמה:
- המרת קואורדינטות אוטומטית – אחד החלקים הכי קשים בפיתוח אפליקציית מצלמה הוא מיפוי של הקשה של משתמש (קואורדינטות x, y במסך) למערכת הקואורדינטות של חיישן המצלמה (0-1, 0-1 מסובב) לצורך מיקוד ומדידה.
CameraXViewfinderמספקCoordinateTransformerשמטפל בחישובים באופן אוטומטי, גם כשמשנים את גודל החלון או כשמקפלים את המכשיר. - התנהגות נכונה של פריסה – בניגוד ל-
SurfaceViewאו ל-TextureView,CameraXViewfinderפועל בצורה נכונה עם הסדר של שכבות ה-Z ב-Compose. אתם יכולים להוסיף שכבת-על של רכיבי ממשק משתמש (טבעות מיקוד, אמצעי בקרה) או להחיל משנים (פינות מעוגלות, אנימציות) בלי להציג ארטיפקטים של רינדור. - שינוי גודל ויחס גובה-רוחב:
CameraXViewfinderמטפל באופן פנימי בלוגיקה של חיתוך במרכז לעומת התאמה למרכז, כדי שהתצוגה המקדימה לא תימתח כשמשנים את הגודל של חלון האפליקציה ליחסי גובה-רוחב לא סטנדרטיים (לדוגמה, מסך מפוצל או מצב ממשק מחשב).
צפיות
באפליקציות מבוססות-תצוגה, משתמשים ב-PreviewView או ב-ViewFinderView. אם אתם משתמשים ישירות ב-SurfaceView או ב-TextureView, אתם צריכים לחשב את יחס הגובה-רוחב ולהחיל בעצמכם את מטריצת הטרנספורמציה הנכונה.
פתרון 3: טיפול דינמי בכיוון ובשינוי הגודל
כשמשתמשים ישירות בממשקי API של פלטפורמות, חשוב לזכור את סיבוב המכשיר, את ההפעלה מחדש של הפעילות ואת יחס הגובה-רוחב.
הפסקת השימוש בסיבוב המכשיר
אל תסתמכו רק על Display#getRotation() או על כיוון החיישן הפיזי כדי לקבוע את פריסה של ממשק המשתמש.
- שימוש במדדי חלון – כדי לקבוע את הפריסה (ממשק משתמש לרוחב לעומת ממשק משתמש לאורך) משווים את הרוחב והגובה של חלון האפליקציה באמצעות
WindowManager#getCurrentWindowMetrics(). - התעלמות מהכיוון הטבעי – יכול להיות שהאפליקציה מוצגת בחלון בצורת פורטרט במסך לרוחב. הכיוון של המכשיר לא רלוונטי לגבולות של ממשק המשתמש.
איך להימנע מהפעלה מחדש של פעילות
התנהגות ברירת המחדל של Android היא השמדה של הפעילות של האפליקציה בשינויים בהגדרות (כמו שינוי הגודל של החלון). באפליקציות של מצלמות, הבעיה הזו מופיעה כהבהוב במסך או כניתוק במהלך שיחות וידאו.
- הגדרת המניפסט – כדי לשנות את הגודל בלי להפעיל מחדש את האפליקציה, צריך להצהיר על שינויים בהגדרות במניפסט.
- עדכונים דינמיים – ב-
onConfigurationChanged(), מעדכנים את פרמטרי הפריסה של התצוגה המקדימה של המצלמה כך שיתאימו לגודל החלון החדש.
יחס גובה-רוחב וחיתוך
בעיה נפוצה במכשירים מתקפלים ובחלונות במחשב היא מתיחה של התצוגה המקדימה, שבה פיד המצלמה ביחס של 4:3 נמתח בכוח לחלון ביחס של 16:9 או 1:1.
- לא למתוח – אף פעם לא מכריחים את מאגר המצלמה להתאים בדיוק לגבולות התצוגה אם יחסי הגובה-רוחב של התצוגה המקדימה והחלון שונים.
- חיתוך במרכז (מומלץ): שינוי קנה המידה של התצוגה המקדימה כך שתמלא את המימד הקצר ביותר של החלון וחיתוך של החלקים העודפים. כך מוודאים שהנושא לא מעוות וממלא את המסגרת.
- התאמה למרכז (אפשרות חלופית): אם חשוב להציג את כל שדה הראייה (לדוגמה, כשסורקים מסמך), אפשר להוסיף מסגרת שחורה לתצוגה המקדימה בתוך החלון.
בונוס: תמיכה בחוויות שימוש שמתאימות במיוחד למכשירים מתקפלים
מכשירים מתקפלים הם לא רק טלפונים שאפשר לכופף. הם גם מציעים מצבי חומרה ייחודיים שיכולים לשפר באופן משמעותי את האופן שבו משתמשים מצלמים תמונות וסרטונים. במקום להתייחס לקיפול כבעיה שצריך לפתור, אפשר להשתמש בו כדי ליצור תכונות שלא אפשריות במכשירים לא מתקפלים.
מצב שולחני (צילום בהפעלה קולית)
מצב שולחני מאפשר למשתמשים לקפל את המכשיר לחצי ולהניח אותו על משטח כדי לבצע שיחות וידאו ארוכות, לצלם תמונות בטכניקת Time-lapse ולצלם תמונות של הלילה בחשיפה ארוכה.
מצב מסך אחורי (תמונות סלפי באיכות גבוהה)
- במכשירים מתקפלים, המצלמות האחוריות הן בדרך כלל באיכות גבוהה יותר מהמצלמות הקדמיות. מצב מסך אחורי מאפשר למשתמש לפתוח את המכשיר ולהפוך אותו, כך שמסך הכיסוי הקטן משמש כעינית בזמן אמת למצלמה האחורית הראשית.
- מצב הצילום במסך האחורי מאפשר לצלם סלפי באיכות של 50MP ומעלה, תמונות קבוצתיות רחבות במיוחד וסרטוני וולוגינג באיכות גבוהה בלי לשאת ציוד נוסף.
מצב מסך מפוצל (תצוגה מקדימה של התכונה)
- מצב מסך כפול מאפשר לכם להציג את התצוגה המקדימה של המצלמה בשני המסכים – הפנימי והחיצוני – בו-זמנית. האפשרות הזו מושלמת לצילום אנשים: האנשים שמצולמים יכולים לראות את עצמם במסך החיצוני ולשנות את התנוחה שלהם בזמן שאתם מכוונים את הפריים במסך הפנימי.
- בניגוד למצב של מסך אחורי (שמעביר את כל האפליקציה), במצב של מסך כפול נוצר חלון משני של המצגת במסך הכיסוי.