מדריכים

אנחנו גאים להציג את Cahier: דוגמה חדשה של Android GitHub ליצירתיות ולפרודוקטיביות במסך גדול

משך הקריאה: 11 דקות
Chris Assigbe
מהנדס קשרי מפתחים

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

אפליקציות Google, כמו Google Docs, ‏ Pixel Studio, ‏ Google Photos, ‏ Chrome PDF, ‏ Youtube Effect Maker ותכונות ייחודיות ב-Android כמו מקיפים ומחפשים,כולן משתמשות בממשקי ה-API העדכניים ביותר. 

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

מה זה Cahier?

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

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

התכונות העיקריות שמוצגות בדוגמה כוללות:

  • יצירת הערות מגוונת: הסבר על הטמעה של מערכת גמישה ליצירת תוכן שתומכת בפורמטים שונים בהערה אחת, כולל טקסט, ציורים חופשיים וקבצים מצורפים של תמונות.
  • כלים יצירתיים לציור בדיו: הטמעה של חוויית ציור עם ביצועים גבוהים וזמן אחזור נמוך באמצעות Ink API. הדוגמה מספקת דוגמה מעשית לשילוב של מגוון מכחולים, בוחר צבעים, פונקציונליות של ביטול פעולה/ביצוע חוזר של פעולה וכלי מחיקה.
  • שילוב תוכן גמיש באמצעות גרירה ושחרור: סרטון שמראה איך לטפל בתוכן נכנס ויוצא באמצעות גרירה ושחרור. זה כולל קבלת תמונות שנמשכו מאפליקציות אחרות, ומתן אפשרות למשתמשים לגרור תוכן מהאפליקציה שלכם כדי לשתף אותו בקלות.
  • ארגון ההערות: אפשר לסמן הערות כמועדפות כדי לגשת אליהן במהירות. כדי לשמור על הסדר, אפשר לסנן את התצוגה.
  • ארכיטקטורה של אופליין קודם כל: האפליקציה מבוססת על ארכיטקטורה של אופליין קודם כל באמצעות Room, כך שכל הנתונים נשמרים באופן מקומי והאפליקציה ממשיכה לפעול באופן מלא גם בלי חיבור לאינטרנט.
  • תמיכה רבת עוצמה בריבוי חלונות וכמה מופעים במקביל: הדוגמה הזו מראה איך לתמוך בכמה מופעים במקביל, כך שאפשר להפעיל את האפליקציה בכמה חלונות כדי שהמשתמשים יוכלו לעבוד על כמה פתקים זה לצד זה, ולשפר את הפרודוקטיביות והיצירתיות במסכים גדולים.
  • ממשק משתמש אדפטיבי לכל המסכים: ממשק המשתמש מותאם בצורה חלקה לגדלים ולכיוונים שונים של מסכים באמצעות ListDetailPaneScaffold ו- NavigationSuiteScaffold כדי לספק חוויית משתמש אופטימלית בטלפונים, בטאבלטים ובמכשירים מתקפלים.
  • שילוב עמוק במערכת: מדריך שמסביר איך להגדיר את האפליקציה כאפליקציה לרישום הערות שמוגדרת כברירת מחדל ב-Android מגרסה 14 ואילך. כדי לעשות זאת, צריך להגיב ל-Intents של הערות ברמת המערכת, וכך לאפשר ללכוד תוכן במהירות מנקודות כניסה שונות במערכת.

מיועד לפרודוקטיביות וליצירתיות במסכים גדולים

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

בסיס של יכולת הסתגלות

Cahier מתוכנן להיות מותאם מהיסוד. בדוגמה נעשה שימוש בספרייה material3-adaptive, ובאופן ספציפי ברכיבים ListDetailPaneScaffold ו-NavigationSuiteScaffold, כדי להתאים את פריסת האפליקציה למגוון גדלים וכיוונים של מסכים בצורה חלקה. זהו רכיב חיוני באפליקציות מודרניות ל-Android, ו-Cahier מספקת דוגמה ברורה לאופן ההטמעה שלו בצורה יעילה.

ממשק משתמש מותאם של Cahier שנבנה באמצעות ספריית ההתאמה של Material 3..gif

ממשק משתמש אדפטיבי של Cahier שנבנה באמצעות ספריית Material 3 Adaptive

הצגת ממשקי API ושילובים מרכזיים

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

מבט מקרוב על ממשקי API מרכזיים

