چگونه‌ها

معرفی Cahier: یک نمونه جدید اندروید گیت‌هاب برای بهره‌وری و خلاقیت در صفحه نمایش بزرگ

مطالعه ۱۱ دقیقه‌ای
Chris Assigbe
مهندس روابط توسعه‌دهنده

رابط برنامه‌نویسی کاربردی Ink اکنون در مرحله بتا است و آماده ادغام در برنامه شما می‌باشد. این نقطه عطف با بازخورد ارزشمند توسعه‌دهندگان امکان‌پذیر شده است و منجر به بهبود مستمر در عملکرد، پایداری و کیفیت بصری API شده است.

برنامه‌های گوگل مانند Google Docs ، Pixel Studio ، Google Photos ، Chrome PDF ، Youtube Effect Maker و ویژگی‌های منحصر به فرد در اندروید مانند Circle to Search، همگی از جدیدترین APIها استفاده می‌کنند.

برای بزرگداشت این نقطه عطف، مفتخریم که از عرضه Cahier ، یک نمونه برنامه یادداشت‌برداری جامع که برای دستگاه‌های اندرویدی در همه اندازه‌ها، به‌ویژه تبلت‌ها و تلفن‌های تاشو، بهینه شده است، خبر دهیم.

کایه چیست؟

Cahier (به معنی دفترچه یادداشت در زبان فرانسوی) یک برنامه نمونه است که برای نشان دادن چگونگی ساخت برنامه‌ای طراحی شده است که به کاربران امکان می‌دهد افکار خود را با ترکیب متن، نقاشی و تصاویر ثبت و سازماندهی کنند.

این نمونه می‌تواند به عنوان مرجعی برای افزایش بهره‌وری و خلاقیت کاربر در صفحه نمایش‌های بزرگ عمل کند. این نمونه، بهترین شیوه‌ها را برای ساخت چنین تجربیاتی، تسریع درک توسعه‌دهندگان و پذیرش APIها و تکنیک‌های قدرتمند مرتبط، به نمایش می‌گذارد. این پست شما را با ویژگی‌های اصلی Cahier، APIهای کلیدی و تصمیمات معماری که این نمونه را به مرجعی عالی برای برنامه‌های شما تبدیل می‌کند، آشنا می‌کند.

ویژگی‌های کلیدی نشان داده شده در نمونه عبارتند از:

  • ایجاد یادداشت‌های چندمنظوره: نحوه پیاده‌سازی یک سیستم ایجاد محتوای انعطاف‌پذیر را نشان می‌دهد که از قالب‌های مختلف در یک یادداشت واحد، از جمله متن، نقشه‌های آزاد و پیوست‌های تصویر، پشتیبانی می‌کند.
  • ابزارهای خلاقانه‌ی جوهرسازی : با استفاده از Ink API، تجربه‌ی طراحی با کارایی بالا و تأخیر کم را پیاده‌سازی می‌کند. این نمونه، مثالی عملی از ادغام قلم‌موهای مختلف، انتخابگر رنگ، قابلیت لغو/بازگرداندن کار و ابزار پاک‌کن را ارائه می‌دهد.
  • یکپارچه‌سازی روان محتوا با کشیدن و رها کردن : نحوه مدیریت محتوای ورودی و خروجی را با استفاده از کشیدن و رها کردن نشان می‌دهد. این شامل پذیرش تصاویر رها شده از برنامه‌های دیگر و فعال کردن امکان بیرون کشیدن محتوا از برنامه شما برای اشتراک‌گذاری یکپارچه می‌شود.
  • سازماندهی یادداشت‌ها : یادداشت‌ها را برای دسترسی سریع به عنوان موارد دلخواه علامت‌گذاری کنید. برای مرتب ماندن، نمای آنها را فیلتر کنید.
  • معماری آفلاین: با معماری آفلاین با استفاده از Room ساخته شده است و تضمین می‌کند که تمام داده‌ها به صورت محلی ذخیره می‌شوند و برنامه بدون اتصال به اینترنت کاملاً کاربردی باقی می‌ماند.
  • پشتیبانی قدرتمند از چند پنجره و چند نمونه : نحوه پشتیبانی از چند نمونه را نشان می‌دهد و به برنامه شما اجازه می‌دهد در چندین پنجره اجرا شود تا کاربران بتوانند روی یادداشت‌های مختلف در کنار هم کار کنند و بهره‌وری و خلاقیت را در صفحه نمایش‌های بزرگ افزایش دهند.
  • رابط کاربری تطبیق‌پذیر برای همه صفحه نمایش‌ها : رابط کاربری با استفاده از ListDetailPaneScaffold و NavigationSuiteScaffold به طور یکپارچه با اندازه‌ها و جهت‌های مختلف صفحه نمایش سازگار می‌شود تا یک تجربه کاربری بهینه در تلفن‌ها، تبلت‌ها و دستگاه‌های تاشو ارائه دهد.
  • یکپارچه‌سازی عمیق سیستم : راهنمایی در مورد چگونگی تبدیل برنامه خود به برنامه یادداشت‌برداری پیش‌فرض در اندروید ۱۴ و بالاتر با پاسخ به اهداف یادداشت‌های سراسری سیستم، که امکان ضبط سریع محتوا از نقاط ورودی مختلف سیستم را فراهم می‌کند، ارائه می‌دهد.

