Compare commits
2 Commits
3cd21f8fca
...
fd84f18e4d
| Author | SHA1 | Date | |
|---|---|---|---|
| fd84f18e4d | |||
| fe025c8a69 |
48
.kotlin/errors/errors-1779517395470.log
Normal file
48
.kotlin/errors/errors-1779517395470.log
Normal file
@@ -0,0 +1,48 @@
|
||||
kotlin version: 2.2.10
|
||||
error message: java.nio.file.AccessDeniedException: C:\Users\Administrator\AppData\Local\kotlin\daemon\kotlin-daemon-client-tsmarker12650102232292672793.tmp
|
||||
|
||||
error message: Daemon compilation failed: Could not connect to Kotlin compile daemon
|
||||
java.lang.RuntimeException: Could not connect to Kotlin compile daemon
|
||||
at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.compileWithDaemon(GradleKotlinCompilerWork.kt:214)
|
||||
at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.compileWithDaemonOrFallbackImpl(GradleKotlinCompilerWork.kt:159)
|
||||
at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.run(GradleKotlinCompilerWork.kt:111)
|
||||
at org.jetbrains.kotlin.compilerRunner.GradleCompilerRunnerWithWorkers$GradleKotlinCompilerWorkAction.execute(GradleCompilerRunnerWithWorkers.kt:74)
|
||||
at org.gradle.workers.internal.DefaultWorkerServer.execute(DefaultWorkerServer.java:68)
|
||||
at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:64)
|
||||
at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:61)
|
||||
at org.gradle.internal.classloader.ClassLoaderUtils.executeInClassloader(ClassLoaderUtils.java:102)
|
||||
at org.gradle.workers.internal.NoIsolationWorkerFactory$1.lambda$execute$0(NoIsolationWorkerFactory.java:61)
|
||||
at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:44)
|
||||
at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:41)
|
||||
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:209)
|
||||
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)
|
||||
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
|
||||
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
|
||||
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:166)
|
||||
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
|
||||
at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
|
||||
at org.gradle.workers.internal.AbstractWorker.executeWrappedInBuildOperation(AbstractWorker.java:41)
|
||||
at org.gradle.workers.internal.NoIsolationWorkerFactory$1.execute(NoIsolationWorkerFactory.java:58)
|
||||
at org.gradle.workers.internal.DefaultWorkerExecutor.lambda$submitWork$0(DefaultWorkerExecutor.java:176)
|
||||
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
|
||||
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runExecution(DefaultConditionalExecutionQueue.java:194)
|
||||
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.access$700(DefaultConditionalExecutionQueue.java:127)
|
||||
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner$1.run(DefaultConditionalExecutionQueue.java:169)
|
||||
at org.gradle.internal.Factories$1.create(Factories.java:30)
|
||||
at org.gradle.internal.work.DefaultWorkerLeaseService.lambda$withLocksAcquired$0(DefaultWorkerLeaseService.java:269)
|
||||
at org.gradle.internal.work.ResourceLockStatistics$1.measure(ResourceLockStatistics.java:42)
|
||||
at org.gradle.internal.work.DefaultWorkerLeaseService.withLocksAcquired(DefaultWorkerLeaseService.java:267)
|
||||
at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:259)
|
||||
at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:127)
|
||||
at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:132)
|
||||
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runBatch(DefaultConditionalExecutionQueue.java:164)
|
||||
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.run(DefaultConditionalExecutionQueue.java:133)
|
||||
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572)
|
||||
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
|
||||
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
|
||||
at org.gradle.internal.concurrent.AbstractManagedExecutor$1.run(AbstractManagedExecutor.java:47)
|
||||
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
|
||||
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
|
||||
at java.base/java.lang.Thread.run(Thread.java:1583)
|
||||
|
||||
|
||||
48
.kotlin/errors/errors-1779517396396.log
Normal file
48
.kotlin/errors/errors-1779517396396.log
Normal file
@@ -0,0 +1,48 @@
|
||||
kotlin version: 2.2.10
|
||||
error message: java.nio.file.AccessDeniedException: C:\Users\Administrator\AppData\Local\kotlin\daemon\kotlin-daemon-client-tsmarker2077405252922174295.tmp
|
||||
|
||||
error message: Daemon compilation failed: Could not connect to Kotlin compile daemon
|
||||
java.lang.RuntimeException: Could not connect to Kotlin compile daemon
|
||||
at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.compileWithDaemon(GradleKotlinCompilerWork.kt:214)
|
||||
at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.compileWithDaemonOrFallbackImpl(GradleKotlinCompilerWork.kt:159)
|
||||
at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.run(GradleKotlinCompilerWork.kt:111)
|
||||
at org.jetbrains.kotlin.compilerRunner.GradleCompilerRunnerWithWorkers$GradleKotlinCompilerWorkAction.execute(GradleCompilerRunnerWithWorkers.kt:74)
|
||||
at org.gradle.workers.internal.DefaultWorkerServer.execute(DefaultWorkerServer.java:68)
|
||||
at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:64)
|
||||
at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:61)
|
||||
at org.gradle.internal.classloader.ClassLoaderUtils.executeInClassloader(ClassLoaderUtils.java:102)
|
||||
at org.gradle.workers.internal.NoIsolationWorkerFactory$1.lambda$execute$0(NoIsolationWorkerFactory.java:61)
|
||||
at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:44)
|
||||
at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:41)
|
||||
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:209)
|
||||
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)
|
||||
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
|
||||
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
|
||||
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:166)
|
||||
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
|
||||
at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
|
||||
at org.gradle.workers.internal.AbstractWorker.executeWrappedInBuildOperation(AbstractWorker.java:41)
|
||||
at org.gradle.workers.internal.NoIsolationWorkerFactory$1.execute(NoIsolationWorkerFactory.java:58)
|
||||
at org.gradle.workers.internal.DefaultWorkerExecutor.lambda$submitWork$0(DefaultWorkerExecutor.java:176)
|
||||
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
|
||||
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runExecution(DefaultConditionalExecutionQueue.java:194)
|
||||
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.access$700(DefaultConditionalExecutionQueue.java:127)
|
||||
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner$1.run(DefaultConditionalExecutionQueue.java:169)
|
||||
at org.gradle.internal.Factories$1.create(Factories.java:30)
|
||||
at org.gradle.internal.work.DefaultWorkerLeaseService.lambda$withLocksAcquired$0(DefaultWorkerLeaseService.java:269)
|
||||
at org.gradle.internal.work.ResourceLockStatistics$1.measure(ResourceLockStatistics.java:42)
|
||||
at org.gradle.internal.work.DefaultWorkerLeaseService.withLocksAcquired(DefaultWorkerLeaseService.java:267)
|
||||
at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:259)
|
||||
at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:127)
|
||||
at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:132)
|
||||
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runBatch(DefaultConditionalExecutionQueue.java:164)
|
||||
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.run(DefaultConditionalExecutionQueue.java:133)
|
||||
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572)
|
||||
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
|
||||
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
|
||||
at org.gradle.internal.concurrent.AbstractManagedExecutor$1.run(AbstractManagedExecutor.java:47)
|
||||
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
|
||||
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
|
||||
at java.base/java.lang.Thread.run(Thread.java:1583)
|
||||
|
||||
|
||||
@@ -102,5 +102,6 @@ dependencies {
|
||||
implementation("androidx.camera:camera-view:1.0.0-alpha25")
|
||||
//上拉刷新下拉加载
|
||||
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
|
||||
implementation("com.yanzhenjie.recyclerview:x:1.3.2")
|
||||
|
||||
}
|
||||
@@ -15,10 +15,8 @@ data class LinkedUser(
|
||||
)
|
||||
|
||||
class LinkedUserAdapter(
|
||||
private val deleteText: String,
|
||||
private val isUnlinkMode: Boolean,
|
||||
private val onItemClick: (LinkedUser, Int) -> Unit,
|
||||
private val onDeleteClick: (LinkedUser, Int) -> Unit
|
||||
private val onItemClick: (LinkedUser, Int) -> Unit
|
||||
) : RecyclerView.Adapter<LinkedUserAdapter.LinkedUserViewHolder>() {
|
||||
|
||||
private val items = mutableListOf<LinkedUser>()
|
||||
@@ -36,12 +34,6 @@ class LinkedUserAdapter(
|
||||
}
|
||||
}
|
||||
|
||||
fun closeSwipe(position: Int) {
|
||||
if (position in items.indices) {
|
||||
notifyItemChanged(position)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LinkedUserViewHolder {
|
||||
val binding = ItemLinkedUserBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
@@ -52,53 +44,24 @@ class LinkedUserAdapter(
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: LinkedUserViewHolder, position: Int) {
|
||||
|
||||
holder.bind(items[position], position)
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = items.size
|
||||
|
||||
inner class LinkedUserViewHolder(
|
||||
private val binding: ItemLinkedUserBinding
|
||||
val binding: ItemLinkedUserBinding
|
||||
) : RecyclerView.ViewHolder(binding.root) {
|
||||
|
||||
fun bind(item: LinkedUser, position: Int) {
|
||||
binding.tvPhone.text = "手机号码:${item.phone}"
|
||||
binding.tvIdCard.text = "身份证号:${item.idCard}"
|
||||
binding.llContent.translationX = 0f
|
||||
binding.tvUserName.text = item.name
|
||||
binding.tvTime.text = item.time
|
||||
binding.tvPhone.text = "手机号码:${item.phone}"
|
||||
binding.tvIdCard.text = "身份证号:${item.idCard}"
|
||||
|
||||
// MODE_SETTINGS → 显示"解除关联";MODE_PERSONAL → 显示"删除"
|
||||
if (isUnlinkMode) {
|
||||
binding.tvUnlinkAction.visibility = View.VISIBLE
|
||||
binding.tvDeleteAction.visibility = View.GONE
|
||||
} else {
|
||||
binding.tvUnlinkAction.visibility = View.GONE
|
||||
binding.tvDeleteAction.visibility = View.VISIBLE
|
||||
binding.tvDeleteAction.text = deleteText
|
||||
}
|
||||
|
||||
binding.llContent.setOnClickListener {
|
||||
if (binding.llContent.translationX < 0f) {
|
||||
binding.llContent.animate()
|
||||
.translationX(0f)
|
||||
.setDuration(200)
|
||||
.start()
|
||||
} else {
|
||||
onItemClick(item, position)
|
||||
}
|
||||
}
|
||||
|
||||
binding.tvDeleteAction.setOnClickListener {
|
||||
onDeleteClick(item, position)
|
||||
}
|
||||
|
||||
binding.tvUnlinkAction.setOnClickListener {
|
||||
onDeleteClick(item, position)
|
||||
binding.root.setOnClickListener {
|
||||
onItemClick(item, position)
|
||||
}
|
||||
}
|
||||
|
||||
fun getContentLayout(): View = binding.llContent
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ import com.gyf.immersionbar.ImmersionBar
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
class AddLinkedUserActivity : AppCompatActivity() {
|
||||
private lateinit var binding: AddLinkedUserActivityBinding
|
||||
private val selectedPhoneSet = mutableSetOf<String>()
|
||||
@@ -37,9 +37,16 @@ class AddLinkedUserActivity : AppCompatActivity() {
|
||||
|
||||
initRecyclerView()
|
||||
initListener()
|
||||
setupSwipeRefresh()
|
||||
fetchFamilyMembers()
|
||||
}
|
||||
|
||||
private fun setupSwipeRefresh() {
|
||||
binding.swipeRefresh.setOnRefreshListener {
|
||||
fetchFamilyMembers()
|
||||
}
|
||||
}
|
||||
|
||||
private fun initRecyclerView() {
|
||||
binding.rvAddLinkedUser.layoutManager = LinearLayoutManager(this)
|
||||
binding.rvAddLinkedUser.adapter =
|
||||
@@ -52,13 +59,31 @@ class AddLinkedUserActivity : AppCompatActivity() {
|
||||
selectedUserIdMap.remove(phone)
|
||||
}
|
||||
}
|
||||
|
||||
// 设置上拉加载更多
|
||||
binding.rvAddLinkedUser.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||
super.onScrolled(recyclerView, dx, dy)
|
||||
val layoutManager = recyclerView.layoutManager as LinearLayoutManager
|
||||
val totalItemCount = layoutManager.itemCount
|
||||
val lastVisibleItem = layoutManager.findLastVisibleItemPosition()
|
||||
if (totalItemCount > 0 && lastVisibleItem >= totalItemCount - 3) {
|
||||
// 滑到底部时自动刷新(加载更多)
|
||||
if (!binding.swipeRefresh.isRefreshing) {
|
||||
fetchFamilyMembers()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun fetchFamilyMembers() {
|
||||
binding.swipeRefresh.isRefreshing = true
|
||||
lifecycleScope.launch {
|
||||
try {
|
||||
val response = RetrofitNetwork.getNetworkService().getFamilyMembers()
|
||||
withContext(Dispatchers.Main) {
|
||||
binding.swipeRefresh.isRefreshing = false
|
||||
if (response.code == 200) {
|
||||
if (response.data != null && response.data.isNotEmpty()) {
|
||||
updateFamilyMemberList(response.data)
|
||||
@@ -72,6 +97,7 @@ class AddLinkedUserActivity : AppCompatActivity() {
|
||||
} catch (e: Exception) {
|
||||
android.util.Log.e("AddLinkedUserActivity", "网络请求异常", e)
|
||||
withContext(Dispatchers.Main) {
|
||||
binding.swipeRefresh.isRefreshing = false
|
||||
Toast.makeText(this@AddLinkedUserActivity, "网络请求失败: ${e.message}", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,12 +4,11 @@ import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.text.Editable
|
||||
import android.text.TextWatcher
|
||||
import android.util.TypedValue
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.ItemTouchHelper
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.example.defenseapplication.R
|
||||
@@ -24,10 +23,12 @@ import com.example.defenseapplication.utils.DeviceUserUpdateEvent
|
||||
import com.example.defenseapplication.utils.RetrofitNetwork
|
||||
import com.example.defenseapplication.view.CustomDialogFragmentText
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
import com.yanzhenjie.recyclerview.SwipeMenuItem
|
||||
import com.yanzhenjie.recyclerview.SwipeRecyclerView
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
//关联用户页面
|
||||
|
||||
class LinkedUserActivity : AppCompatActivity() {
|
||||
|
||||
private lateinit var binding: LinkedUserActivityBinding
|
||||
@@ -37,8 +38,6 @@ class LinkedUserActivity : AppCompatActivity() {
|
||||
private var mode: Int = MODE_SETTINGS
|
||||
|
||||
companion object {
|
||||
const val REQUEST_CODE_SEARCH = 1001
|
||||
const val EXTRA_SEARCH_RESULT = "search_result"
|
||||
const val EXTRA_MODE = "extra_mode"
|
||||
const val MODE_SETTINGS = 0
|
||||
const val MODE_PERSONAL = 1
|
||||
@@ -75,139 +74,57 @@ class LinkedUserActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
private fun initView() {
|
||||
val deleteText = if (mode == MODE_SETTINGS) getString(R.string.unlink) else getString(R.string.delete)
|
||||
val isUnlinkMode = mode == MODE_SETTINGS
|
||||
adapter = LinkedUserAdapter(
|
||||
deleteText = deleteText,
|
||||
isUnlinkMode = isUnlinkMode,
|
||||
isUnlinkMode = mode == MODE_SETTINGS,
|
||||
onItemClick = { user, position ->
|
||||
val intent = Intent(this, UserDetailsActivity::class.java).apply {
|
||||
putExtra("userId", user.userId)
|
||||
putExtra("deleteText", if (mode == MODE_SETTINGS) getString(R.string.unlink) else getString(R.string.delete))
|
||||
putExtra("isUnlinkMode", mode == MODE_SETTINGS)
|
||||
}
|
||||
startActivity(intent)
|
||||
},
|
||||
onDeleteClick = { user, position ->
|
||||
showUnlinkDialog(user, position)
|
||||
}
|
||||
)
|
||||
binding.rvLinkedUser.layoutManager = LinearLayoutManager(this)
|
||||
binding.rvLinkedUser.adapter = adapter
|
||||
|
||||
// 根据模式只显示一个按钮,滑动露出完整按钮
|
||||
val swipeThresholdPx = TypedValue.applyDimension(
|
||||
TypedValue.COMPLEX_UNIT_DIP, -100f, resources.displayMetrics
|
||||
)
|
||||
val heldPositions = mutableMapOf<Int, Boolean>()
|
||||
(binding.rvLinkedUser as RecyclerView).layoutManager = LinearLayoutManager(this)
|
||||
|
||||
var currentlyHeldPosition: Int = -1
|
||||
binding.swipeRefresh.setOnRefreshListener {
|
||||
fetchUserList()
|
||||
}
|
||||
|
||||
val itemTouchHelper = ItemTouchHelper(object : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT) {
|
||||
override fun onMove(
|
||||
recyclerView: RecyclerView,
|
||||
viewHolder: RecyclerView.ViewHolder,
|
||||
target: RecyclerView.ViewHolder
|
||||
): Boolean = false
|
||||
|
||||
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
|
||||
}
|
||||
|
||||
override fun onChildDraw(
|
||||
c: android.graphics.Canvas,
|
||||
recyclerView: RecyclerView,
|
||||
viewHolder: RecyclerView.ViewHolder,
|
||||
dX: Float,
|
||||
dY: Float,
|
||||
actionState: Int,
|
||||
isCurrentlyActive: Boolean
|
||||
) {
|
||||
if (viewHolder is LinkedUserAdapter.LinkedUserViewHolder) {
|
||||
val contentLayout = viewHolder.getContentLayout()
|
||||
val position = viewHolder.adapterPosition
|
||||
|
||||
// 如果当前滑动的位置和已展开的位置不同,先收起已展开的项
|
||||
if (isCurrentlyActive && currentlyHeldPosition != -1 && currentlyHeldPosition != position) {
|
||||
val oldViewHolder = recyclerView.findViewHolderForAdapterPosition(currentlyHeldPosition)
|
||||
if (oldViewHolder is LinkedUserAdapter.LinkedUserViewHolder) {
|
||||
oldViewHolder.getContentLayout().animate()
|
||||
.translationX(0f)
|
||||
.setDuration(200)
|
||||
.start()
|
||||
}
|
||||
heldPositions.remove(currentlyHeldPosition)
|
||||
currentlyHeldPosition = -1
|
||||
}
|
||||
|
||||
if (isCurrentlyActive) {
|
||||
val isHeld = heldPositions[position]
|
||||
if (isHeld == true) {
|
||||
if (dX > 0) {
|
||||
// 已展开时向右滑动 → 平滑收回
|
||||
val newX = swipeThresholdPx + dX
|
||||
// 不能超过原位
|
||||
contentLayout.translationX = if (newX > 0) 0f else newX
|
||||
} else {
|
||||
// 保持展开或继续左滑(限制不超过阈值)
|
||||
contentLayout.translationX = swipeThresholdPx
|
||||
}
|
||||
} else {
|
||||
// 未展开,正常滑动限制(左滑不超过阈值,右滑不超过原位)
|
||||
val swipeDistance = when {
|
||||
dX < swipeThresholdPx -> swipeThresholdPx
|
||||
dX > 0 -> 0f
|
||||
else -> dX
|
||||
}
|
||||
contentLayout.translationX = swipeDistance
|
||||
}
|
||||
} else {
|
||||
val isHeld = heldPositions[position]
|
||||
if (isHeld == true) {
|
||||
contentLayout.translationX = swipeThresholdPx
|
||||
}
|
||||
}
|
||||
binding.rvLinkedUser.setSwipeMenuCreator { leftMenu, rightMenu, position ->
|
||||
if (mode == MODE_SETTINGS) {
|
||||
val unlinkItem = SwipeMenuItem(this@LinkedUserActivity).apply {
|
||||
setText(getString(R.string.unlink))
|
||||
setBackgroundColor(getColor(R.color.red))
|
||||
setTextColor(getColor(R.color.white))
|
||||
width = 200
|
||||
height = ViewGroup.LayoutParams.MATCH_PARENT
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
- 滑动超过一半后松手:列表项 保持在滑动位置,显示按钮
|
||||
- 滑动未超过一半松手:列表项 恢复原位
|
||||
- 已展开状态下向右拖动归位或拖动超过一半松手:恢复原位
|
||||
* */
|
||||
override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
|
||||
super.clearView(recyclerView, viewHolder)
|
||||
if (viewHolder is LinkedUserAdapter.LinkedUserViewHolder) {
|
||||
val position = viewHolder.adapterPosition
|
||||
val contentLayout = viewHolder.getContentLayout()
|
||||
|
||||
// 判断滑动距离是否超过一半阈值(注意都是负数,所以绝对值比较)
|
||||
if (Math.abs(contentLayout.translationX) > Math.abs(swipeThresholdPx / 2)) {
|
||||
heldPositions[position] = true
|
||||
currentlyHeldPosition = position
|
||||
contentLayout.translationX = swipeThresholdPx
|
||||
} else {
|
||||
heldPositions.remove(position)
|
||||
if (currentlyHeldPosition == position) {
|
||||
currentlyHeldPosition = -1
|
||||
}
|
||||
contentLayout.animate()
|
||||
.translationX(0f)
|
||||
.setDuration(300)
|
||||
.start()
|
||||
}
|
||||
rightMenu.addMenuItem(unlinkItem)
|
||||
} else {
|
||||
val deleteItem = SwipeMenuItem(this@LinkedUserActivity).apply {
|
||||
setText(getString(R.string.delete))
|
||||
setBackgroundColor(getColor(R.color.red))
|
||||
setTextColor(getColor(R.color.white))
|
||||
width = 200
|
||||
height = ViewGroup.LayoutParams.MATCH_PARENT
|
||||
}
|
||||
rightMenu.addMenuItem(deleteItem)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getSwipeThreshold(viewHolder: RecyclerView.ViewHolder): Float = 0.05f
|
||||
})
|
||||
itemTouchHelper.attachToRecyclerView(binding.rvLinkedUser)
|
||||
binding.rvLinkedUser.setOnItemMenuClickListener { _, position ->
|
||||
// 直接关闭菜单(使用 RecyclerView 的方法)
|
||||
binding.rvLinkedUser.smoothCloseMenu() // 或 closeMenu()
|
||||
val user = userList[position]
|
||||
showDeleteDialog(user, position)
|
||||
}
|
||||
|
||||
(binding.rvLinkedUser as RecyclerView).adapter = adapter
|
||||
}
|
||||
|
||||
private var currentSwipePosition: Int = -1
|
||||
private var currentSwipeHeld: Boolean = false
|
||||
|
||||
private fun showUnlinkDialog(user: LinkedUser, position: Int) {
|
||||
currentSwipePosition = position
|
||||
currentSwipeHeld = true
|
||||
|
||||
private fun showDeleteDialog(user: LinkedUser, position: Int) {
|
||||
val dialog = CustomDialogFragmentText()
|
||||
if (mode == MODE_SETTINGS) {
|
||||
dialog.setTitle(getString(R.string.tip))
|
||||
@@ -217,22 +134,16 @@ class LinkedUserActivity : AppCompatActivity() {
|
||||
dialog.setMessage(getString(R.string.confirm_delete_user))
|
||||
}
|
||||
dialog.setShowInput(false)
|
||||
dialog.setPositiveText(getString(R.string.confirm))
|
||||
dialog.setNegativeText(getString(R.string.cancel))
|
||||
dialog.setOnConfirmListener {
|
||||
deleteDeviceUser(user, position)
|
||||
}
|
||||
dialog.setOnDismissListener {
|
||||
resetSwipeState()
|
||||
}
|
||||
dialog.show(supportFragmentManager, "UnlinkDialog")
|
||||
dialog.show(supportFragmentManager, "DeleteDialog")
|
||||
}
|
||||
|
||||
private fun deleteDeviceUser(user: LinkedUser, position: Int) {
|
||||
val deviceId = DeviceIdEvent.getDeviceId()
|
||||
if (deviceId.isNullOrEmpty() || user.userId.isEmpty()) {
|
||||
Toast.makeText(this, "参数错误", Toast.LENGTH_SHORT).show()
|
||||
resetSwipeState()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -246,57 +157,45 @@ class LinkedUserActivity : AppCompatActivity() {
|
||||
withContext(Dispatchers.Main) {
|
||||
if (response.code == 200) {
|
||||
userList.removeAt(position)
|
||||
adapter.removeItem(position)
|
||||
adapter.notifyItemRemoved(position) // 通知删除动画
|
||||
adapter.notifyItemRangeChanged(position, userList.size - position) // 更新后续位置索引
|
||||
Toast.makeText(this@LinkedUserActivity, "删除成功", Toast.LENGTH_SHORT).show()
|
||||
} else {
|
||||
Toast.makeText(this@LinkedUserActivity, response.msg, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
resetSwipeState()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
withContext(Dispatchers.Main) {
|
||||
Toast.makeText(this@LinkedUserActivity, "网络请求失败", Toast.LENGTH_SHORT).show()
|
||||
resetSwipeState()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun resetSwipeState() {
|
||||
if (currentSwipePosition >= 0 && currentSwipeHeld) {
|
||||
binding.rvLinkedUser.post {
|
||||
val viewHolder = binding.rvLinkedUser.findViewHolderForAdapterPosition(currentSwipePosition)
|
||||
if (viewHolder is LinkedUserAdapter.LinkedUserViewHolder) {
|
||||
viewHolder.getContentLayout().animate()
|
||||
.translationX(0f)
|
||||
.setDuration(300)
|
||||
.start()
|
||||
}
|
||||
currentSwipePosition = -1
|
||||
currentSwipeHeld = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun initData() {
|
||||
fetchUserList()
|
||||
}
|
||||
|
||||
private fun fetchUserList() {
|
||||
binding.swipeRefresh.isRefreshing = true
|
||||
lifecycleScope.launch {
|
||||
try {
|
||||
val response = if (mode == MODE_SETTINGS) {
|
||||
val deviceId = DeviceIdEvent.getDeviceId()
|
||||
if (deviceId.isNullOrEmpty()) {
|
||||
Toast.makeText(this@LinkedUserActivity, "设备 ID 为空", Toast.LENGTH_SHORT).show()
|
||||
return@launch
|
||||
val deviceId = DeviceIdEvent.getDeviceId()
|
||||
if (deviceId.isNullOrEmpty()) {
|
||||
Toast.makeText(this@LinkedUserActivity, "设备 ID 为空", Toast.LENGTH_SHORT).show()
|
||||
withContext(Dispatchers.Main) {
|
||||
binding.swipeRefresh.isRefreshing = false
|
||||
}
|
||||
return@launch
|
||||
}
|
||||
val response = if (mode == MODE_SETTINGS) {
|
||||
RetrofitNetwork.getNetworkService().getDeviceUserList(deviceId)
|
||||
} else {
|
||||
RetrofitNetwork.getNetworkService().getFamilyMembers()
|
||||
}
|
||||
withContext(Dispatchers.Main) {
|
||||
binding.swipeRefresh.isRefreshing = false
|
||||
if (response.code == 200 && response.data != null) {
|
||||
if (mode == MODE_SETTINGS) {
|
||||
updateDeviceUserList(response.data as List<DeviceUserBean>)
|
||||
@@ -310,6 +209,7 @@ class LinkedUserActivity : AppCompatActivity() {
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
withContext(Dispatchers.Main) {
|
||||
binding.swipeRefresh.isRefreshing = false
|
||||
Toast.makeText(this@LinkedUserActivity, "网络请求失败", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
@@ -398,18 +298,5 @@ class LinkedUserActivity : AppCompatActivity() {
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
if (requestCode == REQUEST_CODE_SEARCH && resultCode == RESULT_OK) {
|
||||
data?.getStringExtra(EXTRA_SEARCH_RESULT)?.let { result ->
|
||||
val newUser = LinkedUser(
|
||||
userId = "",
|
||||
name = result,
|
||||
phone = "13800000000",
|
||||
idCard = "110101199001011234",
|
||||
time = "2026-05-10 ${android.text.format.DateFormat.format("HH:mm:ss", System.currentTimeMillis())}"
|
||||
)
|
||||
userList.add(0, newUser)
|
||||
adapter.submitList(userList)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
118
app/src/main/res/layout-land/linked_user_activity.xml
Normal file
118
app/src/main/res/layout-land/linked_user_activity.xml
Normal file
@@ -0,0 +1,118 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/main"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:background="@color/bg_gray"
|
||||
tools:context=".liveVideo.LinkedUserActivity">
|
||||
|
||||
<!-- 标题栏 -->
|
||||
<LinearLayout
|
||||
android:id="@+id/topBar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="56dp"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:background="@color/white">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivBack"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:src="@drawable/back" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:text="@string/linked_user"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="16dp"
|
||||
android:textStyle="bold" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 搜索区域 -->
|
||||
<LinearLayout
|
||||
android:id="@+id/searchLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/white"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:paddingVertical="12dp"
|
||||
android:layout_marginTop="8dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="40dp"
|
||||
android:background="@drawable/bg_user_manage"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingHorizontal="16dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="18dp"
|
||||
android:layout_height="18dp"
|
||||
android:src="@drawable/search"
|
||||
android:layout_marginRight="8dp"/>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etSearch"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="40dp"
|
||||
android:background="@null"
|
||||
android:hint="@string/search_preset_text"
|
||||
android:textColorHint="@color/gray"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="14sp"
|
||||
android:inputType="text"
|
||||
android:imeOptions="actionSearch"
|
||||
android:singleLine="true"/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
<!-- 列表区域 -->
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
android:id="@+id/swipeRefresh"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1">
|
||||
<com.yanzhenjie.recyclerview.SwipeRecyclerView
|
||||
android:id="@+id/rvLinkedUser"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingBottom="16dp"/>
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
|
||||
<!-- 底部按钮 -->
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:paddingBottom="60dp">
|
||||
|
||||
<android.widget.Button
|
||||
android:id="@+id/btnAddLinkedUser"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="40dp"
|
||||
android:text="@string/add_linked_user"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="14dp"
|
||||
android:background="@drawable/rounded_blue_bg" />
|
||||
<!-- 悬浮加号按钮 -->
|
||||
<ImageView
|
||||
android:visibility="gone"
|
||||
android:layout_gravity="end"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:src="@drawable/add_img"
|
||||
android:id="@+id/fabAdd"/>
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
@@ -68,14 +68,19 @@
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 列表区域 -->
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/rvAddLinkedUser"
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
android:id="@+id/swipeRefresh"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingBottom="16dp"/>
|
||||
android:layout_weight="1">
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/rvAddLinkedUser"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingBottom="16dp"/>
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
|
||||
<!-- 底部按钮 -->
|
||||
<LinearLayout
|
||||
|
||||
@@ -1,86 +1,47 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
android:layout_height="120dp"
|
||||
android:background="@color/white"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<!-- 背景按钮层:删除 + 解除关联 两个按钮 -->
|
||||
<LinearLayout
|
||||
android:id="@+id/llActions"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="120dp"
|
||||
android:gravity="end"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvDeleteAction"
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/red"
|
||||
android:gravity="center"
|
||||
android:text="@string/delete"
|
||||
android:textColor="@color/white"
|
||||
android:id="@+id/tvUserName"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvUnlinkAction"
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/red"
|
||||
android:gravity="center"
|
||||
android:text="@string/unlink"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 前景内容层:随 swipe 移动 -->
|
||||
<LinearLayout
|
||||
android:id="@+id/llContent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="120dp"
|
||||
android:background="@color/white"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvUserName"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvTime"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/gray"
|
||||
android:textSize="12sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvPhone"
|
||||
android:id="@+id/tvTime"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:textColor="@color/gray"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvIdCard"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:textColor="@color/gray"
|
||||
android:textSize="14sp" />
|
||||
android:textSize="12sp" />
|
||||
</LinearLayout>
|
||||
|
||||
</FrameLayout>
|
||||
<TextView
|
||||
android:id="@+id/tvPhone"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:textColor="@color/gray"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvIdCard"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:textColor="@color/gray"
|
||||
android:textSize="14sp" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -73,14 +73,19 @@
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
<!-- 列表区域 -->
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/rvLinkedUser"
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
android:id="@+id/swipeRefresh"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingBottom="16dp"/>
|
||||
android:layout_weight="1">
|
||||
<com.yanzhenjie.recyclerview.SwipeRecyclerView
|
||||
android:id="@+id/rvLinkedUser"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingBottom="16dp"/>
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
|
||||
<!-- 底部按钮 -->
|
||||
<LinearLayout
|
||||
|
||||
Reference in New Issue
Block a user