בואו נתעמק בשני ממשקי API מרכזיים שמשולבים ב-Cahier כדי לספק חוויית סיכום ברמה גבוהה.

יצירת חוויות כתיבה טבעיות באמצעות Ink API

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

ממשק Ink API מציע ארכיטקטורה מודולרית, כך שאפשר להתאים אותו לסטאק ולצרכים הספציפיים של האפליקציה. מודולי ה-API כוללים:

  • מודולים ליצירת תוכן (Composeviews): טיפול בקלט של דיו בזמן אמת כדי ליצור קווים חלקים עם ההשהיה הנמוכה ביותר שהמכשיר יכול לספק.
    • ב-DrawingSurface, ‏ Cahier משתמש ברכיב החדש InProgressStrokes כדי לטפל בקלט של עט או מגע בזמן אמת. המודול הזה אחראי ללכידת אירועי הצבעה ולעיבוד של משיכות מכחול עם זמן האחזור הנמוך ביותר האפשרי.
  • מודול Strokes: מייצג את הקלט של הדיו ואת הייצוג החזותי שלו.כשמשתמש מסיים לצייר קו, הקריאה החוזרת onStrokesFinished מספקת לאפליקציה אובייקט Stroke סופי/יבש. האובייקט הבלתי ניתן לשינוי הזה, שמייצג את קו הדיו שהושלם, מנוהל לאחר מכן ב-DrawingCanvasViewModel.
  • מודול רינדור: מציג ביעילות קווים של דיו, ומאפשר לשלב אותם עם Jetpack פיתוח נייטיב או תצוגות של Android.
    • כדי להציג את הקווים הקיימים ואת הקווים החדשים שנוצרו, Cahier משתמש ב-CanvasStrokeRenderer ב-DrawingSurface לציור פעיל וב-DrawingDetailPanePreview להצגת תצוגה מקדימה סטטית של ההערה. המודול הזה מצייר ביעילות את האובייקטים של Stroke על Canvas.
  • מודולים של מברשות (Composeviews): מאפשרים להגדיר את הסגנון החזותי של המשיכות בצורה הצהרתית. העדכונים האחרונים (מאז גרסת אלפא03) כוללים מברשת חדשה של קו מקווקו, שימושית במיוחד לתכונות כמו בחירת לאסו. ‫DrawingCanvasViewModel מכיל את המצב של currentBrush. ארגז כלים ב-DrawingCanvas מאפשר למשתמשים לבחור משפחות שונות של מכחולים (כמו StockBrushes.pressurePen() או StockBrushes.highlighter()) ולשנות צבעים. ה- ViewModel מעדכן את האובייקט Brush, שמשמש לאחר מכן את הקומפוזיציה InProgressStrokes עבור קווים חדשים.
  • מודולים של גיאומטריה (Composeviews): תמיכה במניפולציה ובניתוח של קווים לתכונות כמו מחיקה ובחירה.
    • כלי המחק בתיבת הכלים והפונקציונליות ב-DrawingCanvasViewModel מסתמכים על מודול הגיאומטריה. כשהמחק פעיל, הוא יוצר מקבילית שניתנת לשינוי סביב הנתיב של תנועת המשתמש. הכלי 'מחק' בודק אם יש נקודות חיתוך בין הצורה לבין התיבות התוחמות של הקווים הקיימים כדי לקבוע אילו קווים למחוק, וכך הוא מרגיש אינטואיטיבי ומדויק.
  • מודול אחסון: מספק יכולות יעילות של סריאליזציה ודה-סריאליזציה לנתוני דיו, וכך חוסך משמעותית במקום בדיסק ובגודל הרשת. כדי לשמור ציורים, Cahier שומר את אובייקטי הקו במסד הנתונים Room שלו. בקטע Converters, בדוגמה נעשה שימוש בפונקציה encode של מודול האחסון כדי לבצע סריאליזציה של StrokeInputBatch (נתוני הנקודות הגולמיים) ל- ByteArray. מערך הבייטים, יחד עם מאפייני המברשת, נשמר כמחרוזת JSON. הפונקציה decode משמשת לשחזור הקווים כשמעלים הערה.
orion.png

בנוסף למודולים הבסיסיים האלה, העדכונים האחרונים הרחיבו את היכולות של Ink API:

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

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

לייזר בצבעי הקשת שנוצר באמצעות המברשות המותאמות אישית של Ink API..gif