ساخته شده برای بهره‌وری و خلاقیت در صفحه نمایش‌های بزرگ

برای عرضه اولیه، ما تمرکز اطلاعیه را بر روی چند ویژگی اصلی قرار داده‌ایم که Cahie r را به یک منبع یادگیری کلیدی برای موارد استفاده از بهره‌وری و خلاقیت تبدیل می‌کند.

پایه و اساس سازگاری

Cahier از پایه طوری ساخته شده که قابلیت تطبیق‌پذیری داشته باشد. این نمونه از کتابخانه‌های material3-adaptive، به ویژه ListDetailPaneScaffold و NavigationSuiteScaffold، برای تطبیق یکپارچه طرح‌بندی برنامه با اندازه‌ها و جهت‌های مختلف صفحه نمایش استفاده می‌کند. این یک عنصر حیاتی برای یک برنامه اندروید مدرن است و Cahier نمونه‌ای واضح از نحوه پیاده‌سازی مؤثر آن ارائه می‌دهد.

رابط کاربری تطبیقی ​​Cahier که با کتابخانه تطبیقی ​​Material 3 ساخته شده است..gif

رابط کاربری تطبیقی ​​Cahier که با کتابخانه تطبیقی ​​Material 3 ساخته شده است

نمایش APIها و یکپارچه‌سازی‌های کلیدی

این نمونه بر نمایش APIهای قدرتمند بهره‌وری متمرکز است که می‌توانید در برنامه‌های خود از آنها استفاده کنید، از جمله:

نگاهی دقیق‌تر به APIهای کلیدی

بیایید عمیق‌تر به دو مورد از APIهای اساسی که Cahier برای ارائه یک تجربه یادداشت‌برداری درجه یک در خود ادغام کرده است، بپردازیم.

ایجاد تجربه‌های طبیعی در زمینه‌ی جوهرسازی با Ink API

ورودی قلم، دستگاه‌های صفحه نمایش بزرگ را به نوت‌بوک‌ها و دفترچه‌های طراحی دیجیتال تبدیل می‌کند. برای کمک به شما در ساخت تجربیات روان و طبیعی در زمینه‌ی طراحی با قلم، ما Ink API را به سنگ بنای نمونه تبدیل کرده‌ایم. Ink API ایجاد، رندر و دستکاری خطوط قلم زیبا را با بهترین کیفیت و کمترین تأخیر در کلاس خود آسان می‌کند.

