دکمه Draggable: کاوش در عناصر UI تعاملی با آهنگسازی Jetpack

ایجاد عناصر UI تعاملی روشی خارق العاده برای تقویت تعامل کاربر در برنامه های تلفن همراه است. یکی از این عناصر یک دکمه قابل کشیدن است – یک مؤلفه ساده و در عین حال قدرتمند که می تواند احساس بازیگوش و پویا را به برنامه شما برساند.
در این پست وبلاگ ، ما چگونگی ایجاد دکمه های قابل کشیدن را با استفاده از JetPack Compose ، یک ابزار مدرن برای ساخت UIS بومی بومی بررسی خواهیم کرد. ما دو اثر را پوشش خواهیم داد: یک دکمه قابل کشیدن اساسی و یک نسخه پیشرفته که هنگام انتشار به موقعیت اصلی خود باز می گردد.
دکمه قابل کشیدن اساسی
پیش نمایش اثر
رمز کامل
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.gestures.detectDragGestures
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.material3.Button
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.IntOffset
import com.kevintest.myapplication.ui.theme.MyApplicationTheme
import kotlin.math.roundToInt
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
MyApplicationTheme {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
DraggableButtonScreen(
modifier = Modifier.padding(innerPadding)
)
}
}
}
}
}
@Composable
fun DraggableButtonScreen(modifier: Modifier) {
Box(
contentAlignment = Alignment.Center,
modifier = modifier
.fillMaxSize()
.statusBarsPadding()
.navigationBarsPadding()
) {
DraggableButton()
}
}
@Composable
private fun DraggableButton() {
var offset by remember { mutableStateOf(IntOffset.Zero) }
val context = LocalContext.current
Button(
onClick = {},
modifier = Modifier
.offset { offset }
.pointerInput(Unit) {
detectDragGestures(
onDrag = { change, dragAmount ->
val maxOffsetX = (context.resources.displayMetrics.widthPixels - size.width) / 2
val maxOffsetY = (context.resources.displayMetrics.heightPixels - size.height) / 2
offset = IntOffset(
(offset.x + dragAmount.x.roundToInt()).coerceIn(-maxOffsetX, maxOffsetX),
(offset.y + dragAmount.y.roundToInt()).coerceIn(-maxOffsetY, maxOffsetY)
)
change.consume()
}
)
}
) {
Text("Drag me")
}
}
تجزیه کد
دکمه اصلی DragGable از روش Jetpack Compose Compose برای انجام عملیات کشیدن استفاده می کند. در اینجا یک توضیح گام به گام در مورد کد آورده شده است:
- اولیه سازی حالت: ما استفاده می کنیم
remember { mutableStateOf(IntOffset.Zero) }
برای اولیه کردن جبران دکمه. با کشیدن دکمه ، این حالت به روز می شود. - تشخیص ژست کشیدن:
detectDragGestures
از روش برای ردیابی رویدادهای کشیدن استفاده می شود. در داخل این روش:- ONDRAG: این پاسخ به تماس ، جبران دکمه را بر اساس مقدار کشیدن به روز می کند. ما استفاده می کنیم
coerceIn
برای اطمینان از ماندن دکمه در مرزهای صفحه. - Change.Consume (): این تماس مانع از انتشار بیشتر رویداد درگ ، اطمینان از تعامل صاف می شود.
- ONDRAG: این پاسخ به تماس ، جبران دکمه را بر اساس مقدار کشیدن به روز می کند. ما استفاده می کنیم
- مرزهای صفحه: برای جلوگیری از کشیدن دکمه به بیرون از صفحه ، ما بر اساس اندازه صفحه نمایش و ابعاد دکمه MaxoffsetX و MaxoffSety را محاسبه می کنیم.
دکمه قابل کشیدن با اثر ضربه محکم و ناگهانی
پیش نمایش اثر
رمز کامل
@Composable
private fun DraggableButton() {
var offset by remember { mutableStateOf(IntOffset.Zero) }
var isDragging by remember { mutableStateOf(false) }
val animatedOffset by animateIntOffsetAsState(
targetValue = if (isDragging) offset else IntOffset.Zero,
animationSpec = tween(durationMillis = 300),
label = "offsetAnimation"
)
val context = LocalContext.current
Button(
onClick = {},
modifier = Modifier
.offset { if (isDragging) offset else animatedOffset }
.pointerInput(Unit) {
detectDragGestures(
onDragStart = { isDragging = true },
onDragEnd = {
isDragging = false
offset = IntOffset.Zero
},
onDrag = { change, dragAmount ->
val maxOffsetX = (context.resources.displayMetrics.widthPixels - size.width) / 2
val maxOffsetY = (context.resources.displayMetrics.heightPixels - size.height) / 2
offset = IntOffset(
(offset.x + dragAmount.x.roundToInt()).coerceIn(-maxOffsetX, maxOffsetX),
(offset.y + dragAmount.y.roundToInt()).coerceIn(-maxOffsetY, maxOffsetY)
)
change.consume()
}
)
}
) {
Text("Drag me")
}
}
تجزیه کد
اثر ضربه محکم و ناگهانی یک پیچ و تاب سرگرم کننده را به دکمه DragGable اضافه می کند. هنگامی که دکمه آزاد شد ، به راحتی به موقعیت اصلی خود متحرک می شود. این با استفاده از JetPack Compose حاصل می شود animateIntOffsetAsState
روش
- اولیه سازی حالت: ما یک متغیر حالت اضافی را معرفی می کنیم
isDragging
برای ردیابی اینکه آیا دکمه کشیده شده است. - منطق انیمیشن:
animateIntOffsetAsState
روش جبران دکمه را متحرک می کند. کیisDragging
است ،false
، دکمه انیمیشن بهIntOffset.Zero
بشر - به روزرسانی های ژست را بکشید:
onDragStart
مجموعه های برگشتیisDragging
بهtrue
، در حالی کهonDragEnd
تنظیم مجدد آن بهfalse
و دکمه را به موقعیت اصلی خود بازگرداند.
این همه ، متشکرم (= ، =)