לייזר בצבעי הקשת שנוצר באמצעות מברשות בהתאמה אישית של Ink API

notes.png

מברשת מוזיקה שנוצרה באמצעות מברשות בהתאמה אישית של Ink API

  • מודולים מקוריים של Jetpack פיתוח נייטיב שמאפשרים יכולת פעולה הדדית מייעלים את השילוב של פונקציות דיו ישירות בממשקי המשתמש של פיתוח נייטיב, וכך יוצרים חוויית פיתוח יעילה יותר.

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

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

ממשק Ink API כבר נמצא בשימוש בהרבה אפליקציות של Google, כולל לסימון ב-Docs, לחיפוש באמצעות הקפת עיגול, ובאפליקציות של שותפים כמו Orion Notes ו-PDF Scanner.

“Ink API היה הבחירה הראשונה שלנו לחיפוש באמצעות הקפת עיגול (CtS). השילוב של Ink API היה קל מאוד בזכות התיעוד המקיף, והצלחנו להגיע לאב-טיפוס עובד ראשון תוך שבוע בלבד. התמיכה של Ink באנימציה ובמרקם מותאם אישית של המברשת אפשרה לנו לבצע במהירות איטרציות על עיצוב המשיכות". - ג'ורדן קומודה (Jordan Komoda), מהנדס תוכנה – Google

הגדרת אפליקציית פתקים כברירת מחדל עם תפקיד של פתקים

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

הטמעה ב-Cahier

הטמעה של התפקיד notes (הערות) כוללת כמה שלבים חשובים, שכולם מודגמים בדוגמה:

  1. הצהרה בקובץ המניפסט: קודם כל, האפליקציה צריכה להצהיר על היכולת שלה לטפל בכוונות ליצירת הערות. בקובץ AndroidManifest.xml, ‏ Cahier כולל <intent-filter> לפעולה android.intent.action.CREATE_NOTE. האות הזה מציין למערכת שהאפליקציה היא מועמדת פוטנציאלית לתפקיד של אפליקציית פתקים.
  2. בדיקת סטטוס התפקיד: הכיתה SettingsViewModel משתמשת ב-RoleManager של Android כדי לקבוע את הסטטוס הנוכחי. הפונקציה SettingsViewModel בודקת אם התפקיד של פתק זמין במכשיר (isRoleAvailable) ואם Cahier מחזיק כרגע בתפקיד הזה (isRoleHeld). המצב הזה נחשף לממשק המשתמש באמצעות Kotlin flows.
  3. בקשת התפקיד: בקובץ Settings.kt, מוצג Button למשתמש אם התפקיד זמין אבל לא מוקצה לו. כשלוחצים על הכפתור, הוא קורא לפונקציה requestNotesRole ב-ViewModel. הפונקציה יוצרת Intent לפתיחת מסך ההגדרות של אפליקציית ברירת המחדל, שבו המשתמש יכול לבחור ב-Cahier. התהליך מנוהל באמצעות rememberLauncherForActivityResult API, שמטפל בהפעלת ה-Intent ובקבלת התוצאה.
  4. עדכון ממשק המשתמש: אחרי שהמשתמש חוזר ממסך ההגדרות, הקריאה החוזרת (callback) של ActivityResultLauncher מפעילה פונקציה ב-ViewModel כדי לעדכן את סטטוס התפקיד, וכך לוודא שממשק המשתמש משקף בצורה מדויקת אם האפליקציה מוגדרת עכשיו כאפליקציית ברירת המחדל.

במדריך ליצירת אפליקציה לניהול הערות מוסבר איך לשלב את התפקיד של הערות באפליקציה.

helloworld.png

Cahier מופעל בחלון צף כאפליקציית ברירת המחדל לסיכום פגישות בטאבלט Lenovo

צעד משמעותי קדימה: Lenovo מאפשרת את פונקציית ההערות

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

ההתחייבות הזו של יצרן OEM מוביל מעידה על החשיבות הגוברת של התפקיד של 'הערות' באספקת חוויית משתמש משולבת ופרודוקטיבית באנדרואיד. 