Ink API یک معماری ماژولار ارائه می‌دهد، بنابراین می‌توانید آن را با نیازهای خاص برنامه خود تطبیق دهید. ماژول‌های API شامل موارد زیر هستند:

  • ماژول‌های نوشتن ( نوشتن - نمایش‌ها ): ورودی جوهر را به صورت آنی مدیریت می‌کنند تا خطوط روان با کمترین تأخیری که یک دستگاه می‌تواند ارائه دهد، ایجاد شود.
    • در DrawingSurface ، Cahier از InProgressStrokes که به تازگی معرفی شده است، برای مدیریت ورودی‌های لمسی یا قلم نوری به صورت بلادرنگ استفاده می‌کند. این ماژول مسئول ثبت رویدادهای اشاره‌گر و رندر کردن ضربات جوهر خیس با کمترین تأخیر ممکن است.
  • ماژول Strokes : ورودی جوهر و نمایش بصری آن را نشان می‌دهد. وقتی کاربر رسم یک خط را تمام می‌کند، تابع onStrokesFinished یک شیء Stroke نهایی/خشک شده را به برنامه ارائه می‌دهد. این شیء تغییرناپذیر، که نشان دهنده‌ی خط جوهر تکمیل شده است، سپس در DrawingCanvasViewModel مدیریت می‌شود.
  • ماژول رندرینگ: به طور کارآمد خطوط جوهر را نمایش می‌دهد و به آنها اجازه می‌دهد تا با Jetpack Compose یا نماهای اندروید ترکیب شوند.
    • برای نمایش خطوط موجود و خطوط تازه خشک‌شده، Cahier از CanvasStrokeRenderer در DrawingSurface برای طراحی فعال و از DrawingDetailPanePreview برای نمایش پیش‌نمایش استاتیک یادداشت استفاده می‌کند. این ماژول به طور مؤثر اشیاء Stroke را روی یک Canvas ترسیم می‌کند.
  • ماژول‌های قلم‌مو ( Compose - views ): روشی اعلانی برای تعریف سبک بصری خطوط ارائه می‌دهند. به‌روزرسانی‌های اخیر (از زمان انتشار alpha03) شامل یک قلم‌مو با خط چین جدید است که به ویژه برای ویژگی‌هایی مانند انتخاب با لاسو مفید است. DrawingCanvasViewModel حالت قلم‌مو فعلی را نگه می‌دارد. یک جعبه ابزار در DrawingCanvas به کاربران امکان می‌دهد خانواده‌های قلم‌موهای مختلف (مانند StockBrushes.pressurePen() یا StockBrushes.highlighter() ) را انتخاب کرده و رنگ‌ها را تغییر دهند. ViewModel شیء قلم‌مو را به‌روزرسانی می‌کند، که سپس توسط InProgressStrokes قابل ترکیب برای خطوط جدید استفاده می‌شود.
  • ماژول‌های هندسه ( ایجاد - نمایش ): از دستکاری و تجزیه و تحلیل خطوط برای قابلیت‌هایی مانند پاک کردن و انتخاب پشتیبانی می‌کنند.
    • ابزار پاک‌کن در جعبه ابزار و عملکرد آن در DrawingCanvasViewModel به ماژول geometry متکی است. وقتی پاک‌کن فعال است، یک MutableParallelogram در اطراف مسیر حرکت کاربر ایجاد می‌کند. سپس پاک‌کن تقاطع‌های بین شکل و کادرهای محدودکننده‌ی خطوط موجود را بررسی می‌کند تا مشخص کند کدام خطوط را باید پاک کند، که باعث می‌شود پاک‌کن بصری و دقیق به نظر برسد.
  • ماژول ذخیره‌سازی : قابلیت‌های سریال‌سازی و حذف سریال‌سازی کارآمد برای داده‌های ink را فراهم می‌کند که منجر به صرفه‌جویی قابل توجه در اندازه دیسک و شبکه می‌شود. برای ذخیره ترسیمات، Cahier اشیاء Stroke را در پایگاه داده Room خود حفظ می‌کند. در Converters ، نمونه از تابع رمزگذاری ماژول ذخیره‌سازی برای سریال‌سازی StrokeInputBatch (داده‌های خام نقطه‌ای) در یک ByteArray استفاده می‌کند. آرایه بایت، همراه با ویژگی‌های قلم‌مو، به عنوان یک رشته JSON ذخیره می‌شود. تابع رمزگشایی برای بازسازی strokeها هنگام بارگذاری یک یادداشت استفاده می‌شود.
