关联用户列表优化
This commit is contained in:
@@ -102,5 +102,6 @@ dependencies {
|
|||||||
implementation("androidx.camera:camera-view:1.0.0-alpha25")
|
implementation("androidx.camera:camera-view:1.0.0-alpha25")
|
||||||
//上拉刷新下拉加载
|
//上拉刷新下拉加载
|
||||||
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
|
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
|
||||||
|
implementation("com.yanzhenjie.recyclerview:x:1.3.2")
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -5,7 +5,6 @@ import android.view.View
|
|||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.example.defenseapplication.databinding.ItemLinkedUserBinding
|
import com.example.defenseapplication.databinding.ItemLinkedUserBinding
|
||||||
import com.example.defenseapplication.view.SlideLayout
|
|
||||||
|
|
||||||
data class LinkedUser(
|
data class LinkedUser(
|
||||||
val userId: String,
|
val userId: String,
|
||||||
@@ -16,18 +15,11 @@ data class LinkedUser(
|
|||||||
)
|
)
|
||||||
|
|
||||||
class LinkedUserAdapter(
|
class LinkedUserAdapter(
|
||||||
private val deleteText: String,
|
|
||||||
private val isUnlinkMode: Boolean,
|
private val isUnlinkMode: Boolean,
|
||||||
private val onItemClick: (LinkedUser, Int) -> Unit,
|
private val onItemClick: (LinkedUser, Int) -> Unit
|
||||||
private val onDeleteClick: (LinkedUser, Int) -> Unit
|
|
||||||
) : RecyclerView.Adapter<LinkedUserAdapter.LinkedUserViewHolder>() {
|
) : RecyclerView.Adapter<LinkedUserAdapter.LinkedUserViewHolder>() {
|
||||||
|
|
||||||
private val items = mutableListOf<LinkedUser>()
|
private val items = mutableListOf<LinkedUser>()
|
||||||
private var _openSlideLayout: SlideLayout? = null
|
|
||||||
|
|
||||||
/** 供外部(如 Activity)访问当前展开的 SlideLayout */
|
|
||||||
val openSlideLayout: SlideLayout?
|
|
||||||
get() = _openSlideLayout
|
|
||||||
|
|
||||||
fun submitList(userList: List<LinkedUser>) {
|
fun submitList(userList: List<LinkedUser>) {
|
||||||
items.clear()
|
items.clear()
|
||||||
@@ -52,54 +44,7 @@ class LinkedUserAdapter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onBindViewHolder(holder: LinkedUserViewHolder, position: Int) {
|
override fun onBindViewHolder(holder: LinkedUserViewHolder, position: Int) {
|
||||||
val item = items[position]
|
holder.bind(items[position], position)
|
||||||
holder.bind(item)
|
|
||||||
|
|
||||||
// 每次 bind 都设置监听器,RecyclerView 复用视图时也会调用
|
|
||||||
val slideLayout = holder.itemView as SlideLayout
|
|
||||||
slideLayout.setOnSlideChangeListener(object : SlideLayout.OnSlideChangeListener {
|
|
||||||
override fun onMenuOpen(slideLayout: SlideLayout) {
|
|
||||||
val prev = _openSlideLayout
|
|
||||||
if (prev != null && prev != slideLayout) {
|
|
||||||
prev.closeMenu()
|
|
||||||
}
|
|
||||||
_openSlideLayout = slideLayout
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onMenuClose(slideLayout: SlideLayout) {
|
|
||||||
if (_openSlideLayout == slideLayout) {
|
|
||||||
_openSlideLayout = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onClick(slideLayout: SlideLayout) {
|
|
||||||
val prev = _openSlideLayout
|
|
||||||
if (prev != null && prev != slideLayout) {
|
|
||||||
prev.closeMenu()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
holder.binding.llContent.setOnClickListener {
|
|
||||||
val pos = holder.bindingAdapterPosition
|
|
||||||
if (pos != RecyclerView.NO_POSITION) {
|
|
||||||
onItemClick(items[pos], pos)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
holder.binding.tvDeleteAction.setOnClickListener {
|
|
||||||
val pos = holder.bindingAdapterPosition
|
|
||||||
if (pos != RecyclerView.NO_POSITION) {
|
|
||||||
onDeleteClick(items[pos], pos)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
holder.binding.tvUnlinkAction.setOnClickListener {
|
|
||||||
val pos = holder.bindingAdapterPosition
|
|
||||||
if (pos != RecyclerView.NO_POSITION) {
|
|
||||||
onDeleteClick(items[pos], pos)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getItemCount(): Int = items.size
|
override fun getItemCount(): Int = items.size
|
||||||
@@ -108,19 +53,14 @@ class LinkedUserAdapter(
|
|||||||
val binding: ItemLinkedUserBinding
|
val binding: ItemLinkedUserBinding
|
||||||
) : RecyclerView.ViewHolder(binding.root) {
|
) : RecyclerView.ViewHolder(binding.root) {
|
||||||
|
|
||||||
fun bind(item: LinkedUser) {
|
fun bind(item: LinkedUser, position: Int) {
|
||||||
binding.tvUserName.text = item.name
|
binding.tvUserName.text = item.name
|
||||||
binding.tvTime.text = item.time
|
binding.tvTime.text = item.time
|
||||||
binding.tvPhone.text = "手机号码:${item.phone}"
|
binding.tvPhone.text = "手机号码:${item.phone}"
|
||||||
binding.tvIdCard.text = "身份证号:${item.idCard}"
|
binding.tvIdCard.text = "身份证号:${item.idCard}"
|
||||||
|
|
||||||
if (isUnlinkMode) {
|
binding.root.setOnClickListener {
|
||||||
binding.tvUnlinkAction.visibility = View.VISIBLE
|
onItemClick(item, position)
|
||||||
binding.tvDeleteAction.visibility = View.GONE
|
|
||||||
} else {
|
|
||||||
binding.tvUnlinkAction.visibility = View.GONE
|
|
||||||
binding.tvDeleteAction.visibility = View.VISIBLE
|
|
||||||
binding.tvDeleteAction.text = deleteText
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import android.os.Bundle
|
|||||||
import android.text.Editable
|
import android.text.Editable
|
||||||
import android.text.TextWatcher
|
import android.text.TextWatcher
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
@@ -22,10 +23,12 @@ import com.example.defenseapplication.utils.DeviceUserUpdateEvent
|
|||||||
import com.example.defenseapplication.utils.RetrofitNetwork
|
import com.example.defenseapplication.utils.RetrofitNetwork
|
||||||
import com.example.defenseapplication.view.CustomDialogFragmentText
|
import com.example.defenseapplication.view.CustomDialogFragmentText
|
||||||
import com.gyf.immersionbar.ImmersionBar
|
import com.gyf.immersionbar.ImmersionBar
|
||||||
|
import com.yanzhenjie.recyclerview.SwipeMenuItem
|
||||||
|
import com.yanzhenjie.recyclerview.SwipeRecyclerView
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
//关联用户页面
|
|
||||||
class LinkedUserActivity : AppCompatActivity() {
|
class LinkedUserActivity : AppCompatActivity() {
|
||||||
|
|
||||||
private lateinit var binding: LinkedUserActivityBinding
|
private lateinit var binding: LinkedUserActivityBinding
|
||||||
@@ -35,8 +38,6 @@ class LinkedUserActivity : AppCompatActivity() {
|
|||||||
private var mode: Int = MODE_SETTINGS
|
private var mode: Int = MODE_SETTINGS
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val REQUEST_CODE_SEARCH = 1001
|
|
||||||
const val EXTRA_SEARCH_RESULT = "search_result"
|
|
||||||
const val EXTRA_MODE = "extra_mode"
|
const val EXTRA_MODE = "extra_mode"
|
||||||
const val MODE_SETTINGS = 0
|
const val MODE_SETTINGS = 0
|
||||||
const val MODE_PERSONAL = 1
|
const val MODE_PERSONAL = 1
|
||||||
@@ -73,45 +74,57 @@ class LinkedUserActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun initView() {
|
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(
|
adapter = LinkedUserAdapter(
|
||||||
deleteText = deleteText,
|
isUnlinkMode = mode == MODE_SETTINGS,
|
||||||
isUnlinkMode = isUnlinkMode,
|
|
||||||
onItemClick = { user, position ->
|
onItemClick = { user, position ->
|
||||||
val intent = Intent(this, UserDetailsActivity::class.java).apply {
|
val intent = Intent(this, UserDetailsActivity::class.java).apply {
|
||||||
putExtra("userId", user.userId)
|
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)
|
startActivity(intent)
|
||||||
},
|
|
||||||
onDeleteClick = { user, position ->
|
|
||||||
showUnlinkDialog(user, position)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
binding.rvLinkedUser.layoutManager = LinearLayoutManager(this)
|
|
||||||
binding.rvLinkedUser.adapter = adapter
|
(binding.rvLinkedUser as RecyclerView).layoutManager = LinearLayoutManager(this)
|
||||||
|
|
||||||
binding.swipeRefresh.setOnRefreshListener {
|
binding.swipeRefresh.setOnRefreshListener {
|
||||||
fetchUserList()
|
fetchUserList()
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.rvLinkedUser.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
binding.rvLinkedUser.setSwipeMenuCreator { leftMenu, rightMenu, position ->
|
||||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
if (mode == MODE_SETTINGS) {
|
||||||
super.onScrolled(recyclerView, dx, dy)
|
val unlinkItem = SwipeMenuItem(this@LinkedUserActivity).apply {
|
||||||
val layoutManager = recyclerView.layoutManager as LinearLayoutManager
|
setText(getString(R.string.unlink))
|
||||||
val totalItemCount = layoutManager.itemCount
|
setBackgroundColor(getColor(R.color.red))
|
||||||
val lastVisibleItem = layoutManager.findLastVisibleItemPosition()
|
setTextColor(getColor(R.color.white))
|
||||||
if (totalItemCount > 0 && lastVisibleItem >= totalItemCount - 3) {
|
width = 200
|
||||||
if (!binding.swipeRefresh.isRefreshing) {
|
height = ViewGroup.LayoutParams.MATCH_PARENT
|
||||||
fetchUserList()
|
|
||||||
}
|
}
|
||||||
|
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)
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showUnlinkDialog(user: LinkedUser, position: Int) {
|
binding.rvLinkedUser.setOnItemMenuClickListener { _, position ->
|
||||||
|
// 直接关闭菜单(使用 RecyclerView 的方法)
|
||||||
|
binding.rvLinkedUser.smoothCloseMenu() // 或 closeMenu()
|
||||||
|
val user = userList[position]
|
||||||
|
showDeleteDialog(user, position)
|
||||||
|
}
|
||||||
|
|
||||||
|
(binding.rvLinkedUser as RecyclerView).adapter = adapter
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showDeleteDialog(user: LinkedUser, position: Int) {
|
||||||
val dialog = CustomDialogFragmentText()
|
val dialog = CustomDialogFragmentText()
|
||||||
if (mode == MODE_SETTINGS) {
|
if (mode == MODE_SETTINGS) {
|
||||||
dialog.setTitle(getString(R.string.tip))
|
dialog.setTitle(getString(R.string.tip))
|
||||||
@@ -121,18 +134,10 @@ class LinkedUserActivity : AppCompatActivity() {
|
|||||||
dialog.setMessage(getString(R.string.confirm_delete_user))
|
dialog.setMessage(getString(R.string.confirm_delete_user))
|
||||||
}
|
}
|
||||||
dialog.setShowInput(false)
|
dialog.setShowInput(false)
|
||||||
dialog.setPositiveText(getString(R.string.confirm))
|
|
||||||
dialog.setNegativeText(getString(R.string.cancel))
|
|
||||||
dialog.setOnConfirmListener {
|
dialog.setOnConfirmListener {
|
||||||
deleteDeviceUser(user, position)
|
deleteDeviceUser(user, position)
|
||||||
}
|
}
|
||||||
dialog.setOnDismissListener {
|
dialog.show(supportFragmentManager, "DeleteDialog")
|
||||||
// Dialog 关闭后,如果之前打开了菜单则关闭它
|
|
||||||
if (adapter.openSlideLayout != null) {
|
|
||||||
adapter.openSlideLayout?.closeMenu()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dialog.show(supportFragmentManager, "UnlinkDialog")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun deleteDeviceUser(user: LinkedUser, position: Int) {
|
private fun deleteDeviceUser(user: LinkedUser, position: Int) {
|
||||||
@@ -152,7 +157,8 @@ class LinkedUserActivity : AppCompatActivity() {
|
|||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
if (response.code == 200) {
|
if (response.code == 200) {
|
||||||
userList.removeAt(position)
|
userList.removeAt(position)
|
||||||
adapter.removeItem(position)
|
adapter.notifyItemRemoved(position) // 通知删除动画
|
||||||
|
adapter.notifyItemRangeChanged(position, userList.size - position) // 更新后续位置索引
|
||||||
Toast.makeText(this@LinkedUserActivity, "删除成功", Toast.LENGTH_SHORT).show()
|
Toast.makeText(this@LinkedUserActivity, "删除成功", Toast.LENGTH_SHORT).show()
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(this@LinkedUserActivity, response.msg, Toast.LENGTH_SHORT).show()
|
Toast.makeText(this@LinkedUserActivity, response.msg, Toast.LENGTH_SHORT).show()
|
||||||
@@ -175,12 +181,15 @@ class LinkedUserActivity : AppCompatActivity() {
|
|||||||
binding.swipeRefresh.isRefreshing = true
|
binding.swipeRefresh.isRefreshing = true
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
try {
|
try {
|
||||||
val response = if (mode == MODE_SETTINGS) {
|
|
||||||
val deviceId = DeviceIdEvent.getDeviceId()
|
val deviceId = DeviceIdEvent.getDeviceId()
|
||||||
if (deviceId.isNullOrEmpty()) {
|
if (deviceId.isNullOrEmpty()) {
|
||||||
Toast.makeText(this@LinkedUserActivity, "设备 ID 为空", Toast.LENGTH_SHORT).show()
|
Toast.makeText(this@LinkedUserActivity, "设备 ID 为空", Toast.LENGTH_SHORT).show()
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
binding.swipeRefresh.isRefreshing = false
|
||||||
|
}
|
||||||
return@launch
|
return@launch
|
||||||
}
|
}
|
||||||
|
val response = if (mode == MODE_SETTINGS) {
|
||||||
RetrofitNetwork.getNetworkService().getDeviceUserList(deviceId)
|
RetrofitNetwork.getNetworkService().getDeviceUserList(deviceId)
|
||||||
} else {
|
} else {
|
||||||
RetrofitNetwork.getNetworkService().getFamilyMembers()
|
RetrofitNetwork.getNetworkService().getFamilyMembers()
|
||||||
@@ -289,18 +298,5 @@ class LinkedUserActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||||
super.onActivityResult(requestCode, resultCode, data)
|
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,176 +0,0 @@
|
|||||||
package com.example.defenseapplication.view
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.util.AttributeSet
|
|
||||||
import android.view.MotionEvent
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewParent
|
|
||||||
import android.widget.FrameLayout
|
|
||||||
import android.widget.OverScroller
|
|
||||||
|
|
||||||
class SlideLayout @JvmOverloads constructor(
|
|
||||||
context: Context,
|
|
||||||
attrs: AttributeSet? = null,
|
|
||||||
defStyleAttr: Int = 0
|
|
||||||
) : FrameLayout(context, attrs, defStyleAttr) {
|
|
||||||
|
|
||||||
private val scroller = OverScroller(context)
|
|
||||||
|
|
||||||
private var downX: Float = 0f
|
|
||||||
private var downY: Float = 0f
|
|
||||||
private var lastX: Float = 0f
|
|
||||||
|
|
||||||
private var isHorizontalDragging: Boolean = false
|
|
||||||
|
|
||||||
private var listener: OnSlideChangeListener? = null
|
|
||||||
private var shouldMenuBeOpen: Boolean = false
|
|
||||||
|
|
||||||
/** 缓存菜单宽度,避免 RecyclerView 复用时 measuredWidth 读取不到 */
|
|
||||||
private var cachedMenuWidth: Int = 0
|
|
||||||
|
|
||||||
interface OnSlideChangeListener {
|
|
||||||
fun onMenuOpen(slideLayout: SlideLayout)
|
|
||||||
fun onMenuClose(slideLayout: SlideLayout)
|
|
||||||
fun onClick(slideLayout: SlideLayout)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setOnSlideChangeListener(listener: OnSlideChangeListener) {
|
|
||||||
this.listener = listener
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
|
||||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
|
|
||||||
// 缓存菜单宽度,在 onLayout 和 onTouchEvent 中使用
|
|
||||||
cachedMenuWidth = if (childCount >= 2) getChildAt(0).measuredWidth else 0
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getMenuWidth(): Int {
|
|
||||||
// 优先使用缓存值,RecyclerView 复用时 measuredWidth 可能尚未更新
|
|
||||||
val w = cachedMenuWidth
|
|
||||||
return if (w > 0) w else {
|
|
||||||
if (childCount >= 2) {
|
|
||||||
val measured = getChildAt(0).measuredWidth
|
|
||||||
if (measured > 0) measured else getChildAt(0).width
|
|
||||||
} else 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
|
|
||||||
super.onLayout(changed, left, top, right, bottom)
|
|
||||||
if (childCount < 2) return
|
|
||||||
val contentWidth = right - left
|
|
||||||
val menu = getChildAt(0)
|
|
||||||
val menuW = getMenuWidth()
|
|
||||||
// 内容左移 scrollX → 菜单右边缘逐渐露出
|
|
||||||
// 菜单左边界 = 内容右边缘 - scrollX
|
|
||||||
menu.layout(contentWidth - scrollX, top, contentWidth - scrollX + menuW, bottom)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
|
|
||||||
when (ev.action) {
|
|
||||||
MotionEvent.ACTION_DOWN -> {
|
|
||||||
downX = ev.x
|
|
||||||
downY = ev.y
|
|
||||||
lastX = ev.x
|
|
||||||
isHorizontalDragging = false
|
|
||||||
}
|
|
||||||
MotionEvent.ACTION_MOVE -> {
|
|
||||||
val dx = Math.abs(ev.x - downX)
|
|
||||||
val dy = Math.abs(ev.y - downY)
|
|
||||||
if (dx > dy && dx > 10f) {
|
|
||||||
isHorizontalDragging = true
|
|
||||||
disallowInterceptChain(true)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return super.onInterceptTouchEvent(ev)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onTouchEvent(event: MotionEvent): Boolean {
|
|
||||||
when (event.action) {
|
|
||||||
MotionEvent.ACTION_DOWN -> {
|
|
||||||
downX = event.x
|
|
||||||
downY = event.y
|
|
||||||
lastX = event.x
|
|
||||||
disallowInterceptChain(true)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
MotionEvent.ACTION_MOVE -> {
|
|
||||||
val dx = lastX - event.x
|
|
||||||
lastX = event.x
|
|
||||||
|
|
||||||
if (Math.abs(event.x - downX) > 10f) {
|
|
||||||
isHorizontalDragging = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isHorizontalDragging) {
|
|
||||||
val menuW = getMenuWidth()
|
|
||||||
var newScrollX = scrollX + dx.toInt()
|
|
||||||
if (newScrollX < 0) newScrollX = 0
|
|
||||||
if (newScrollX > menuW) newScrollX = menuW
|
|
||||||
scrollTo(newScrollX, 0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MotionEvent.ACTION_UP -> {
|
|
||||||
val wasDragging = isHorizontalDragging
|
|
||||||
isHorizontalDragging = false
|
|
||||||
disallowInterceptChain(false)
|
|
||||||
|
|
||||||
if (!wasDragging) {
|
|
||||||
listener?.onClick(this)
|
|
||||||
} else {
|
|
||||||
val menuW = getMenuWidth()
|
|
||||||
if (scrollX > menuW / 2) {
|
|
||||||
openMenu()
|
|
||||||
} else {
|
|
||||||
closeMenu()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MotionEvent.ACTION_CANCEL -> {
|
|
||||||
isHorizontalDragging = false
|
|
||||||
disallowInterceptChain(false)
|
|
||||||
// 弹窗等外部中断:按当前菜单是否露出状态决定动画关闭或保持关闭
|
|
||||||
if (scrollX > 0) {
|
|
||||||
closeMenu()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun disallowInterceptChain(disallow: Boolean) {
|
|
||||||
var parent: ViewParent? = parent
|
|
||||||
while (parent != null) {
|
|
||||||
parent.requestDisallowInterceptTouchEvent(disallow)
|
|
||||||
parent = parent.parent
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun computeScroll() {
|
|
||||||
if (scroller.computeScrollOffset()) {
|
|
||||||
scrollTo(scroller.currX, scroller.currY)
|
|
||||||
postInvalidateOnAnimation()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun openMenu() {
|
|
||||||
val menuW = getMenuWidth()
|
|
||||||
if (shouldMenuBeOpen && scrollX == menuW) return
|
|
||||||
shouldMenuBeOpen = true
|
|
||||||
scroller.startScroll(scrollX, 0, menuW - scrollX, 0, 300)
|
|
||||||
postInvalidateOnAnimation()
|
|
||||||
listener?.onMenuOpen(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun closeMenu() {
|
|
||||||
if (!shouldMenuBeOpen && scrollX == 0) return
|
|
||||||
shouldMenuBeOpen = false
|
|
||||||
scroller.startScroll(scrollX, 0, -scrollX, 0, 300)
|
|
||||||
postInvalidateOnAnimation()
|
|
||||||
listener?.onMenuClose(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isMenuOpened(): Boolean = shouldMenuBeOpen
|
|
||||||
}
|
|
||||||
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>
|
||||||
@@ -1,43 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<com.example.defenseapplication.view.SlideLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
|
|
||||||
<!-- 背景按钮层:删除 + 解除关联 两个按钮 -->
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/llActions"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="120dp"
|
|
||||||
android:gravity="start|center_vertical"
|
|
||||||
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: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_width="match_parent"
|
||||||
android:layout_height="120dp"
|
android:layout_height="120dp"
|
||||||
android:background="@color/white"
|
android:background="@color/white"
|
||||||
@@ -81,6 +43,5 @@
|
|||||||
android:layout_marginTop="4dp"
|
android:layout_marginTop="4dp"
|
||||||
android:textColor="@color/gray"
|
android:textColor="@color/gray"
|
||||||
android:textSize="14sp" />
|
android:textSize="14sp" />
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</com.example.defenseapplication.view.SlideLayout>
|
</LinearLayout>
|
||||||
@@ -78,7 +78,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:layout_weight="1">
|
android:layout_weight="1">
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<com.yanzhenjie.recyclerview.SwipeRecyclerView
|
||||||
android:id="@+id/rvLinkedUser"
|
android:id="@+id/rvLinkedUser"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
|||||||
Reference in New Issue
Block a user