כמה מופעים במקביל, ריבוי חלונות וממשק מחשב

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

  • ריבוי חלונות: היכולת הבסיסית להפעיל אפליקציה לצד אפליקציה אחרת במסך מפוצל או במצב חלון חופשי. זה חיוני למשימות כמו הפניה לדף אינטרנט בזמן שכותבים הערות ב-Cahier.
  • כמה מופעים במקביל: כאן אפשר לראות את היתרון האמיתי של ריבוי משימות. Cahier מאפשר למשתמשים לפתוח כמה חלונות עצמאיים של האפליקציה בו-זמנית. תארו לעצמכם שאתם משווים בין שתי הערות שונות זו לצד זו או מעיינים בהערת טקסט בחלון אחד בזמן שאתם עובדים על ציור בחלון אחר. ‫Cahier מדגים איך לנהל את המקרים הנפרדים האלה, שלכל אחד מהם יש מצב משלו, וכך הופך את האפליקציה לכלי רב עוצמה ורב-פנים.
  • ממשק מחשב: כשמחברים טאבלט או מכשיר מתקפל למסך חיצוני, מצב ממשק מחשב ב-Android הופך אותם לתחנת עבודה. האפליקציה Cahier בנויה עם ממשק משתמש אדפטיבי ותומכת בכמה מופעים במקביל, ולכן היא פועלת בצורה מצוינת בסביבה הזו. המשתמשים יכולים לפתוח כמה חלונות של Cahier, לשנות את הגודל שלהם ולמקם אותם כמו במחשב שולחני רגיל. כך הם יכולים לבצע תהליכי עבודה מורכבים שלא היו אפשריים קודם במכשירים ניידים.
cahier-desktop-windowing.webp

Cahier פועל במצב חלון שולחן עבודה ב-Pixel Tablet

כך הטמענו את התכונות האלה ב-Cahier:

כדי להפעיל ריבוי מופעים, קודם היינו צריכים לסמן למערכת שהאפליקציה תומכת בהפעלה של כמה מופעים שלה על ידי הוספת המאפיין PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI להצהרה של MainActivity ב- AndroidManifest:

<activity

    android:name="com.example.cahier.MainActivity"

    android:exported="true"

    android:label="@string/app_name"

    android:theme="@style/Theme.MyApplication"

    android:showWhenLocked="true"

    android:turnScreenOn="true"

    android:resizeableActivity="true"

    android:launchMode="singleInstancePerTask">


    <property

        android:name="android.window.PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI"

        android:value="true"/>

    ...

</activity>

לאחר מכן, הטמענו את הלוגיקה להפעלת מופע חדש של האפליקציה. בקובץ CahierHomeScreen.kt, כשמשתמש בוחר לפתוח הערה בחלון חדש, אנחנו יוצרים Intent חדש עם דגלים ספציפיים שמנחים את המערכת איך לטפל בהפעלת הפעילות החדשה. השילוב של FLAG_ACTIVITY_NEW_TASKFLAG_ACTIVITY_MULTIPLE_TASK ו-FLAG_ACTIVITY_LAUNCH_ADJACENT מבטיח שההערה תיפתח בחלון חדש ונפרד לצד החלון הקיים.

fun openNewWindow(activity: Activity?, note: Note) {

    val intent = Intent(activity, MainActivity::class.java)

    intent.putExtra(AppArgs.NOTE_TYPE_KEY, note.type)

    intent.putExtra(AppArgs.NOTE_ID_KEY, note.id)

    intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_MULTIPLE_TASK or

        Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT


    activity?.startActivity(intent)

}

כדי לתמוך במצב מרובה חלונות, היינו צריכים לסמן למערכת שהאפליקציה תומכת בשינוי גודל על ידי הגדרת הרכיב <activity> או <application> בקובץ ה-Manifest.

<activity

    android:name="com.example.cahier.MainActivity"

    android:resizeableActivity="true"

    ...>

</activity>

ממשק המשתמש עצמו בנוי באמצעות ספריית Material 3 דינמית, ולכן הוא יכול להסתגל בצורה חלקה לתרחישים של ריבוי חלונות, כמו מצב מסך מפוצל ב-Android. 

כדי לשפר את חוויית המשתמש, הוספנו תמיכה בגרירה ושחרור. בהמשך מוסבר איך הטמענו את התכונה הזו ב-Cahier.

