关联用户2

This commit is contained in:
2026-05-20 16:30:24 +08:00
parent 133ea5a88b
commit 246b39ca1a
15 changed files with 254 additions and 172 deletions

View File

@@ -6,6 +6,7 @@ import bean.LoginBean
import com.blankj.utilcode.util.Utils import com.blankj.utilcode.util.Utils
import com.example.defenseapplication.bean.BaseInfo import com.example.defenseapplication.bean.BaseInfo
import com.example.defenseapplication.utils.ApiConfig import com.example.defenseapplication.utils.ApiConfig
import com.example.defenseapplication.utils.LanguageHeaderManager
import com.example.defenseapplication.utils.LanguageUtil import com.example.defenseapplication.utils.LanguageUtil
import com.example.defenseapplication.utils.UserinfoUtil import com.example.defenseapplication.utils.UserinfoUtil
import com.google.gson.Gson import com.google.gson.Gson

View File

@@ -1,25 +1,36 @@
package com.example.defenseapplication.adapter package com.example.defenseapplication.adapter
import android.graphics.Color
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.ViewGroup import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.example.defenseapplication.R
import com.example.defenseapplication.databinding.ItemAddLinkedUserBinding import com.example.defenseapplication.databinding.ItemAddLinkedUserBinding
data class UserItem(val name: String, val phone: String) data class UserItem(val name: String, val phone: String, val userId: String = "")
class AddLinkedUserAdapter( class AddLinkedUserAdapter(
private val data: List<UserItem>, private val data: List<UserItem>,
private val selectedIds: MutableSet<String>, private val selectedIds: MutableSet<String>,
private val onItemClick: (String, Boolean) -> Unit private val selectedUserIdMap: MutableMap<String, String>,
private val onItemClick: (String, Boolean, String?) -> Unit
) : RecyclerView.Adapter<AddLinkedUserAdapter.ViewHolder>() { ) : RecyclerView.Adapter<AddLinkedUserAdapter.ViewHolder>() {
inner class ViewHolder(val binding: ItemAddLinkedUserBinding) : RecyclerView.ViewHolder(binding.root) { inner class ViewHolder(val binding: ItemAddLinkedUserBinding) : RecyclerView.ViewHolder(binding.root) {
fun bind(item: UserItem) { fun bind(item: UserItem) {
binding.tvUserName.text = "${item.name}-${item.phone}" binding.tvUserName.text = "${item.name}-${item.phone}"
binding.cbSelect.isChecked = selectedIds.contains(item.phone) val isChecked = selectedIds.contains(item.phone)
binding.cbSelect.setOnClickListener { binding.cbSelect.isChecked = isChecked
val isChecked = binding.cbSelect.isChecked binding.cbSelect.setOnCheckedChangeListener { _, checked ->
onItemClick(item.phone, isChecked) if (checked) {
binding.cbSelect.buttonTintList = android.content.res.ColorStateList.valueOf(Color.parseColor("#09C2BD"))
} else {
binding.cbSelect.buttonTintList = null
}
onItemClick(item.phone, checked, item.userId)
}
if (isChecked) {
binding.cbSelect.buttonTintList = android.content.res.ColorStateList.valueOf(Color.parseColor("#09C2BD"))
} }
} }
} }

View File

@@ -56,10 +56,10 @@ class LinkedUserAdapter(
) : RecyclerView.ViewHolder(binding.root) { ) : RecyclerView.ViewHolder(binding.root) {
fun bind(item: LinkedUser, position: Int) { fun bind(item: LinkedUser, position: Int) {
binding.tvPhone.text ="手机号码:${item.phone}"
binding.tvIdCard.text ="身份证号:${item.idCard}"
binding.llContent.translationX = 0f binding.llContent.translationX = 0f
binding.tvUserName.text = item.name binding.tvUserName.text = item.name
binding.tvPhone.text = "手机号码:${item.phone}"
binding.tvIdCard.text = "身份证号:${item.idCard}"
binding.tvTime.text = item.time binding.tvTime.text = item.time
//设置删除按钮的文字 //设置删除按钮的文字
binding.tvDeleteAction.text = deleteText binding.tvDeleteAction.text = deleteText

View File

@@ -0,0 +1,8 @@
package com.example.defenseapplication.bean
data class AddDeviceUserRequest(
val deviceId: String,
val deviceNo: String? = null,
val deviceName: String? = null,
val userId: String
)

View File

@@ -1,9 +1,9 @@
package com.example.defenseapplication.bean package com.example.defenseapplication.bean
data class DeviceUserBean( data class DeviceUserBean(
val createDept: String? = null, //创建部门 val createDept: Int ? = null, //创建部门
val createBy: String? = null, //创建人 val createBy: Int? = null, //创建人
val updateBy: String? = null, //更新者 val updateBy: Int? = null, //更新者
val updateTime: String? = null, //更新时间 val updateTime: String? = null, //更新时间
val paramskeykey: String? = null, val paramskeykey: String? = null,
val deviceId: String? = null, // 设备 ID val deviceId: String? = null, // 设备 ID

View File

@@ -0,0 +1,20 @@
package com.example.defenseapplication.bean
data class FamilyMembersBean(
val id: String? = null, // ID
val parentId: String? = null, // 家长 id
val parentName: String? = null, // 家长昵称
val userId: String? = null, // 成员 id
val nickName: String? = null, // 成员昵称
val idCard: String? = null, // 身份证号
val phonenumber: String? = null, // 手机号码
val status: String? = null, // 账号状态0 正常 1 停用)
val role: String? = null, // 角色
val createTime: String? = null, // 创建时间
val inviteCode: String? = null, // 邀请码
val createDept: Int? = null, // 创建部门
val createBy: Int? = null, // 创建人
val updateBy: Int? = null, // 更新者
val updateTime: String? = null, // 更新时间
val paramskeykey: String? = null
)

View File

@@ -3,16 +3,27 @@ package com.example.defenseapplication.liveVideo
import android.os.Bundle import android.os.Bundle
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.example.defenseapplication.R import com.example.defenseapplication.R
import com.example.defenseapplication.adapter.AddLinkedUserAdapter import com.example.defenseapplication.adapter.AddLinkedUserAdapter
import com.example.defenseapplication.adapter.UserItem import com.example.defenseapplication.adapter.UserItem
import com.example.defenseapplication.bean.AddDeviceUserRequest
import com.example.defenseapplication.bean.FamilyMembersBean
import com.example.defenseapplication.databinding.AddLinkedUserActivityBinding import com.example.defenseapplication.databinding.AddLinkedUserActivityBinding
import com.example.defenseapplication.utils.DeviceIdEvent
import com.example.defenseapplication.utils.DeviceUserUpdateEvent
import com.example.defenseapplication.utils.RetrofitNetwork
import com.gyf.immersionbar.ImmersionBar import com.gyf.immersionbar.ImmersionBar
//添加关联用户 import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
class AddLinkedUserActivity : AppCompatActivity() { class AddLinkedUserActivity : AppCompatActivity() {
private lateinit var binding: AddLinkedUserActivityBinding private lateinit var binding: AddLinkedUserActivityBinding
private val selectedPhoneSet = mutableSetOf<String>() private val selectedPhoneSet = mutableSetOf<String>()
private val userItemList = mutableListOf<UserItem>()
private val selectedUserIdMap = mutableMapOf<String, String>()
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@@ -26,36 +37,112 @@ class AddLinkedUserActivity : AppCompatActivity() {
initRecyclerView() initRecyclerView()
initListener() initListener()
fetchFamilyMembers()
} }
private fun initRecyclerView() { private fun initRecyclerView() {
val mockData = listOf(
UserItem("王五", "13566666666"),
UserItem("赵六", "15733333333")
)
binding.rvAddLinkedUser.layoutManager = LinearLayoutManager(this) binding.rvAddLinkedUser.layoutManager = LinearLayoutManager(this)
binding.rvAddLinkedUser.adapter = binding.rvAddLinkedUser.adapter =
AddLinkedUserAdapter(mockData, selectedPhoneSet) { phone, isChecked -> AddLinkedUserAdapter(userItemList, selectedPhoneSet, selectedUserIdMap) { phone, isChecked, userId ->
if (isChecked) { if (isChecked) {
selectedPhoneSet.add(phone) selectedPhoneSet.add(phone)
userId?.let { selectedUserIdMap[phone] = it }
} else { } else {
selectedPhoneSet.remove(phone) selectedPhoneSet.remove(phone)
selectedUserIdMap.remove(phone)
} }
} }
} }
private fun fetchFamilyMembers() {
lifecycleScope.launch {
try {
val response = RetrofitNetwork.getNetworkService().getFamilyMembers()
withContext(Dispatchers.Main) {
if (response.code == 200) {
if (response.data != null && response.data.isNotEmpty()) {
updateFamilyMemberList(response.data)
} else {
Toast.makeText(this@AddLinkedUserActivity, "暂无家庭成员数据", Toast.LENGTH_SHORT).show()
}
} else {
Toast.makeText(this@AddLinkedUserActivity, "请求失败: ${response.msg}", Toast.LENGTH_SHORT).show()
}
}
} catch (e: Exception) {
android.util.Log.e("AddLinkedUserActivity", "网络请求异常", e)
withContext(Dispatchers.Main) {
Toast.makeText(this@AddLinkedUserActivity, "网络请求失败: ${e.message}", Toast.LENGTH_SHORT).show()
}
}
}
}
private fun updateFamilyMemberList(familyMembersList: List<FamilyMembersBean>) {
userItemList.clear()
familyMembersList.forEach { member ->
userItemList.add(
UserItem(
name = member.nickName ?: member.parentName ?: "未知用户",
phone = member.phonenumber ?: "",
userId = member.userId ?: ""
)
)
}
binding.rvAddLinkedUser.adapter?.notifyDataSetChanged()
}
private fun initListener() { private fun initListener() {
binding.btnAddLinkedUser.setOnClickListener { binding.btnAddLinkedUser.setOnClickListener {
if (selectedPhoneSet.isEmpty()) { if (selectedPhoneSet.isEmpty()) {
Toast.makeText(this, getString(R.string.please_select_at_least_one_user), Toast.LENGTH_SHORT).show() Toast.makeText(this, getString(R.string.please_select_at_least_one_user), Toast.LENGTH_SHORT).show()
} else { } else {
val message = getString(R.string.selected_users_voice, selectedPhoneSet.size) addDeviceUser()
Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
} }
} }
binding.ivBack.setOnClickListener { binding.ivBack.setOnClickListener {
finish() finish()
} }
} }
private fun addDeviceUser() {
val deviceId = DeviceIdEvent.getDeviceId()
if (deviceId.isNullOrEmpty()) {
Toast.makeText(this, "设备ID为空", Toast.LENGTH_SHORT).show()
return
}
lifecycleScope.launch {
var successCount = 0
for ((phone, userId) in selectedUserIdMap) {
try {
val request = AddDeviceUserRequest(
deviceId = deviceId,
userId = userId
)
val response = RetrofitNetwork.getNetworkService().addDeviceUser(request)
withContext(Dispatchers.Main) {
if (response.code == 200) {
successCount++
} else {
Toast.makeText(this@AddLinkedUserActivity, "添加用户 $phone 失败: ${response.msg}", Toast.LENGTH_SHORT).show()
}
}
} catch (e: Exception) {
e.printStackTrace()
withContext(Dispatchers.Main) {
Toast.makeText(this@AddLinkedUserActivity, "添加用户 $phone 失败: 网络错误", Toast.LENGTH_SHORT).show()
}
}
}
withContext(Dispatchers.Main) {
if (successCount > 0) {
Toast.makeText(this@AddLinkedUserActivity, "成功添加 $successCount 个用户", Toast.LENGTH_SHORT).show()
DeviceUserUpdateEvent.notifyUpdate()
finish()
}
}
}
}
} }

View File

@@ -15,8 +15,10 @@ import com.example.defenseapplication.adapter.LinkedUser
import com.example.defenseapplication.adapter.LinkedUserAdapter import com.example.defenseapplication.adapter.LinkedUserAdapter
import com.example.defenseapplication.bean.DeleteDeviceUserRequest import com.example.defenseapplication.bean.DeleteDeviceUserRequest
import com.example.defenseapplication.bean.DeviceUserBean import com.example.defenseapplication.bean.DeviceUserBean
import com.example.defenseapplication.bean.FamilyMembersBean
import com.example.defenseapplication.databinding.LinkedUserActivityBinding import com.example.defenseapplication.databinding.LinkedUserActivityBinding
import com.example.defenseapplication.utils.DeviceIdEvent import com.example.defenseapplication.utils.DeviceIdEvent
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
@@ -55,6 +57,18 @@ class LinkedUserActivity : AppCompatActivity() {
initData() initData()
initListener() initListener()
setupModeUI() setupModeUI()
DeviceUserUpdateEvent.addListener(deviceUserUpdateListener)
}
private val deviceUserUpdateListener = object : DeviceUserUpdateEvent.DeviceUserUpdateListener {
override fun onDeviceUserUpdated() {
fetchUserList()
}
}
override fun onDestroy() {
super.onDestroy()
DeviceUserUpdateEvent.removeListener(deviceUserUpdateListener)
} }
private fun initView() { private fun initView() {
@@ -222,22 +236,29 @@ class LinkedUserActivity : AppCompatActivity() {
} }
private fun initData() { private fun initData() {
fetchDeviceUserList() fetchUserList()
} }
private fun fetchDeviceUserList() { private fun fetchUserList() {
val deviceId = DeviceIdEvent.getDeviceId()
if (deviceId.isNullOrEmpty()) {
Toast.makeText(this, "设备 ID 为空", Toast.LENGTH_SHORT).show()
return
}
lifecycleScope.launch { lifecycleScope.launch {
try { try {
val response = RetrofitNetwork.getNetworkService().getDeviceUserList(deviceId) val response = if (mode == MODE_SETTINGS) {
val deviceId = DeviceIdEvent.getDeviceId()
if (deviceId.isNullOrEmpty()) {
Toast.makeText(this@LinkedUserActivity, "设备 ID 为空", Toast.LENGTH_SHORT).show()
return@launch
}
RetrofitNetwork.getNetworkService().getDeviceUserList(deviceId)
} else {
RetrofitNetwork.getNetworkService().getFamilyMembers()
}
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
if (response.code == 200 && response.data != null) { if (response.code == 200 && response.data != null) {
updateDeviceUserList(response.data) if (mode == MODE_SETTINGS) {
updateDeviceUserList(response.data as List<DeviceUserBean>)
} else {
updateFamilyMembersList(response.data as List<FamilyMembersBean>)
}
} else { } else {
Toast.makeText(this@LinkedUserActivity, response.msg, Toast.LENGTH_SHORT).show() Toast.makeText(this@LinkedUserActivity, response.msg, Toast.LENGTH_SHORT).show()
} }
@@ -267,14 +288,29 @@ class LinkedUserActivity : AppCompatActivity() {
adapter.submitList(userList) adapter.submitList(userList)
} }
private fun updateFamilyMembersList(familyMembersList: List<FamilyMembersBean>) {
userList.clear()
familyMembersList.forEach { member ->
userList.add(
LinkedUser(
userId = member.userId ?: "",
name = member.nickName ?: member.parentName ?: "未知用户",
phone = member.phonenumber ?: "",
idCard = member.idCard ?: "",
time = member.createTime ?: ""
)
)
}
adapter.submitList(userList)
}
private fun initListener() { private fun initListener() {
binding.ivBack.setOnClickListener { binding.ivBack.setOnClickListener {
finish() finish()
} }
binding.searchLayout.setOnClickListener { binding.searchLayout.setOnClickListener {
val intent = Intent(this, LinkedUserSearchActivity::class.java)
startActivityForResult(intent, REQUEST_CODE_SEARCH)
} }
binding.btnAddLinkedUser.setOnClickListener { binding.btnAddLinkedUser.setOnClickListener {

View File

@@ -1,45 +0,0 @@
package com.example.defenseapplication.liveVideo
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.defenseapplication.databinding.LinkedUserSearchActivityBinding
import com.gyf.immersionbar.ImmersionBar
//搜索
class LinkedUserSearchActivity : AppCompatActivity() {
private lateinit var binding: LinkedUserSearchActivityBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = LinkedUserSearchActivityBinding.inflate(layoutInflater)
setContentView(binding.root)
ImmersionBar.with(this)
.statusBarDarkFont(true)
.titleBar(binding.topBar)
.init()
initListener()
initData()
}
private fun initListener() {
binding.ivBack.setOnClickListener {
finish()
}
binding.btnSearch.setOnClickListener {
initData()
}
}
private fun initData() {
val searchText = binding.etSearch.text.toString().trim()
binding.rvSearchResult.layoutManager = LinearLayoutManager(this)
}
}

View File

@@ -163,19 +163,17 @@ object ApiConfig {
val requestBuilder = chain.request().newBuilder() val requestBuilder = chain.request().newBuilder()
val token = authToken val token = authToken
val langHeader = LanguageHeaderManager.getLanguageHeaderValue() val langHeader = LanguageHeaderManager.getLanguageHeaderValue()
// 添加必要的请求头
requestBuilder.header("clientid", "428a8310cd442757ae699df5d894f051")
requestBuilder.header("content-language", langHeader)
// 如果有 token添加 Authorization 头
if (token.isNotBlank()) { if (token.isNotBlank()) {
Log.d("ApiConfig", buildAuthorizationValue(token)) Log.d("ApiConfig", buildAuthorizationValue(token))
requestBuilder.header("Authorization", buildAuthorizationValue(token)) requestBuilder.header("Authorization", buildAuthorizationValue(token))
requestBuilder.header("clientid", "428a8310cd442757ae699df5d894f051")
requestBuilder.header("content-language", langHeader)
} }
requestBuilder
// .header("Client-Toc", "Y")
// .header("Accept-Language", LanguageHelper.getLanguageServiceStr(BrightApp.getInstance()))
// .header("model", "Android")
// .header("X-App-Version", AppUtils.getAppVersionName())
chain.proceed(requestBuilder.build()) chain.proceed(requestBuilder.build())
} }

View File

@@ -8,8 +8,10 @@ import com.example.defenseapplication.bean.GetCodeBean
import bean.LoginBean import bean.LoginBean
import bean.LoginRequest import bean.LoginRequest
import bean.RegisterRequest import bean.RegisterRequest
import com.example.defenseapplication.bean.AddDeviceUserRequest
import com.example.defenseapplication.bean.DeleteBean import com.example.defenseapplication.bean.DeleteBean
import com.example.defenseapplication.bean.DeleteDeviceUserRequest import com.example.defenseapplication.bean.DeleteDeviceUserRequest
import com.example.defenseapplication.bean.FamilyMembersBean
import com.example.defenseapplication.bean.MessageGroup import com.example.defenseapplication.bean.MessageGroup
import com.example.defenseapplication.bean.SwitchFamilyRequest import com.example.defenseapplication.bean.SwitchFamilyRequest
import retrofit2.http.Body import retrofit2.http.Body
@@ -104,5 +106,29 @@ interface ApiService {
@POST("/app/deleteDeviceUser") @POST("/app/deleteDeviceUser")
suspend fun deleteDeviceUser(@Body request: DeleteDeviceUserRequest): GetCodeBean<Any> suspend fun deleteDeviceUser(@Body request: DeleteDeviceUserRequest): GetCodeBean<Any>
/**
* 查看家庭成员表
*/
@GET("/app/familyMembers/list")
suspend fun getFamilyMembers(
@Query("createDept") createDept: Long? = null,
@Query("createBy") createBy: Long? = null,
@Query("createTime") createTime: String? = null,
@Query("updateBy") updateBy: Long? = null,
@Query("updateTime") updateTime: String? = null,
@Query("params.key.key") paramsKey: String? = null,
@Query("id") id: Long? = null,
@Query("parentId") parentId: Long? = null,
@Query("parentName") parentName: String? = null,
@Query("userId") userId: Long? = null,
@Query("status") status: String? = null
): GetCodeBean<List<FamilyMembersBean>>
/**
* 添加设备关联用户
*/
@POST("/app/addDeviceUser")
suspend fun addDeviceUser(@Body request: AddDeviceUserRequest): GetCodeBean<Any>
} }

View File

@@ -0,0 +1,23 @@
package com.example.defenseapplication.utils
object DeviceUserUpdateEvent {
private val listeners = mutableListOf<DeviceUserUpdateListener>()
interface DeviceUserUpdateListener {
fun onDeviceUserUpdated()
}
fun addListener(listener: DeviceUserUpdateListener) {
if (!listeners.contains(listener)) {
listeners.add(listener)
}
}
fun removeListener(listener: DeviceUserUpdateListener) {
listeners.remove(listener)
}
fun notifyUpdate() {
listeners.forEach { it.onDeviceUserUpdated() }
}
}

View File

@@ -1,3 +1,5 @@
package com.example.defenseapplication.utils
import android.content.Context import android.content.Context
import androidx.core.content.edit import androidx.core.content.edit
@@ -6,7 +8,7 @@ enum class AppLanguage(val code: String) {
SIMPLIFIED_CHINESE("zh_CN"), SIMPLIFIED_CHINESE("zh_CN"),
TRADITIONAL_CHINESE("zh_TW") TRADITIONAL_CHINESE("zh_TW")
} }
//语言枚举与管理器
object LanguageHeaderManager { object LanguageHeaderManager {
private const val PREF_NAME = "app_lang_pref" private const val PREF_NAME = "app_lang_pref"
private const val KEY_LANGUAGE = "selected_language" private const val KEY_LANGUAGE = "selected_language"

View File

@@ -6,6 +6,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical" android:orientation="vertical"
android:background="@color/bg_gray"
tools:context=".liveVideo.AddLinkedUserActivity"> tools:context=".liveVideo.AddLinkedUserActivity">
<!-- 标题栏 --> <!-- 标题栏 -->

View File

@@ -1,86 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@color/bg_gray"
tools:context=".liveVideo.LinkedUserSearchActivity">
<!-- 标题栏 -->
<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/search"
android:textColor="@color/black"
android:textSize="16dp"
android:textStyle="bold" />
<TextView
android:id="@+id/btnSearch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/search"
android:textColor="@color/green"
android:textSize="14sp"/>
</LinearLayout>
<!-- 搜索输入框 -->
<LinearLayout
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="wrap_content"
android:hint="@string/search_preset_text"
android:textColor="@color/black"
android:textColorHint="@color/gray"
android:textSize="14sp"
android:background="@null"/>
</LinearLayout>
</LinearLayout>
<!-- 搜索结果列表 -->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvSearchResult"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingHorizontal="16dp"
android:paddingTop="8dp"/>
</LinearLayout>