اوریون.png

فراتر از این ماژول‌های اصلی، به‌روزرسانی‌های اخیر قابلیت‌های Ink API را گسترش داده‌اند:

  • APIهای آزمایشی جدید برای اشیاء سفارشی BrushFamily به توسعه‌دهندگان این امکان را می‌دهد تا انواع قلم‌موهای خلاقانه و منحصر به فرد ایجاد کنند و امکاناتی مانند قلم‌موهای Pencil و Laser Pointer را فراهم کنند.

کایه از قلم‌موهای سفارشی، از جمله قلم‌مو موسیقی منحصر به فرد که در زیر نمایش داده شده است، برای نشان دادن امکانات خلاقانه پیشرفته استفاده می‌کند.

لیزر رنگین‌کمانی که با قلم‌موهای سفارشی Ink API ساخته شده است..gif

لیزر رنگین‌کمانی که با قلم‌موهای سفارشی Ink API ساخته شده است

یادداشت‌ها.png

قلم‌مو موسیقی با قلم‌موهای سفارشی Ink API ساخته شده است

  • ماژول‌های بومی Jetpack Compose برای ایجاد قابلیت همکاری، ادغام قابلیت‌های inking را مستقیماً در رابط‌های کاربری Compose شما ساده می‌کنند تا یک تجربه توسعه اصطلاحاً کاربردی‌تر و کارآمدتر ایجاد شود.

Ink API مزایای متعددی ارائه می‌دهد که آن را به انتخابی ایده‌آل برای برنامه‌های بهره‌وری و خلاقیت نسبت به پیاده‌سازی سفارشی تبدیل می‌کند:

  • سهولت استفاده: رابط برنامه‌نویسی کاربردی Ink پیچیدگی‌های گرافیک و هندسه را کنار می‌گذارد و به شما امکان می‌دهد روی ویژگی‌های اصلی Cahier تمرکز کنید.
  • عملکرد: پشتیبانی داخلی از تأخیر کم و رندر بهینه، تجربه‌ی روان و واکنش‌گرای جوهرافشانی را تضمین می‌کند.
  • انعطاف‌پذیری: طراحی ماژولار به شما امکان می‌دهد اجزای مورد نیاز را انتخاب و گزینش کنید، که این امر امکان ادغام یکپارچه‌ی Ink API را در معماری Cahier فراهم می‌کند.

رابط برنامه‌نویسی کاربردی Ink در حال حاضر در بسیاری از برنامه‌های گوگل، از جمله برای نشانه‌گذاری در Docs و Circle to Search و همچنین برنامه‌های همکار مانند Orion Notes و PDF Scanner ، به کار گرفته شده است.

«Ink API اولین انتخاب ما برای Circle-to-Search (CtS) بود. با استفاده از مستندات گسترده آنها، ادغام Ink API بسیار آسان بود و به ما این امکان را داد که تنها در عرض یک هفته به اولین نمونه اولیه کاربردی خود برسیم. پشتیبانی از بافت قلم موی سفارشی و انیمیشن Ink به ما این امکان را داد که به سرعت طراحی stroke را تکرار کنیم.» - جردن کومودا، مهندس نرم‌افزار - گوگل

تبدیل شدن به برنامه یادداشت‌های پیش‌فرض با نقش یادداشت‌ها