גרירה ושחרור

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

  • ייבוא קל: משתמשים יכולים לגרור תמונות מאפליקציות אחרות – כמו דפדפן אינטרנט, גלריית תמונות או מנהל קבצים – ולהפיל אותן ישירות על בד הציור של ההערה. לשם כך, Cahier משתמש במאפיין dragAndDropTarget כדי להגדיר אזור לשחרור, לבדוק אם התוכן תואם (כמו image/*) ולעבד את ה-URI הנכנס.
  • שיתוף פשוט: קל לשתף תוכן מתוך Cahier בדיוק כמו תוכן מאפליקציות אחרות. משתמשים יכולים ללחוץ לחיצה ארוכה על תמונה בתוך פתק טקסט, או ללחוץ לחיצה ארוכה על כל האזור של פתק שרטוט או של תמונה מורכבת, ולגרור אותו לאפליקציה אחרת.

מידע מעמיק: גרירה מלוח הציור

הטמעה של תנועת הגרירה בלוח הציור היא אתגר ייחודי. ב- DrawingSurface, רכיבי ה-Composable שמטפלים בקלט של ציור בזמן אמת (ה-API של Ink‏ InProgressStrokes) ורכיב ה- Box שמזהה את תנועת הלחיצה הארוכה כדי להתחיל גרירה הם רכיבי Composable מקבילים.

כברירת מחדל, מערכת הקלט של מצביע Jetpack פיתוח נייטיב מתוכננת כך שרק רכיב קומפוזבילי אחד מאותה רמה – הראשון בסדר ההצהרה שחופף למיקום המגע – מקבל את האירוע. במקרה של Cahier, אנחנו רוצים שהלוגיקה של הטיפול בקלט של גרירה ושחרור תפעל ותשתמש בקלט לפני שרכיב ה-Composable‏ InProgressStrokes ישתמש בכל הקלט שלא נעשה בו שימוש כדי לצייר, ואז ישתמש בקלט הזה. אם לא נסדר את הדברים בסדר הנכון, התיבה לא תזהה את תנועת הלחיצה הארוכה כדי להתחיל בגרירה, או InProgressStrokes לא תקבל את הקלט כדי לצייר.

כדי לפתור את הבעיה הזו, יצרנו משנה pointerInputWithSiblingFallthrough מותאם אישית, והצבנו את Box באמצעות המשנה הזה לפני InProgressStrokes בקוד הניתן להרכבה. הכלי הזה הוא מעטפת דקה סביב המערכת הרגילה pointerInput, אבל עם שינוי קריטי אחד: הוא מבטל את הפונקציה sharePointerInputWithSiblings() כדי להחזיר true. הקוד הזה אומר ל-Compose framework לאפשר לאירועי הצבעה לעבור דרך רכיבי composable מקבילים, גם אחרי שהם נצרכו.

internal fun Modifier.pointerInputWithSiblingFallthrough(

    pointerInputEventHandler: PointerInputEventHandler

) = this then PointerInputSiblingFallthroughElement(pointerInputEventHandler)


private class PointerInputSiblingFallthroughModifierNode(

    pointerInputEventHandler: PointerInputEventHandler

) : PointerInputModifierNode, DelegatingNode() {


    var pointerInputEventHandler: PointerInputEventHandler

        get() = delegateNode.pointerInputEventHandler

        set(value) {

            delegateNode.pointerInputEventHandler = value

        }


    val delegateNode = delegate(

        SuspendingPointerInputModifierNode(pointerInputEventHandler)

    )


    override fun onPointerEvent(

        pointerEvent: PointerEvent,

        pass: PointerEventPass,

        bounds: IntSize

    ) {

        delegateNode.onPointerEvent(pointerEvent, pass, bounds)

    }


    override fun onCancelPointerInput() {

        delegateNode.onCancelPointerInput()

    }


    override fun sharePointerInputWithSiblings() = true

}


private data class PointerInputSiblingFallthroughElement(

    val pointerInputEventHandler: PointerInputEventHandler

) : ModifierNodeElement<PointerInputSiblingFallthroughModifierNode>() {


    override fun create() = PointerInputSiblingFallthroughModifierNode(pointerInputEventHandler)


    override fun update(node: PointerInputSiblingFallthroughModifierNode) {

        node.pointerInputEventHandler = pointerInputEventHandler

    }


    override fun InspectorInfo.inspectableProperties() {

        name = "pointerInputWithSiblingFallthrough"

        properties["pointerInputEventHandler"] = pointerInputEventHandler

    }

}

כך משתמשים בו ב-DrawingSurface:

Box(

    modifier = Modifier

        .fillMaxSize()

        // Our custom modifier enables this gesture to coexist with the drawing input.

        .pointerInputWithSiblingFallthrough {

            detectDragGesturesAfterLongPress(

                onDragStart = { onStartDrag() },

                onDrag = { _, _ -> /* consume drag events */ },

                onDragEnd = { /* No action needed */ }

            )

        }

) 

