مهندس نرمافزار
در این جلسه، بهطور فنی و عمیق به بررسی تکامل از «کاشیهای» تمامصفحه به «ابزارههای Wear» پویا با ارتفاع جزئی میپردازیم.
مزایای فنی Jetpack Glance API یکپارچه و موتور جدید Remote Compose را بررسی خواهیم کرد و توضیح خواهیم داد که چگونه این دو بهطور یکپارچه با Modern Android Development همسو میشوند.
درنهایت، جدیدترین راهنماییهای UX را همرسانی خواهیم کرد و استراتژیهای انتقال کاربردی را مرور خواهیم کرد تا به شما کمک کنیم نسل بعدی واسط کاربر قابلمشاهده در یک نگاه را بسازید.
آوانویسی
سلام به همه.
نام من فرانک است و من رهبری تجربههای اجمالی ما را برای Wear OS برعهده دارم.
ساعتها همراهان ضروری و همیشگی کاربران شما هستند و امروز شما را راهنمایی میکنیم که چگونه از تجربه جدید «ابزارههای Wear» بهره ببرید.
ما به دو مورد نگاه خواهیم کرد، ما به ارائه مهمترین ویژگیهای شما مستقیماً به مچ دست کاربران شما نگاه خواهیم کرد، و این کار را بااستفاده از جدیدترین میاناهای برنامهسازی کاربردی انجام خواهیم داد، میاناهای برنامهسازی کاربردی که برای ساختن Wear OS طراحی شدهاند، برای توسعهدهندگان Android، مانند خودتان، آشنا و شهودی بهنظر میرسند.
امروز همکار باهوش و هممیزی من، یوری، روی صحنه به من ملحق میشود تا دقیقاً ببینیم چگونه این کار را انجام میدهیم.
سلام، من یوری شیمکه هستم.
من مهندس تیم Wear OS هستم و تمرکز اصلی من کار روی Remote Compose API است.
امروز مقدمه کوتاهی درباره Remote Compose ارائه میدهم و سپس درباره فرایند انتقال از «کاشیها» به «ابزارههای Wear» صحبت میکنم.
با این مقدمه، شما را به فرانک میسپارم.
عالی.
متشکرم، یوری.
ما با تبدیل «کاشیهای» تمامصفحه به «ابزارههای Wear»، مچ دست را رسماً وارد بومسازگان ابزارههای یکپارچه Android میکنیم.
و چون این تجربهها اکنون بااستفاده از Jetpack Glance ساخته شدهاند، میتوانید ببینید که این همان زیرساخت اساسی است که برای ابزارههای تلفن همراه استفاده میشود.
خواهید دید که در آینده ساختن برای Wear برایتان حتی آشناتر خواهد شد.
برای تقویت این تجربهها، درحال تکامل پشته میانای کاربر هستیم-- پشته میانای کاربر زیربنایی.
«ابزارههای Wear» با Remote Compose، چارچوب جدید Android برای واسط کاربر ازراهدور، کار میکنند.
این یعنی درنهایت میتوانید از میانای برنامهسازی کاربردی اعلانی که کاملاً با Jetpack Compose همراستا است برای ساختن تجربههای خارج از برنامه، مثل ابزارهها، استفاده کنید.
Remote Compose گرافیک مدرن و چیدمانهای واکنشگرا را به ابزارهایی میآورد که عملکرد و کارایی باتری را تضمین میکنند.
و با جدا کردن میانای کاربری از فرایند برنامه، ابزارکهای شما بهطور ایمن سریالی میشوند و بهراحتی در طیف گستردهای از دستگاههای Android ارائه میشوند، متأسفیم.
این یعنی میتوانید این تجربههای غنی را با کمترین تلاش به تقریباً همه سطوح ازراهدور پشتیبانیشده بیاورید.
برای اینکه انتقال از «کاشیها» به ابزارهها تا حد امکان روان باشد، دو اندازه محفظه استاندارد معرفی میکنیم: کوچک و بزرگ.
این ابزارهها بهگونهای طراحی شدهاند که با قالبهای ابزاره مبتنی بر جدول دو در یک و دو در دو که قبلاً با ساختن ابزاره در تلفن همراه به آنها عادت کردهاید، کاملاً همسو باشند.
و از Wear 7 در برخیاز سازندگان سختافزار، «ابزارههای Wear» شما اکنون در سینی پیمایش عمودی در کنار ابزارههای برنامههای دیگر قرار خواهند گرفت.
برای مثال، این نحوه نمایش «ابزارههای Wear» در Samsung Galaxy Watch است.
معماری پلاتفرم بهگونهای ساخته شده است که از سینیهای پیمایش عمودی پشتیبانی کند تا سازندگان سختافزار بتوانند در آینده از این الگو استفاده کنند.
و لازم نیست نگران ازدست دادن کاربران جدید یا کاربران فعلی باشید.
میاناهای برنامهسازی کاربردی Jetpack Glance Wear برای پشتیبانی از سازگاری با نسخههای قدیمی تا Wear 4 طراحی شدهاند.
در دستگاههای قدیمیتری که از سینی افقی ابزارهها یا «کاشیها» پشتیبانی میکنند، سیستم این کار را برای شما انجام میدهد.
کافی است در کدتان اعلام کنید که میخواهید از حالت تمامصفحه پشتیبانی کنید، و سیستم ابزاره بزرگ شما را میگیرد و آن را بهعنوان «کاشیهای» سنتی تمامصفحه در این دستگاهها نمایش میدهد.
اکنون، یوری ما را در کد راهنمایی میکند تا دقیقاً به شما نشان دهد چگونه «کاشیهای» موجود خود را به «ابزارههای Wear» منتقل کنید.
متشکرم، فرانک.
اگر میخواهید «ابزاره Wear» جدیدی را از ابتدا بسازید، کار سادهای است.
کافی است GlanceWearWidgetService را تعریف کنید و واسط کاربر خود را بااستفاده از Remote Compose بسازید.
اما اگر برنامهتان ازقبل «کاشی» درحال تولید دارد، باید هم سرویسها، هم میانای کاربر، و هم دادههایتان را منتقل کنید.
برای اینکه این انتقال تا حد امکان روان باشد، مسیرهایی را برای اطمینان از تجربه یکپارچه برای کاربران فعلی ارائه کردهایم.
برای خدمات، میتوانید بین دو استراتژی انتخاب کنید: خدمات دوگانه یا خدمات تکی.
با سرویس دوگانه، که توصیه میکنیم، TileService موجود را برای دستگاههای Wear OS قدیمیتر حفظ میکنید و GlanceWearWidgetService جدیدی برای Wear OS 7 و نسخههای جدیدتر اضافه میکنید.
درمقابل، با سرویس تکی، یک GlanceWearWidgetService تکی جدید ایجاد میکنید که هر دو پروتکل را مدیریت میکند و در حالت سازگاری اجرا میشود تا ابزاره شما را به «کاشی» در دستگاههای قدیمیتر ترجمه کند.
در هر دو صورت، همچنان به کاربرانتان دسترسی خواهید داشت.
این کار فقط بر کدی که در آینده نگهداری میکنید تأثیر میگذارد.
و ما بهتازگی اسناد جامعی را در سایت توسعهدهنده Android منتشر کردهایم که دقیقاً نحوه و زمان استفاده از هر دو این الگوها را شرح میدهد.
آن را بررسی کنید تا بیشتر بدانید کدام استراتژی برای برنامه شما بهترین است.
اکنون بیایید درباره لایه میانای کاربر صحبت کنیم.
هنگام انتقال، مدل ذهنی شما تغییر میکند.
قبلاً، کاشیها از ProtoLayout استفاده میکردند، کتابخانهای که منحصراً برای کاشیهای Wear ساخته شده است.
ازسویدیگر، «ابزارههای Wear» براساس Remote Compose ساخته شده است.
Remote Compose دقیقاً از همان پایه میانای کاربری Jetpack Compose استفاده میکند و از همان کامپایلر و زمان اجرای اصلی بهره میبرد.
و بهگونهای طراحی شده است که آشنا بهنظر برسد و با کتابخانههای Compose UI مانند foundation و Material 3 مطابقت نزدیکی داشته باشد.
اما بهجای چارگوش، ستون، یا نوشتار، آنها را با RemoteBox، RemoteColumn، یا RemoteText عوض میکنید.
در این مورد، با نوشتن زیاد «ازراهدور» آشنا خواهید شد.
بهعلاوه، برای سرعت بخشیدن به گردش کار شما، مجموعه کاملی از مؤلفههای «ترکیببندی ازراهدور» آماده استفاده را که بهطور خاص برای ابزارهها طراحی شدهاند اضافه کردهایم.
این یعنی طرحهای Wear Material 3 موجود شما، ازجمله آنچه در Figma دارید، بهراحتی میتوانند با ابزارهها سازگار شوند و این امر را برای مهندسان و طراحان آشنا میکند.
برای اینکه ببینیم این چارچوبها چقدر همسو هستند، بیایید به یک مثال واقعی نگاه کنیم.
میخواهیم مؤلفه برنامه خودمان را روی دکمه کلید Material 3 بسازیم.
در سمت راست، مؤلفه استاندارد Wear Compose را داریم که در داخل برنامهتان مینویسید، و در سمت چپ نسخه Remote Compose را داریم.
// Wear Compose
@Composable
fun HistoryEraserButton(
onClick: () -> Unit,
modifier: Modifier = Modifier,
checked: Boolean = true,
onCheckedChange: (Boolean) -> Unit = {},
)// Wear RemoteCompose
@RemoteComposable
@Composable
fun RemoteHistoryEraserButton(
onClick: Action,
modifier: RemoteModifier = RemoteModifier,
checked: RemoteBoolean = true.rb,
onCheckedChange: Action = Action.Empty,
)به شباهت الگوها توجه کنید.
اما هنگام نوشتن کد Remote Compose، از حاشیهنویسی RemoteComposable استفاده خواهید کرد.
و در جایی که از پارامترهای آشنا مانند اصلاحکننده و بولی استفاده میکنید، آنها دارای انواع معادل Remote Compose مانند RemoteModifier و RemoteBoolean هستند.
و بهجای لامبدا از کنشها استفاده میکنید.
بهجای تعریف اجرای کد برای اجرا در lambda، باید کنشی مثل راهاندازی قصد معوق، فراخوانی سرویس، یا بهروزرسانی مقدار را اعلام کنید.
بیایید به بدنه مؤلفهمان برویم.
متوجه خواهید شد که حتی زمینهسازی هم تراز شده است.
میتوانید آرایش رنگهای Material 3 را دقیقاً همانطور که در Compose استاندارد انجام میدهید روی مؤلفه Remote Compose اعمال کنید، که به ابزاره شما اجازه میدهد دقیقاً با نمانامسازی برنامهتان مطابقت داشته باشد.
// Wear Compose
val colors = MaterialTheme.colorScheme
SplitSwitchButton(
checked = checked,
onCheckedChange = onCheckedChange,
toggleContentDescription = "Arm Eraser",
onContainerClick = onClick,
modifier = modifier.fillMaxWidth(),
colors =
SwitchButtonDefaults.splitSwitchButtonColors(
checkedContainerColor = colors.errorContainer, …
),
label = { Text("History Eraser") },
secondaryLabel = { Text("Don't touch it!") },
)// Wear RemoteCompose
val colors = RemoteMaterialTheme.colorScheme
RemoteSplitSwitchButton(
checked = checked,
onCheckedChange = onCheckedChange,
toggleContentDescription = "Arm Eraser".rs,
onContainerClick = onClick,
modifier = modifier.fillMaxWidth(),
colors =
RemoteSplitSwitchButtonDefaults.splitSwitchButtonColors(
checkedContainerColor = colors.errorContainer, …
),
label = { RemoteText("History Eraser".rs) },
secondaryLabel = { RemoteText("Don't touch it!".rs) },
)و در آخر، بیایید نتیجه را ببینیم. رابط کاربری حاصل دقیقاً همان چیزی است که انتظار دارید، یک دکمه مبدل تمیز، واکنشگرا، و پویانماییشده.
تشخیص تفاوت دشوار است.
برای کمک به شما در طراحی، تکرار، و تأیید چیدمان ابزارههایتان بدون اینکه همیشه روی دستگاه یا شبیهساز اجرا شوند، پشتیبانی پیشنمایش Compose را برای «ابزارههای Wear» اضافه کردهایم.
ازآنجاییکه ابزارهها به محدودیتهای محفظه خاص OEM، مانند اندازه، شکل، حاشیه داخلی، و شعاع گوشه بستگی دارند، ما بر حاشیهنویسی پیشنمایش استاندارد تکیه میکنیم، اما با یک ارائهدهنده پارامتر اضافی برای تزریق این پیکربندیها.
@Preview(name = "Squircle Preview", device = "spec:width=1000dp,height=1000dp,dpi=320")
@Composable
fun WeatherWidgetSquirclePreview(
@PreviewParameter(SquircleAllWidgetPreviewParams::class) params: WearWidgetParams
) = WearWidgetPreview(MockWeatherWidget(65, WeatherCondition.CLOUDY), params)
@Preview(name = "Round Preview", device = "spec:width=1000dp,height=1000dp,dpi=320")
@Composable
fun WeatherWidgetRoundPreview(
@PreviewParameter(RoundAllWidgetPreviewParams::class) params: WearWidgetParams
) = WearWidgetPreview(MockWeatherWidget(65, WeatherCondition.CLOUDY), params)این کتابخانه پیادهسازیهای ارائهدهنده PreviewParameter ازپیش پیکربندیشدهای را ارائه میدهد که با دستگاههای Wear OS در دنیای واقعی مطابقت دارند.
این حاشیهنویسیهای پیشنمایش به شما امکان میدهد بهراحتی چیدمانتان را در شکلهای سختافزاری بسیار متفاوت درستیسنجی کنید.
علاوهبر آزمایش چیدمانها، میتوانید از این پیشنمایشها برای تولید تصاویر ثابتی که برای انتخابگر ابزاره دروندستگاهی لازم است استفاده کنید.
@Preview(name = "Widget Picker Preview", device = "spec:width=1000dp,height=1000dp,dpi=320")
@Composable
fun WeatherWidgetRectangularPreview(
@PreviewParameter(RectangularAllWidgetPreviewParams::class) params: WearWidgetParams
) = WearWidgetPreview(MockWeatherWidget(65, WeatherCondition.CLOUDY), params)این کتابخانه پارامتری برای شکل پیشنمایش مستطیلی ارائه میدهد که محفظههای مستطیلی کامل برشنخورده را شبیهسازی میکند.
و اگر میخواهید ببینید این ویژگی دقیقاً در عمل چگونه کار میکند، برنامه نمونه رسانه Horologist را بازآوری کردهایم تا ابزاره جدیدی را که این میانای برنامهسازی کاربردی را نمایش میدهد دربرگیرد.
نحوه افزودن نسخههای کوچک و بزرگ ابزاره رسانه را نشان میدهیم.
آن را در GitHub بررسی کنید تا مقایسه کنارهم کد ProtoLayout قدیمی و پیادهسازی جدید «ترکیببندی از راه دور» را ببینید.
مطمئنیم که آن را میپسندید.
درنهایت، این یک، میدانید، یک صحبت بدون اشاره به هوش مصنوعی نخواهد بود.
برای سرعت بخشیدن به انتقال، مهارت جدیدی برای انتقال کاشیها به ابزارهها در GitHub منتشر کردهایم.
میتوانید از آن با عامل انتخابیتان استفاده کنید یا میتوانید آن را مستقیماً بااستفاده از Android CLI به Android Studio اضافه کنید.
android skills add wear-widgets
android skills add --allاکنون شما را به فرانسوا میسپارم تا جمعبندی کند.
متشکریم.
متشکرم، یوری.
بنابراین همانطور که میبینید، تبدیل کاشیها به «ابزارکهای Wear» فرایندی بسیار ساده است.
بهطور خلاصه، با انتقال به Jetpack Glance Wear و Remote Compose، شما فقط میانای کاربر خود را بهروز نمیکنید، بلکه به یک زیستبوم ابزارههای Android یکپارچهتر میپیوندید.
اکنون میتوانید بااستفاده از چارچوب مدرن و توصیفی که کاملاً با Jetpack Compose همسو است، ابزارهایی زیبا و سازگار با نسخههای قدیمی بسازید.
میتوانید از همین امروز انتقال کاشیهایتان را شروع کنید. برای کسب اطلاعات بیشتر و دریافت جزئیات کامل، به راهنمای «شروع به کار» در سایت توسعهدهندگان Android مراجعه کنید.
مشتاقانه منتظریم تا همه تجربههای گویا و قابلمشاهده در یک نگاه را که برای مچ دست میسازید ببینیم.
از اینکه امروز صبح به ما پیوستید بسیار سپاسگزاریم و امیدواریم از ادامه کنفرانس لذت ببرید.
متشکریم.
// Wear Compose
@Composable
fun HistoryEraserButton(
onClick: () -> Unit,
modifier: Modifier = Modifier,
checked: Boolean = true,
onCheckedChange: (Boolean) -> Unit = {},
)// Wear RemoteCompose
@RemoteComposable
@Composable
fun RemoteHistoryEraserButton(
onClick: Action,
modifier: RemoteModifier = RemoteModifier,
checked: RemoteBoolean = true.rb,
onCheckedChange: Action = Action.Empty,
)// Wear Compose
val colors = MaterialTheme.colorScheme
SplitSwitchButton(
checked = checked,
onCheckedChange = onCheckedChange,
toggleContentDescription = "Arm Eraser",
onContainerClick = onClick,
modifier = modifier.fillMaxWidth(),
colors =
SwitchButtonDefaults.splitSwitchButtonColors(
checkedContainerColor = colors.errorContainer, …
),
label = { Text("History Eraser") },
secondaryLabel = { Text("Don't touch it!") },
)// Wear RemoteCompose
val colors = RemoteMaterialTheme.colorScheme
RemoteSplitSwitchButton(
checked = checked,
onCheckedChange = onCheckedChange,
toggleContentDescription = "Arm Eraser".rs,
onContainerClick = onClick,
modifier = modifier.fillMaxWidth(),
colors =
RemoteSplitSwitchButtonDefaults.splitSwitchButtonColors(
checkedContainerColor = colors.errorContainer, …
),
label = { RemoteText("History Eraser".rs) },
secondaryLabel = { RemoteText("Don't touch it!".rs) },
)@Preview(name = "Squircle Preview", device = "spec:width=1000dp,height=1000dp,dpi=320")
@Composable
fun WeatherWidgetSquirclePreview(
@PreviewParameter(SquircleAllWidgetPreviewParams::class) params: WearWidgetParams
) = WearWidgetPreview(MockWeatherWidget(65, WeatherCondition.CLOUDY), params)
@Preview(name = "Round Preview", device = "spec:width=1000dp,height=1000dp,dpi=320")
@Composable
fun WeatherWidgetRoundPreview(
@PreviewParameter(RoundAllWidgetPreviewParams::class) params: WearWidgetParams
) = WearWidgetPreview(MockWeatherWidget(65, WeatherCondition.CLOUDY), params)@Preview(name = "Widget Picker Preview", device = "spec:width=1000dp,height=1000dp,dpi=320")
@Composable
fun WeatherWidgetRectangularPreview(
@PreviewParameter(RectangularAllWidgetPreviewParams::class) params: WearWidgetParams
) = WearWidgetPreview(MockWeatherWidget(65, WeatherCondition.CLOUDY), params)android skills add wear-widgets
android skills add --all