یادداشت‌برداری یک قابلیت اصلی است که بهره‌وری کاربر را در دستگاه‌های صفحه نمایش بزرگ افزایش می‌دهد. با ویژگی نقش یادداشت‌ها ، کاربران می‌توانند از صفحه قفل یا در حالی که سایر برنامه‌ها در حال اجرا هستند، به برنامه‌های سازگار شما دسترسی داشته باشند. این ویژگی برنامه‌های یادداشت‌برداری پیش‌فرض در سطح سیستم را شناسایی و تنظیم می‌کند و به آنها اجازه می‌دهد تا برای ضبط محتوا راه‌اندازی شوند.

پیاده‌سازی در Cahier

پیاده‌سازی نقش یادداشت‌ها شامل چند مرحله کلیدی است که همه در نمونه نشان داده شده‌اند:

  1. اعلان مانیفست : ابتدا، برنامه باید قابلیت خود را برای مدیریت intentهای یادداشت‌برداری اعلام کند. در AndroidManifest.xml ، Cahier یک <intent-filter> برای اکشن android.intent.action.CREATE_NOTE قرار می‌دهد. این به سیستم نشان می‌دهد که برنامه یک کاندید بالقوه برای نقش یادداشت‌ها است.
  2. بررسی وضعیت نقش : SettingsViewModel از RoleManager اندروید برای تعیین وضعیت فعلی استفاده می‌کند. SettingsViewModel بررسی می‌کند که آیا نقش notes در دستگاه موجود است ( isRoleAvailable ) و آیا Cahier در حال حاضر آن نقش را دارد ( isRoleHeld ). این وضعیت با استفاده از جریان‌های Kotlin در معرض رابط کاربری قرار می‌گیرد.
  3. درخواست نقش : در فایل Settings.kt ، اگر نقش موجود باشد اما در اختیار کاربر نباشد، یک دکمه (Button) به کاربر نمایش داده می‌شود. وقتی روی دکمه کلیک شود، تابع requestNotesRole را در ViewModel فراخوانی می‌کند. این تابع یک intent برای باز کردن صفحه تنظیمات پیش‌فرض برنامه ایجاد می‌کند که در آن کاربر می‌تواند Cahier را انتخاب کند. این فرآیند با استفاده از API rememberLauncherForActivityResult مدیریت می‌شود که اجرای intent و دریافت نتیجه را مدیریت می‌کند.
  4. به‌روزرسانی رابط کاربری : پس از بازگشت کاربر از صفحه تنظیمات، تابع فراخوانی ActivityResultLauncher تابعی را در ViewModel فعال می‌کند تا وضعیت نقش را به‌روزرسانی کند و اطمینان حاصل شود که رابط کاربری به طور دقیق نشان می‌دهد که آیا برنامه اکنون پیش‌فرض است یا خیر.

یاد بگیرید که چگونه نقش یادداشت‌ها را در برنامه خود در راهنمای ایجاد یک برنامه یادداشت‌برداری ما ادغام کنید.

سلام دنیا.png

Cahier به عنوان برنامه یادداشت‌برداری پیش‌فرض روی تبلت لنوو، در یک پنجره شناور راه‌اندازی شد.

یک گام بزرگ به جلو: لنوو قابلیت یادداشت‌برداری را فعال می‌کند

ما مفتخریم که یک گام بزرگ رو به جلو برای بهره‌وری اندروید روی صفحه نمایش بزرگ را اعلام کنیم: لنوو پشتیبانی از نقش یادداشت‌ها را در تبلت‌های دارای اندروید ۱۵ و بالاتر فعال کرده است! با این به‌روزرسانی، اکنون می‌توانید برنامه‌های یادداشت‌برداری خود را به‌روزرسانی کنید تا به کاربران دارای دستگاه‌های سازگار لنوو اجازه دهید آنها را به عنوان پیش‌فرض تنظیم کنند و دسترسی یکپارچه از صفحه قفل و باز کردن قفل ویژگی‌های ضبط محتوا در سطح سیستم را فراهم کنند.