// The Ink API's composable for live drawing sits here as a sibling.

InProgressStrokes(...)

כשההגדרה הזו מופעלת, המערכת מזהה בו-זמנית גם את קווי הציור וגם את תנועת הגרירה בלחיצה ארוכה. אחרי שמתחילים את הגרירה, אנחנו יוצרים URI של content:// שניתן לשיתוף באמצעות FileProvider ומעבירים את ה-URI למסגרת הגרירה וההשלכה של המערכת באמצעות view.startDragAndDrop(). הפתרון הזה מבטיח חוויית משתמש חזקה ואינטואיטיבית, ומראה איך אפשר להתגבר על קונפליקטים מורכבים של מחוות בממשקי משתמש שכבותיים.

מבנה עם אדריכלות מודרנית

בנוסף ל-APIs ספציפיים, Cahier מדגים דפוסי ארכיטקטורה חיוניים לבניית אפליקציות איכותיות וניתנות להתאמה.

שכבת ההצגה: Jetpack פיתוח נייטיב והתאמה

שכבת ההצגה מבוססת כולה על Jetpack פיתוח נייטיב. כמו שצוין, Cahier משתמש בספרייה material3-adaptive כדי להתאים את ממשק המשתמש. ניהול המצב מתבצע לפי דפוס קפדני של זרימת נתונים חד-כיוונית (UDF), עם מופעים של ViewModel שמשמשים כמאגרי נתונים שמכילים מידע על ההערות ומצב ממשק המשתמש.

שכבת הנתונים: מאגרי מידע ו-Room

במקרה של שכבת הנתונים, Cahier משתמש בממשק NoteRepository כדי לבצע הפשטה של כל פעולות הנתונים. הבחירה הזו מאפשרת לאפליקציה לעבור בצורה חלקה בין מקור נתונים מקומי (Room) לבין קצה עורפי מרוחק פוטנציאלי בעתיד. זרימת הנתונים עבור פעולה כמו עריכת הערה היא פשוטה:

  1. ממשק המשתמש של Jetpack פיתוח נייטיב מפעיל שיטה ב-ViewModel.
  2. ה-ViewModel מאחזר את ההערה מ-NoteRepository, מטפל בלוגיקה ומעביר את ההערה המעודכנת בחזרה למאגר.
  3. NoteRepository שומר את העדכון במסד נתונים של Room.

תמיכה מקיפה בקלט

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

  • סטיילוס: שילוב עם Ink API, דחיית מגע כף היד, הרשמה לתפקיד 'הערות', קלט סטיילוס בשדות טקסט ומצב אימרסיבי.
  • מקלדת: תמיכה ברוב מקשי הקיצור והשילובים הנפוצים (כמו Ctrl+click, ‏ Meta+click) וסימון ברור של המיקום במקלדת.
  • עכבר ומשטח מגע: תמיכה בלחיצה ימנית ובמצבי ריחוף.

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

מתחילים עוד היום

אנחנו מקווים ש-Cahier ישמש כפלטפורמה להשקת האפליקציה הגדולה הבאה שלכם. יצרנו אותו כמשאב מקיף בקוד פתוח שמדגים איך לשלב ממשק משתמש דינמי, ממשקי API עוצמתיים כמו Ink ותפקיד ההערות, וארכיטקטורה מודרנית ודינמית.

מוכנים להתחיל?

  • עיון בקוד: אפשר לעבור אל מאגר GitHub שלנו כדי לעיין ב-codebase של Cahier ולראות את עקרונות העיצוב בפעולה.
  • ליצור משלכם: אתם יכולים להשתמש ב-Cahier כבסיס לאפליקציה משלכם לסיכום פגישות, לסימון מסמכים או ליצירת תוכן.
  • הוספת תוכן: נשמח לקבל ממך תוכן! רוצה לעזור לנו לשפר את Cahier לקהילת מפתחי Android?

מומלץ לעיין במדריכים הרשמיים למפתחים ולהתחיל לפתח עוד היום את האפליקציה הבאה שלכם לשיפור הפרודוקטיביות והיצירתיות. אנחנו כבר ממש סקרנים לראות מה תיצרו!

נכתב על ידי:

להמשך הקריאה