بخشهای زیر نحوه ترکیب Modifier.blur،
BlurRadiusSpec، BlurStop، و BlurScope را برای الگوهای رایج واسط کاربر نشان میدهد. برای آشنایی با این میاناهای برنامهسازی کاربردی، محو کردن در Compose را ببینید.
محو کردن لبههای محتوای پیمایشی یا کشیدنی
هنگام نمایش فهرست پیمایشی، گردونه، یا انتخابگر، میتوانید از محو کردن تدریجی چندایستگاهی برای نرم کردن موارد نزدیک لبههای محفظه استفاده کنید و درعینحال منطقه مرکزی فعال را در کانون واضح نگه دارید.
محو کردن لبههای بالا و پایین فهرست پیمایشی
برای نرم کردن موارد هنگام پیمایش به داخل و خارج از نمای فهرست عمودی،
BlurRadiusSpec.verticalGradient را با ورودیهای BlurStop به
LazyColumn اعمال کنید. در مثال زیر، که متن ترانه را خطبهخط پیمایش میکند،
ایستهای 0.dp بین 0.42f و 0.58f خط فعال را در مرکز
واضح نگه میدارند، درحالیکه خطوط نزدیک به لبههای بالا و پایین بهتدریج محو میشوند:
@Composable fun SongListTopBottomBlurExample(lyrics: List<String>) { // ... LazyColumn( state = listState, flingBehavior = flingBehavior, modifier = Modifier .width(330.dp) .height(480.dp) .padding(horizontal = 24.dp) .blur( blurRadiusSpec = BlurRadiusSpec.verticalGradient( stops = listOf( BlurStop(fraction = 0.00f, radius = 18.dp), // Heavily blurred top edge BlurStop(fraction = 0.24f, radius = 8.dp), // Soft upper transition BlurStop(fraction = 0.42f, radius = 0.dp), // Sharp center focus starts BlurStop(fraction = 0.58f, radius = 0.dp), // Sharp center focus ends BlurStop(fraction = 0.76f, radius = 8.dp), // Soft lower transition BlurStop(fraction = 1.00f, radius = 18.dp), // Heavily blurred bottom edge ), ), edgeTreatment = BlurredEdgeTreatment.Unbounded, ), contentPadding = PaddingValues(vertical = 36.dp), verticalArrangement = Arrangement.spacedBy(26.dp), horizontalAlignment = Alignment.CenterHorizontally, ) { // ... } }
محو کردن لبههای چپ و راست کنترل افقی
بهطور مشابه، برای جلب توجه به مرکز مؤلفهای که بهصورت افقی پیمایشپذیر یا
کشیدنی است، مثل انتخابگر چرخشی، گردونه، یا مقیاس اندازهگیری،
BlurRadiusSpec.horizontalGradient را با ورودیهای BlurStop اعمال کنید. در
ترازوی وزن کشیدنی زیر، لبههای چپ و راست نرم میشوند درحالیکه
خطوط و اعداد نزدیک عقربه نشانگر مرکزی کاملاً واضح میمانند:
@Composable fun HorizontalScaleBlurExample() { var selectedValue by remember { mutableFloatStateOf(65.0f) } val animatedValue by animateFloatAsState( targetValue = selectedValue, animationSpec = tween(durationMillis = 900, easing = FastOutSlowInEasing), label = "horizontalScaleSmoothScroll", ) Column( modifier = Modifier .width(340.dp) .background(Color(0xFF0F172A), RoundedCornerShape(24.dp)) .padding(vertical = 24.dp), horizontalAlignment = Alignment.CenterHorizontally, ) { Text( text = "${(animatedValue * 10).roundToInt() / 10.0} kg", color = Color.White, fontSize = 44.sp, fontWeight = FontWeight.Black, ) Spacer(Modifier.height(16.dp)) Box( // ... ) { // Ruler ticks blurred at the left and right edges, sharp at center Canvas( modifier = Modifier .fillMaxSize() .blur( blurRadiusSpec = BlurRadiusSpec.horizontalGradient( stops = listOf( BlurStop(fraction = 0.00f, radius = 14.dp), BlurStop(fraction = 0.28f, radius = 0.dp), BlurStop(fraction = 0.72f, radius = 0.dp), BlurStop(fraction = 1.00f, radius = 14.dp), ), ), edgeTreatment = BlurredEdgeTreatment.Unbounded, ), ) { // Draw horizontal ruler ticks offset by `animatedValue` // ... } // ... } } }
ایجاد محوی مورب با linearGradient
BlurRadiusSpec.linearGradient شعاع محوشدگی را درطول یک پارهخط
بین مقادیر start و end DpOffset در فضای مختصات لایه تغییر میدهد.
در داخل بلوک لامبدا Modifier.blur، میتوانید BlurScope.size را بخوانید تا یک محو کردن تدریجی قطری را در سراسر تصویر اصلی از گوشه بالا سمت چپ به گوشه پایین سمت راست اجرا کنید، درحالیکه سوژه در بالا سمت چپ کاملاً واضح باقی میماند و منطقه پایین سمت راست پشت نوشتار همپوشان بهتدریج محو میشود:
@Composable fun DiagonalLinearBlurCardExample() { Box( modifier = Modifier .wrapContentSize() .background(Color(0xFFF8FAFC)) .padding(10.dp), ) { Image( painter = painterResource(id = R.drawable.dog), contentDescription = stringResource(id = R.string.dog_content_description), contentScale = ContentScale.Crop, modifier = Modifier .size(width = 300.dp, height = 380.dp) .blur { blurRadiusSpec = BlurRadiusSpec.linearGradient( start = DpOffset(0.dp, 0.dp), end = DpOffset(size.width, size.height), stops = listOf( BlurStop(fraction = 0.00f, radius = 0.dp), BlurStop(fraction = 0.50f, radius = 0.dp), BlurStop(fraction = 0.75f, radius = 14.dp), BlurStop(fraction = 1.00f, radius = 28.dp), ), ) edgeTreatment = BlurredEdgeTreatment(RoundedCornerShape(24.dp)) }, ) // ... } }
ایجاد مورد ویژه متمرکز با radialGradient
BlurRadiusSpec.radialGradient با تغییر دادن شعاع محوشدگی به سمت بیرون از نقطه کانونی، جلوه نورافکن دایرهای ایجاد میکند. center را بهعنوان DpOffset و
fallOffRadius را بهعنوان فاصله Dp از center که در آن به endRadius
میرسد تعریف کنید. اگر center را بهصورت DpOffset.Unspecified رها کنید، گرادیان در مرکز composable قرار میگیرد، و اگر fallOffRadius را بهصورت Dp.Unspecified رها کنید، بهطور پیشفرض روی نصف بعد کوچکتر لایه تنظیم میشود.
برای مثال، اعمال BlurRadiusSpec.radialGradient روی بخشی از نوشتار
و بهروزرسانی center از رویدادهای کشیدن اشارهگر به کاربر اجازه میدهد تا یک نورافکن دایرهای
خوانش را روی پاراگراف بکشد و درعینحال نوشتار اطراف را محو کند، همانطور که
در مثال زیر نشان داده شده است:
@Composable fun RadialSpotlightTextExample() { var touchOffset by remember { mutableStateOf(Offset.Unspecified) } Box( modifier = Modifier .size(width = 330.dp, height = 340.dp) .background(Color(0xFF0F172A), RoundedCornerShape(20.dp)) .pointerInput(Unit) { detectDragGestures( onDragStart = { offset -> touchOffset = offset }, onDrag = { change, _ -> touchOffset = change.position }, ) } .blur { val spotlightCenter = if (touchOffset.isSpecified) { DpOffset(touchOffset.x.toDp(), touchOffset.y.toDp()) } else { DpOffset(x = size.width / 2, y = size.height / 2) } blurRadiusSpec = BlurRadiusSpec.radialGradient( startRadius = 0.dp, endRadius = 10.dp, center = spotlightCenter, fallOffRadius = 215.dp, ) edgeTreatment = BlurredEdgeTreatment(RoundedCornerShape(20.dp)) } .padding(22.dp), ) { // ... } }
ایجاد ماسک محو سفارشی با سایهزن
برای توزیعهای محوشدگی فضایی پیچیده فراتر از گرادیانهای خطی یا شعاعی، مانند الگوهای تکراری، شکلهای دلخواه، یا نویز رویهای، یک Shader سفارشی، مانند AGSL RuntimeShader، را به BlurRadiusSpec.shader ارسال کنید. سایهزن در مختصات پیکسل لایه از مبدأ بالا سمت راست ارزیابی میشود و کانال آلفای نمونهبرداریشده آن (0..1) maxRadius را مقیاسبندی میکند.
سایهزن و پیکربندی BlurRadiusSpec.shader را یکبار بااستفاده از تابع ترکیبپذیر remember ایجاد کنید تا یک نمونه واحد در ترکیبهای مجدد دوباره استفاده شود. Compose بلوک پیکربندی را با اندازه لایه در هر حل فراخوانی میکند، که در آنجا یونیفرمهای وابسته به اندازه را تنظیم میکنید:
@RequiresApi(Build.VERSION_CODES.TIRAMISU) @Composable fun ShaderBlurExample() { // Creates 6 diagonal frosted-glass bands across the image. val maskShader = remember { RuntimeShader( """ uniform float2 size; half4 main(float2 coord) { float2 uv = coord / size; float band = smoothstep(0.4, 0.6, fract((uv.x + uv.y) * 3.0)); return half4(0.0, 0.0, 0.0, half(band)); } """.trimIndent(), ) } val maskBlurSpec = remember(maskShader) { BlurRadiusSpec.shader(maxRadius = 24.dp) { sizePx -> maskShader.setFloatUniform("size", sizePx.width, sizePx.height) maskShader } } Image( painter = painterResource(id = R.drawable.dog), contentDescription = stringResource(id = R.string.dog_content_description), contentScale = ContentScale.Crop, modifier = Modifier .size(150.dp) .blur(blurRadiusSpec = maskBlurSpec), ) }