این تعهد از سوی یک تولیدکننده اصلی تجهیزات (OEM) پیشرو، اهمیت روزافزون نقش نوت‌ها را در ارائه یک تجربه کاربری واقعاً یکپارچه و پربار در اندروید نشان می‌دهد.

چند نمونه‌ای، چند پنجره‌ای و پنجره‌ای کردن دسکتاپ

بهره‌وری در یک صفحه نمایش بزرگ، تماماً به مدیریت اطلاعات و گردش کار به طور کارآمد بستگی دارد. به همین دلیل است که Cahier طوری ساخته شده است که به طور کامل از قابلیت‌های پیشرفته پنجره‌بندی اندروید پشتیبانی کند و یک فضای کاری انعطاف‌پذیر را فراهم کند که با نیازهای کاربر سازگار باشد. این برنامه از موارد زیر پشتیبانی می‌کند:

  • چند پنجره‌ای : قابلیت اساسی اجرا در کنار یک برنامه دیگر در حالت تقسیم صفحه یا حالت آزاد. این قابلیت برای کارهایی مانند مراجعه به یک صفحه وب هنگام یادداشت‌برداری در Cahier ضروری است.
  • چند نمونه‌ای : اینجاست که چندوظیفگی واقعی می‌درخشد. Cahier به کاربران اجازه می‌دهد چندین پنجره مستقل از برنامه را همزمان باز کنند. تصور کنید که دو یادداشت مختلف را در کنار هم مقایسه می‌کنید یا در یک پنجره به یک یادداشت متنی ارجاع می‌دهید در حالی که روی یک نقاشی در پنجره دیگر کار می‌کنید. Cahier نحوه مدیریت این نمونه‌های جداگانه، هر کدام با حالت خاص خود را نشان می‌دهد و برنامه شما را به ابزاری قدرتمند و چندوجهی تبدیل می‌کند.
  • پنجره‌بندی دسکتاپ : وقتی به یک نمایشگر خارجی متصل می‌شود، حالت دسکتاپ اندروید، یک تبلت یا دستگاه تاشو را به یک ایستگاه کاری تبدیل می‌کند. از آنجا که Cahier با یک رابط کاربری تطبیقی ​​ساخته شده و از چند نمونه پشتیبانی می‌کند، این برنامه در این محیط به زیبایی عمل می‌کند. کاربران می‌توانند چندین پنجره Cahier را درست مانند یک دسکتاپ سنتی باز کنند، اندازه آنها را تغییر دهند و در جای خود قرار دهند و گردش‌های کاری پیچیده‌ای را که قبلاً در دستگاه‌های تلفن همراه قابل دسترسی نبودند، امکان‌پذیر کنند.
پنجره‌بندی دفترچه یادداشت رومیزی.webp

اجرای Cahier در حالت پنجره دسکتاپ روی تبلت پیکسل

در اینجا نحوه پیاده‌سازی این ویژگی‌ها در 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_TASK ، FLAG_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 ساخته شده است، آن را قادر می‌سازد تا به طور یکپارچه در سناریوهای چند پنجره‌ای مانند حالت تقسیم صفحه نمایش اندروید سازگار شود.

برای بهبود تجربه کاربری، پشتیبانی از کشیدن و رها کردن (drag and drop) را اضافه کرده‌ایم. در زیر نحوه پیاده‌سازی این قابلیت در Cahier را مشاهده می‌کنید.

بکشید و رها کنید

