این صفحه نحوه مدیریت اندازهها و ارائه طرحبندیهای انعطافپذیر و پاسخگو با Glance را با استفاده از مؤلفههای موجود Glance شرح میدهد.
از Box
، Column
و Row
استفاده کنید
Glance دارای سه طرح اصلی قابل ترکیب است:
Box
: عناصر را روی دیگری قرار می دهد. به یکRelativeLayout
ترجمه می شود.Column
: عناصر را پشت سر هم در محور عمودی قرار می دهد. این به یکLinearLayout
با جهت عمودی ترجمه می شود.Row
: عناصر را پشت سر هم در محور افقی قرار می دهد. به یکLinearLayout
با جهت افقی ترجمه می شود.
Glance از اشیاء Scaffold
پشتیبانی می کند. Column
، Row
و Box
را در یک شیء Scaffold
قرار دهید.
هر یک از این ترکیبپذیرها به شما امکان میدهد ترازهای عمودی و افقی محتوای آن و محدودیتهای عرض، ارتفاع، وزن یا بالشتک را با استفاده از اصلاحکنندهها تعریف کنید. علاوه بر این، هر کودک می تواند اصلاح کننده خود را برای تغییر فضا و مکان در داخل والدین تعریف کند.
مثال زیر به شما نشان می دهد که چگونه یک Row
ایجاد کنید که فرزندان خود را به طور یکنواخت به صورت افقی توزیع کند، همانطور که در شکل 1 مشاهده می شود:
Row(modifier = GlanceModifier.fillMaxWidth().padding(16.dp)) { val modifier = GlanceModifier.defaultWeight() Text("first", modifier) Text("second", modifier) Text("third", modifier) }
Row
حداکثر عرض موجود را پر می کند و چون وزن هر کودک یکسان است، فضای موجود را به طور مساوی تقسیم می کند. شما می توانید وزن ها، اندازه ها، بالشتک ها یا ترازهای مختلفی را برای انطباق طرح ها با نیازهای خود تعریف کنید.
از طرح بندی های قابل پیمایش استفاده کنید
راه دیگر برای ارائه محتوای واکنشگرا این است که آن را قابل پیمایش کنید. این کار با LazyColumn
امکان پذیر است. این قابلیت به شما امکان می دهد مجموعه ای از موارد را برای نمایش در یک ظرف قابل پیمایش در ویجت برنامه تعریف کنید.
قطعههای زیر روشهای مختلفی را برای تعریف آیتمهای داخل LazyColumn
نشان میدهند.
شما می توانید تعداد موارد را ارائه دهید:
// Remember to import Glance Composables // import androidx.glance.appwidget.layout.LazyColumn LazyColumn { items(10) { index: Int -> Text( text = "Item $index", modifier = GlanceModifier.fillMaxWidth() ) } }
موارد جداگانه را ارائه دهید:
LazyColumn { item { Text("First Item") } item { Text("Second Item") } }
فهرست یا آرایه ای از موارد را ارائه دهید:
LazyColumn { items(peopleNameList) { name -> Text(name) } }
همچنین می توانید از ترکیبی از مثال های قبلی استفاده کنید:
LazyColumn { item { Text("Names:") } items(peopleNameList) { name -> Text(name) } // or in case you need the index: itemsIndexed(peopleNameList) { index, person -> Text("$person at index $index") } }
توجه داشته باشید که قطعه قبلی itemId
را مشخص نمی کند. مشخص کردن itemId
به بهبود عملکرد و حفظ موقعیت اسکرول از طریق بهروزرسانیهای فهرست و appWidget
از Android 12 به بعد (مثلاً هنگام افزودن یا حذف موارد از فهرست) کمک میکند. مثال زیر نحوه تعیین itemId
را نشان می دهد:
items(items = peopleList, key = { person -> person.id }) { person -> Text(person.name) }
SizeMode
را تعریف کنید
اندازه AppWidget
ممکن است بسته به دستگاه، انتخاب کاربر یا راهانداز متفاوت باشد، بنابراین مهم است که طرحبندیهای انعطافپذیر را همانطور که در صفحه ارائه طرحبندی ویجت انعطافپذیر توضیح داده شده است، ارائه دهید. Glance این را با تعریف SizeMode
و مقدار LocalSize
ساده می کند. بخش های زیر سه حالت را توضیح می دهند.
SizeMode.Single
SizeMode.Single
حالت پیش فرض است. این نشان می دهد که تنها یک نوع محتوا ارائه شده است. یعنی حتی اگر اندازه موجود AppWidget
تغییر کند، اندازه محتوا تغییر نمی کند.
class MyAppWidget : GlanceAppWidget() { override val sizeMode = SizeMode.Single override suspend fun provideGlance(context: Context, id: GlanceId) { // ... provideContent { MyContent() } } @Composable private fun MyContent() { // Size will be the minimum size or resizable // size defined in the App Widget metadata val size = LocalSize.current // ... } }
هنگام استفاده از این حالت، اطمینان حاصل کنید که:
- مقادیر حداقل و حداکثر اندازه ابرداده به درستی بر اساس اندازه محتوا تعریف می شوند.
- محتوا در محدوده اندازه مورد انتظار به اندازه کافی انعطاف پذیر است.
به طور کلی، شما باید از این حالت زمانی استفاده کنید که:
الف) AppWidget
اندازه ثابتی دارد، یا ب) محتوای آن با تغییر اندازه تغییر نمی کند.
SizeMode.Responsive
این حالت معادل ارائه طرحبندیهای واکنشگرا است که به GlanceAppWidget
اجازه میدهد مجموعهای از طرحبندیهای واکنشگرا را با اندازههای خاص تعریف کند. برای هر اندازه تعریف شده، هنگام ایجاد یا به روز رسانی AppWidget
، محتوا ایجاد می شود و به اندازه خاصی نگاشت می شود. سپس سیستم بر اساس اندازه موجود بهترین مناسب را انتخاب می کند.
به عنوان مثال، در AppWidget
مقصد ما، می توانید سه اندازه و محتوای آن را تعریف کنید:
class MyAppWidget : GlanceAppWidget() { companion object { private val SMALL_SQUARE = DpSize(100.dp, 100.dp) private val HORIZONTAL_RECTANGLE = DpSize(250.dp, 100.dp) private val BIG_SQUARE = DpSize(250.dp, 250.dp) } override val sizeMode = SizeMode.Responsive( setOf( SMALL_SQUARE, HORIZONTAL_RECTANGLE, BIG_SQUARE ) ) override suspend fun provideGlance(context: Context, id: GlanceId) { // ... provideContent { MyContent() } } @Composable private fun MyContent() { // Size will be one of the sizes defined above. val size = LocalSize.current Column { if (size.height >= BIG_SQUARE.height) { Text(text = "Where to?", modifier = GlanceModifier.padding(12.dp)) } Row(horizontalAlignment = Alignment.CenterHorizontally) { Button() Button() if (size.width >= HORIZONTAL_RECTANGLE.width) { Button("School") } } if (size.height >= BIG_SQUARE.height) { Text(text = "provided by X") } } } }
در مثال قبلی، متد provideContent
سه بار فراخوانی شده و به اندازه تعریف شده نگاشت شده است.
- در اولین تماس، اندازه به
100x100
ارزیابی می شود. محتوا شامل دکمه اضافی و متون بالا و پایین نیست. - در تماس دوم، اندازه به
250x100
ارزیابی می شود. محتوا شامل دکمه اضافی است، اما نه متن بالا و پایین. - در تماس سوم، اندازه به
250x250
ارزیابی می شود. محتوا شامل دکمه اضافی و هر دو متن است.
SizeMode.Responsive
ترکیبی از دو حالت دیگر است و به شما امکان می دهد محتوای پاسخگو را در محدوده های از پیش تعریف شده تعریف کنید. به طور کلی، این حالت عملکرد بهتری دارد و هنگامی که اندازه AppWidget
تغییر میکند، امکان انتقال نرمتر را فراهم میکند.
جدول زیر مقدار اندازه را بسته به اندازه SizeMode
و AppWidget
در دسترس نشان می دهد:
اندازه موجود | 105*110 | 203 x 112 | 72*72 | 203*150 |
---|---|---|---|---|
SizeMode.Single | 110*110 | 110*110 | 110*110 | 110*110 |
SizeMode.Exact | 105*110 | 203 x 112 | 72*72 | 203*150 |
SizeMode.Responsive | 80*100 | 80*100 | 80*100 | 150*120 |
* مقادیر دقیق فقط برای اهداف آزمایشی هستند. |
SizeMode.Exact
SizeMode.Exact
معادل ارائه طرحبندیهای دقیق است که هر بار که اندازه AppWidget
موجود تغییر میکند، محتوای GlanceAppWidget
را درخواست میکند (به عنوان مثال، زمانی که کاربر AppWidget
در صفحه اصلی تغییر میدهد).
به عنوان مثال، در ویجت مقصد، اگر عرض موجود بزرگتر از مقدار معینی باشد، می توان یک دکمه اضافی اضافه کرد.
class MyAppWidget : GlanceAppWidget() { override val sizeMode = SizeMode.Exact override suspend fun provideGlance(context: Context, id: GlanceId) { // ... provideContent { MyContent() } } @Composable private fun MyContent() { // Size will be the size of the AppWidget val size = LocalSize.current Column { Text(text = "Where to?", modifier = GlanceModifier.padding(12.dp)) Row(horizontalAlignment = Alignment.CenterHorizontally) { Button() Button() if (size.width > 250.dp) { Button("School") } } } } }
این حالت نسبت به حالت های دیگر انعطاف پذیری بیشتری را ارائه می دهد، اما با چند اخطار همراه است:
- هر بار که اندازه تغییر می کند،
AppWidget
باید کاملاً بازسازی شود. این می تواند منجر به مشکلات عملکرد و جهش UI در زمانی که محتوا پیچیده است، شود. - اندازه موجود ممکن است بسته به اجرای راهانداز متفاوت باشد. به عنوان مثال، اگر لانچر لیست اندازه ها را ارائه ندهد، از حداقل اندازه ممکن استفاده می شود.
- در دستگاههای پیش از اندروید 12، منطق محاسبه اندازه ممکن است در همه شرایط کار نکند.
به طور کلی، اگر SizeMode.Responsive
قابل استفاده نباشد، باید از این حالت استفاده کنید (یعنی مجموعه کوچکی از طرحبندیهای واکنشگرا امکانپذیر نیست).
دسترسی به منابع
همانطور که در مثال زیر نشان داده شده است، از LocalContext.current
برای دسترسی به هر منبع Android استفاده کنید:
LocalContext.current.getString(R.string.glance_title)
توصیه میکنیم برای کاهش اندازه شی RemoteViews
نهایی و فعال کردن منابع پویا، مانند رنگهای پویا، شناسههای منبع را مستقیماً ارائه کنید.
ترکیبپذیرها و روشها منابع را با استفاده از یک "ارائهدهنده"، مانند ImageProvider
، یا با استفاده از یک روش اضافه بار مانند GlanceModifier.background(R.color.blue)
میپذیرند. به عنوان مثال:
Column( modifier = GlanceModifier.background(R.color.default_widget_background) ) { /**...*/ } Image( provider = ImageProvider(R.drawable.ic_logo), contentDescription = "My image", )
مدیریت متن
Glance 1.1.0 شامل یک API برای تنظیم سبک های متن شما است. سبک های متن را با استفاده از ویژگی های fontSize
، fontWeight
یا fontFamily
کلاس TextStyle تنظیم کنید.
همانطور که در مثال زیر نشان داده شده است، fontFamily
از تمام فونت های سیستم پشتیبانی می کند، اما فونت های سفارشی در برنامه ها پشتیبانی نمی شوند:
Text(
style = TextStyle(
fontWeight = FontWeight.Bold,
fontSize = 18.sp,
fontFamily = FontFamily.Monospace
),
text = "Example Text"
)
دکمه های ترکیبی را اضافه کنید
دکمه های ترکیبی در اندروید 12 معرفی شدند. Glance از سازگاری به عقب برای انواع دکمه های ترکیبی زیر پشتیبانی می کند:
این دکمههای مرکب، هر یک نمای قابل کلیک را نشان میدهند که نشاندهنده وضعیت "بررسی" است.
var isApplesChecked by remember { mutableStateOf(false) } var isEnabledSwitched by remember { mutableStateOf(false) } var isRadioChecked by remember { mutableStateOf(0) } CheckBox( checked = isApplesChecked, onCheckedChange = { isApplesChecked = !isApplesChecked }, text = "Apples" ) Switch( checked = isEnabledSwitched, onCheckedChange = { isEnabledSwitched = !isEnabledSwitched }, text = "Enabled" ) RadioButton( checked = isRadioChecked == 1, onClick = { isRadioChecked = 1 }, text = "Checked" )
هنگامی که وضعیت تغییر می کند، لامبدای ارائه شده فعال می شود. همانطور که در مثال زیر نشان داده شده است، می توانید وضعیت چک را ذخیره کنید:
class MyAppWidget : GlanceAppWidget() { override suspend fun provideGlance(context: Context, id: GlanceId) { val myRepository = MyRepository.getInstance() provideContent { val scope = rememberCoroutineScope() val saveApple: (Boolean) -> Unit = { scope.launch { myRepository.saveApple(it) } } MyContent(saveApple) } } @Composable private fun MyContent(saveApple: (Boolean) -> Unit) { var isAppleChecked by remember { mutableStateOf(false) } Button( text = "Save", onClick = { saveApple(isAppleChecked) } ) } }
همچنین میتوانید ویژگیهای colors
به CheckBox
، Switch
و RadioButton
برای سفارشی کردن رنگهای آنها ارائه دهید:
CheckBox( // ... colors = CheckboxDefaults.colors( checkedColor = ColorProvider(day = colorAccentDay, night = colorAccentNight), uncheckedColor = ColorProvider(day = Color.DarkGray, night = Color.LightGray) ), checked = isChecked, onCheckedChange = { isChecked = !isChecked } ) Switch( // ... colors = SwitchDefaults.colors( checkedThumbColor = ColorProvider(day = Color.Red, night = Color.Cyan), uncheckedThumbColor = ColorProvider(day = Color.Green, night = Color.Magenta), checkedTrackColor = ColorProvider(day = Color.Blue, night = Color.Yellow), uncheckedTrackColor = ColorProvider(day = Color.Magenta, night = Color.Green) ), checked = isChecked, onCheckedChange = { isChecked = !isChecked }, text = "Enabled" ) RadioButton( // ... colors = RadioButtonDefaults.colors( checkedColor = ColorProvider(day = Color.Cyan, night = Color.Yellow), uncheckedColor = ColorProvider(day = Color.Red, night = Color.Blue) ), )
اجزای اضافی
Glance 1.1.0 شامل انتشار اجزای اضافی است که در جدول زیر توضیح داده شده است:
نام | تصویر | لینک مرجع | یادداشت های اضافی |
---|---|---|---|
دکمه پر شده | جزء | ||
دکمه های طرح کلی | جزء | ||
دکمه های آیکون | جزء | اولیه / ثانویه / فقط نماد | |
نوار عنوان | جزء | ||
داربست | Scaffold و Title Bar در یک نسخه نمایشی هستند. |
برای اطلاعات بیشتر در مورد مشخصات طراحی، به طرح های اجزای این کیت طراحی در Figma مراجعه کنید.
برای اطلاعات بیشتر در مورد طرحبندیهای متعارف، از طرحبندی ویجتهای کانونی دیدن کنید.