Untitled
unknown
plain_text
a year ago
21 kB
5
Indexable
package com.htd.myapplication.ui.main.components
import android.annotation.SuppressLint
import android.content.Context
import android.util.DisplayMetrics
import android.util.Log
import android.view.ViewGroup
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.pager.PagerState
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.layout.positionInWindow
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.viewinterop.AndroidView
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView
import com.google.accompanist.drawablepainter.rememberDrawablePainter
import com.htd.myapplication.MainActivity
import com.htd.myapplication.R
import com.htd.myapplication.data.AppPackage
import com.htd.myapplication.ui.main.MainViewModel
import com.htd.myapplication.ui.theme.dp1
import kotlinx.coroutines.launch
import org.burnoutcrew.reorderable.ReorderableItem
import org.burnoutcrew.reorderable.detectReorderAfterLongPress
import org.burnoutcrew.reorderable.rememberReorderableLazyGridState
import org.burnoutcrew.reorderable.reorderable
import kotlin.math.min
@Composable
fun ListApp(
numberPages: Int,
viewModel: MainViewModel,
appStateList: MutableList<AppPackage>,
modifier: Modifier
) {
val context = LocalContext.current
val openDeleteApp by viewModel.openDeleteApp.collectAsState()
var size1 by remember { mutableStateOf(IntSize.Zero) }
val positionDel = remember { mutableStateOf(0) }
val isNavigateApp by viewModel.isNavigateMode.collectAsState()
if (appStateList.isEmpty()) {
val temp = viewModel.listApps.collectAsState();
appStateList.addAll(temp.value)
}
var appAdapter = remember {
AppAdapter().apply {
this.appList = appStateList.toList()
this.viewModel = viewModel
}
}
LaunchedEffect(key1 = appStateList) {
appAdapter.appList = appStateList.toList()
appAdapter.notifyDataSetChanged()
}
Box(
modifier = modifier
.fillMaxSize()
.onSizeChanged { size1 = it }
) {
var isInUninstallZone by remember { mutableStateOf(false) }
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally
) {
AndroidView(
modifier = Modifier
.fillMaxHeight(0.9f)
.padding(vertical = 10.dp)
.fillMaxWidth(),
factory = { context ->
RecyclerView(context).apply {
layoutManager = GridLayoutManager(context, 5)
adapter = appAdapter
layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
// Setup ItemTouchHelper for drag and drop
val itemTouchHelper = ItemTouchHelper(object :
ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP or ItemTouchHelper.DOWN or ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT, 0) {
override fun onMove(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean {
// Regular drag and drop
val fromPosition = viewHolder.adapterPosition
val toPosition = target.adapterPosition
appStateList.add(toPosition, appStateList.removeAt(fromPosition))
adapter?.notifyItemMoved(fromPosition, toPosition)
return true
}
override fun onSelectedChanged(
viewHolder: RecyclerView.ViewHolder?,
actionState: Int
) {
super.onSelectedChanged(viewHolder, actionState)
if (actionState == ItemTouchHelper.ACTION_STATE_DRAG) {
viewHolder?.itemView?.alpha = 0.5f
viewModel._openDeleteApp.value = true
}
}
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
// No swipe action
}
override fun onChildDraw(
c: android.graphics.Canvas,
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
dX: Float,
dY: Float,
actionState: Int,
isCurrentlyActive: Boolean
) {
// Check if the view is in the uninstall zone
val itemView = viewHolder.itemView
val recyclerViewHeight = recyclerView.height
val itemBottom = itemView.bottom
// Get the screen width and the x position of the dragged item
val screenWidth = recyclerView.width
val itemLeft = itemView.left
val itemRight = itemView.right
// Define uninstall zone: bottom 100px and width centered
val uninstallZoneWidth = 200 / DisplayMetrics().density
val uninstallZoneLeft = (screenWidth - uninstallZoneWidth) / 2
val uninstallZoneRight = uninstallZoneLeft + uninstallZoneWidth
Log.e("anth", "onChildDraw: ${itemBottom} ${recyclerViewHeight} ${itemLeft} ${uninstallZoneLeft} ")
// Check if item is within the bottom and centered uninstall zone
val isDraggingIntoUninstallZone = itemBottom > recyclerViewHeight - 300 && // Bottom 100px
itemLeft >= uninstallZoneLeft
isInUninstallZone = isDraggingIntoUninstallZone
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive)
}
override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
super.clearView(recyclerView, viewHolder)
if (isInUninstallZone) {
isInUninstallZone = false
val position = viewHolder.adapterPosition
if (position != RecyclerView.NO_POSITION) {
val appInfo = appStateList[position]
MainActivity.getInstance()?.uninstallApp(appInfo.pkgId)
positionDel.value = position
}
}
viewModel._openDeleteApp.value = false
viewHolder.itemView.alpha = 1f
Log.e("anth", "clearView: check " + isInUninstallZone)
}
override fun isLongPressDragEnabled(): Boolean {
return true
}
})
itemTouchHelper.attachToRecyclerView(this)
}
},
update = {
if (appAdapter.itemCount != appStateList.size) {
appStateList.removeAt(positionDel.value)
appAdapter.appList = appStateList.toList()
Log.e("anth", "ListApp: need update adapter")
}
}
)
// Uninstall Zone (Bottom of the Screen with specific width)
if (openDeleteApp) {
Box(
modifier = Modifier
.fillMaxWidth()
.height(100.dp),
contentAlignment = Alignment.Center
) {
Box(
modifier = Modifier
.width(200.dp) // Set a specific width for the drop zone
.fillMaxHeight()
.background(Color.Transparent), // Transparent background for inner box
contentAlignment = Alignment.Center
) {
Image(
painter = painterResource(id = R.drawable.image_uninstall_app),
contentDescription = "",
modifier = Modifier.size(width= 100.dp1, height = 30.dp1)
)
}
}
}
}
}
}
@SuppressLint("CoroutineCreationDuringComposition", "StateFlowValueCalledInComposition")
@OptIn(ExperimentalFoundationApi::class)
@Composable
private fun HorizontalGrid(
list: List<AppPackage>,
context: Context, viewModel: MainViewModel,
pagerState: Any,
listApps: List<AppPackage>,
width: Int,
height: Int,
positionDelete: Offset,
widthDevice: Float,
tmp: Boolean,
onChange: (Boolean) -> Unit,
width1: Dp,
height1: Dp
) {
val allowerDeleteApp by viewModel.allowerDeleteApp.collectAsState()
val widthLeftContent by viewModel.widthLeftContent.collectAsState()
val check = remember {
mutableStateOf(0)
}
var lists = remember {
mutableStateOf(list)
}
var listAppss = remember {
mutableStateOf(listApps)
}
LaunchedEffect(tmp, listApps) {
lists.value = list
listAppss.value = listApps
}
val state = rememberReorderableLazyGridState(onMove = {from, to ->
lists.value = lists.value.toMutableList().apply {
val itemToMove = removeAt(from.index)
add(to.index, itemToMove)
}
if (pagerState is PagerState) {
listAppss.value = listAppss.value.toMutableList().apply {
val itemToMove = removeAt(from.index + (pagerState.currentPage * 9))
add(to.index + (pagerState.currentPage * 9), itemToMove)
check.value = check.value ++
}
viewModel.setList(listAppss.value)
}
})
var boxPosition by remember { mutableStateOf(IntOffset.Zero) }
var checkAllowDelete = remember { mutableStateOf(true) }
LazyVerticalGrid(
columns = GridCells.Fixed(5),
state = state.gridState,
verticalArrangement = Arrangement.spacedBy(50.dp1),
horizontalArrangement = Arrangement.spacedBy(width1 * 0.12f),
contentPadding = PaddingValues(horizontal = 30.dp, vertical = 10.dp),
modifier = Modifier
.reorderable(state)
.fillMaxSize()
.detectReorderAfterLongPress(state)
) {
items(lists.value.size, { if (lists.value[it].icon == null) lists.value[it].pkgId else lists.value[it].icon!!.toString()}) { item ->
val coroutineScope = rememberCoroutineScope()
ReorderableItem(state, lists.value[item].icon.toString()) { isDragging ->
if (isDragging) {
viewModel._itemDelete.value = lists.value.get(item)
viewModel._openDeleteApp.value = true
viewModel._allowerDeleteApp.value = false
if (boxPosition.x > widthDevice - 100) {
if (pagerState is PagerState) {
if (checkAllowDelete.value) {
checkAllowDelete.value = false
listAppss.value = listAppss.value.toMutableList().apply {
val itemToMove =
removeAt(item + ((pagerState.currentPage) * 9))
add(min(((pagerState.currentPage + 1) * 9), listAppss.value.size), itemToMove)
}
viewModel.setList(listAppss.value)
coroutineScope.launch {
pagerState.scrollToPage(pagerState.currentPage + 1)
onChange(!tmp)
}
}
}
} else if (boxPosition.x < widthLeftContent && boxPosition.x != 0) {
if (pagerState is PagerState) {
if (pagerState.currentPage > 0) {
if (checkAllowDelete.value) {
checkAllowDelete.value = false
listAppss.value = listAppss.value.toMutableList().apply {
val itemToMove =
removeAt(item + ((pagerState.currentPage) * 9))
add(min(0+ ((pagerState.currentPage - 1) * 9), listAppss.value.size), itemToMove)
}
viewModel.setList(listAppss.value)
coroutineScope.launch {
pagerState.scrollToPage(pagerState.currentPage - 1)
onChange(!tmp)
}
}
}
}
} else if (boxPosition.x < (positionDelete.x + width) && boxPosition.x > (positionDelete.x - width) && boxPosition.y < (positionDelete.y + height) && boxPosition.y > (positionDelete.y - height)) {
viewModel._allowerDeleteApp.value = true
} else {
viewModel._allowerDeleteApp.value = false
}
} else {
if (lists.value.get(item) == viewModel.itemDelete.value) {
viewModel._openDeleteApp.value = false
if (allowerDeleteApp) {
viewModel._allowerDeleteApp.value = false
viewModel.uninstallApp(context = context, packageName = lists.value.get(item).pkgId)
}
}
}
if (lists.value[item].icon == null) {
Box(modifier = Modifier.fillMaxSize()) {
}
} else {
Box(
modifier = Modifier
.fillMaxSize()
.clickable {
kotlin.runCatching {
viewModel.startActivity(context, list[item])
}
}) {
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally
) {
Box(contentAlignment = Alignment.Center) {
Image(
painter = painterResource(id = R.drawable.ic_bg_app),
contentDescription = "",
modifier = Modifier.size(width1 * 0.1f)
)
Image(
painter = rememberDrawablePainter(drawable = lists.value[item].icon),
contentDescription = "",
modifier = Modifier
.size(width1 * 0.065f)
.padding(5.dp1)
.onGloballyPositioned { coordinates ->
if (isDragging == true) {
boxPosition = IntOffset(
x = coordinates.positionInWindow().x.toInt(),
y = coordinates.positionInWindow().y.toInt()
)
}
}
)
}
Text(
text = lists.value[item].title,
modifier = Modifier.padding(top = 10.dp1, bottom = 10.dp1),
maxLines = 1,
overflow = TextOverflow.Ellipsis,
style = TextStyle(
color = Color.White,
fontWeight = FontWeight.Bold,
fontSize = 12.sp
)
)
}
}
}
}
}
}
}
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun ListApps(list: List<AppPackage>, context: Context, viewModel: MainViewModel, height1: Dp) {
LazyVerticalGrid(
columns = GridCells.Adaptive(minSize = 128.dp)
) {
items(list.size, { list[it].icon.toString() }) { index ->
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.combinedClickable(
onClick = {
kotlin.runCatching {
viewModel.startActivity(context, list[index])
}
},
onLongClick = {
viewModel.setModeEdit(true)
})
) {
Box(contentAlignment = Alignment.Center) {
Image(
painter = painterResource(id = R.drawable.ic_bg_app),
contentDescription = "",
modifier = Modifier.size(height1 * 0.12f)
)
Image(
painter = rememberDrawablePainter(drawable = list[index].icon),
contentDescription = "",
modifier = Modifier.size(height1 * 0.1f)
)
}
Text(
text = list[index].title,
modifier = Modifier.padding(top = 10.dp1),
maxLines = 1,
overflow = TextOverflow.Ellipsis,
style = TextStyle(
color = Color.White,
fontWeight = FontWeight.Bold
)
)
}
}
}
}Editor is loading...
Leave a Comment