یک اپلیکیشن واقعاً سازنده یا خلاق، به صورت جداگانه کار نمی‌کند؛ بلکه به طور یکپارچه با بقیه اکوسیستم دستگاه در تعامل است. کشیدن و رها کردن (drag and drop) سنگ بنای این تعامل است، به خصوص در صفحه نمایش‌های بزرگ که کاربران اغلب در چندین پنجره برنامه کار می‌کنند. Cahier با پیاده‌سازی قابلیت کشیدن و رها کردن (drag and drop) برای افزودن و اشتراک‌گذاری محتوا، این امر را به طور کامل پذیرفته است.

  • وارد کردن آسان : کاربران می‌توانند تصاویر را از برنامه‌های دیگر - مانند مرورگر وب، گالری عکس یا مدیر فایل - بکشند و مستقیماً روی بوم یادداشت رها کنند. برای این کار، Cahier از اصلاح‌کننده dragAndDropTarget برای تعریف یک منطقه رها کردن، بررسی محتوای سازگار (مانند image/* ) و پردازش URI ورودی استفاده می‌کند.
  • اشتراک‌گذاری ساده : محتوای داخل Cahier به راحتی محتوای سایر برنامه‌ها قابل اشتراک‌گذاری است. کاربران می‌توانند روی یک تصویر در یک یادداشت متنی، یا روی کل بوم یک یادداشت طراحی و ترکیب تصویر، لمس طولانی داشته باشند و آن را به برنامه دیگری بکشند.

بررسی عمیق فنی: کشیدن از بوم نقاشی

پیاده‌سازی ژست کشیدن روی بوم نقاشی، چالش منحصر به فردی را ارائه می‌دهد. در DrawingSurface ما، کامپوننت‌هایی که ورودی نقاشی زنده ( InProgressStrokes از Ink API) را مدیریت می‌کنند و Box که ژست فشار طولانی برای شروع کشیدن را تشخیص می‌دهد، کامپوننت‌های خواهرخوانده هستند.

به طور پیش‌فرض، سیستم ورودی اشاره‌گر Jetpack Compose به گونه‌ای طراحی شده است که فقط یک composable خواهرخوانده - اولین مورد در ترتیب اعلان که با محل لمس همپوشانی دارد - رویداد را دریافت می‌کند. در مورد Cahier، ما می‌خواهیم منطق مدیریت ورودی کشیدن و رها کردن ما فرصتی برای اجرا و مصرف ورودی‌ها داشته باشد، قبل از اینکه Composable InProgressStrokes از تمام ورودی‌های مصرف نشده برای ترسیم استفاده کند و سپس آن ورودی را مصرف کند. اگر همه چیز را به ترتیب صحیح مرتب نکنیم، Box ما حرکت فشار طولانی را برای شروع کشیدن تشخیص نمی‌دهد، یا InProgressStrokes ورودی را برای ترسیم دریافت نمی‌کند.

برای حل این مشکل، ما یک اصلاح‌کننده‌ی سفارشی pointerInputWithSiblingFallthrough ایجاد کردیم و Box خود را با استفاده از آن اصلاح‌کننده قبل از InProgressStrokes در کد composable قرار دادیم. این ابزار یک پوشش نازک در اطراف سیستم استاندارد pointerInput است، اما با یک تغییر اساسی: تابع sharePointerInputWithSiblings() را برای برگرداندن true لغو می‌کند. این به چارچوب Compose می‌گوید که به رویدادهای اشاره‌گر اجازه دهد تا حتی پس از مصرف شدن، به 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(...)

با این کار، سیستم به طور صحیح هم خطوط رسم و هم حرکت کشیدن با فشار طولانی را به طور همزمان تشخیص می‌دهد. پس از شروع کشیدن، ما یک content:// URI قابل اشتراک‌گذاری با FileProvider ایجاد می‌کنیم و URI را با استفاده از view.startDragAndDrop() به چارچوب کشیدن و رها کردن سیستم ارسال می‌کنیم. این راه‌حل، یک تجربه کاربری قوی و شهودی را تضمین می‌کند و نحوه غلبه بر تداخلات پیچیده حرکت در رابط‌های کاربری لایه‌ای را نشان می‌دهد.

ساخته شده با معماری مدرن

فراتر از API های خاص، Cahier الگوهای معماری حیاتی برای ساخت برنامه‌های کاربردی با کیفیت بالا و تطبیقی ​​را نشان می‌دهد.

لایه ارائه: Jetpack Compose و سازگاری

لایه ارائه (presentation layer) کاملاً با Jetpack Compose ساخته شده است. همانطور که گفته شد، Cahier از کتابخانه material3-adaptive برای سازگاری رابط کاربری استفاده می‌کند. مدیریت وضعیت (state management) از یک الگوی جریان داده یک‌طرفه (Unidirectional Data Flow) (UDF) پیروی می‌کند، و نمونه‌های ViewModel به عنوان محفظه‌های داده‌ای که اطلاعات یادداشت‌ها و وضعیت رابط کاربری را در خود نگه می‌دارند، استفاده می‌شوند.

لایه داده: مخازن و اتاق

برای لایه داده، Cahier از یک رابط NoteRepository برای انتزاع تمام عملیات داده استفاده می‌کند. این انتخاب طراحی به برنامه اجازه می‌دهد تا به طور واضح بین یک منبع داده محلی (Room) و یک backend از راه دور بالقوه در آینده جابجا شود. جریان داده برای عملی مانند ویرایش یک یادداشت ساده است:

  1. رابط کاربری Jetpack Compose یک متد را در ViewModel فعال می‌کند.
  2. ViewModel یادداشت را از NoteRepository دریافت می‌کند، منطق را مدیریت می‌کند و یادداشت به‌روزرسانی‌شده را به مخزن برمی‌گرداند.
  3. NoteRepository به‌روزرسانی را در پایگاه داده Room ذخیره می‌کند.

پشتیبانی جامع از ورودی‌ها

برای اینکه یک برنامه واقعاً قدرتمند در زمینه بهره‌وری باشد، باید انواع روش‌های ورودی را بدون نقص مدیریت کند. Cahier طوری ساخته شده است که با دستورالعمل‌های ورودی صفحه نمایش بزرگ سازگار باشد و از موارد زیر پشتیبانی می‌کند:

  • قلم: ادغام با رابط برنامه‌نویسی کاربردی Ink، عدم شناسایی اثر کف دست، ثبت نقش یادداشت، ورودی قلم در فیلدهای متنی و حالت فراگیر.
  • صفحه‌کلید: پشتیبانی از رایج‌ترین میانبرها و ترکیب‌های صفحه‌کلید (مانند ctrl+click، meta+click) و نمایش واضح فوکوس صفحه‌کلید.
  • ماوس و ترک‌پد: پشتیبانی از حالت‌های کلیک راست و شناور

پشتیبانی از تعاملات پیشرفته‌ی صفحه‌کلید، ماوس و ترک‌پد، تمرکز اصلی برای بهبودهای بیشتر است.

همین امروز شروع کنید

ما امیدواریم که Cahier به عنوان یک سکوی پرتاب برای برنامه عالی بعدی شما عمل کند. ما آن را به عنوان یک منبع جامع و متن‌باز ساخته‌ایم که نشان می‌دهد چگونه می‌توان یک رابط کاربری تطبیقی، APIهای قدرتمند مانند Ink و نقش یادداشت‌ها و یک معماری تطبیقی ​​مدرن را ترکیب کرد.

آماده شیرجه زدن هستید؟

  • کد را بررسی کنید : برای بررسی کدبیس Cahier و مشاهده اصول طراحی در عمل، به مخزن گیت‌هاب ما مراجعه کنید.
  • خودتان بسازید : از Cahier به عنوان پایه‌ای برای یادداشت‌برداری، نشانه‌گذاری اسناد یا برنامه‌های خلاقانه خود استفاده کنید.
  • مشارکت : ما از مشارکت‌های شما استقبال می‌کنیم! به ما کمک کنید تا Cahier را به منبعی حتی بهتر برای جامعه توسعه‌دهندگان اندروید تبدیل کنیم.

راهنماهای رسمی توسعه‌دهندگان را بررسی کنید و همین امروز ساخت اپلیکیشن بهره‌وری و خلاقیت نسل بعدی خود را شروع کنید. بی‌صبرانه منتظریم ببینیم چه چیزی خلق می‌کنید!

    نوشته شده توسط:

    ادامه مطلب