切换家庭联动

This commit is contained in:
2026-05-16 17:18:05 +08:00
parent a8f202a906
commit 4c53c43f7b
23 changed files with 515 additions and 121 deletions

View File

@@ -38,13 +38,13 @@ class DeviceAdapter(
RecyclerView.ViewHolder(binding.root) {
fun bind(item: DeviceUi) {
binding.tvDeviceName.text = item.name
binding.tvDeviceType.text = item.name
if (item.isOnline) {
binding.tvDeviceName.text = "\u25CF 正在运行"
binding.tvDeviceName.setTextColor(binding.root.context.getColor(R.color.green))
binding.tvDeviceName.text = "\u25CF 正在运行"
} else {
binding.tvDeviceName.text = "\u25CF 离线"
binding.tvDeviceName.setTextColor(binding.root.context.getColor(R.color.red))
binding.tvDeviceName.text = "\u25CF 离线"
}
binding.root.setOnClickListener {
onItemClick(item)

View File

@@ -37,7 +37,12 @@ class FamilyAdapter(
RecyclerView.ViewHolder(binding.root) {
fun bind(item: FamilyBean) {
binding.tvFamilyName.text = item.parentName
val isAdmin = item.role == "appadmin"
if (isAdmin) {
binding.tvFamilyName.text = binding.root.context.getString(R.string.my_family)
} else {
binding.tvFamilyName.text = "${item.parentName}${binding.root.context.getString(R.string.family_with_normal)}"
}
binding.tvFamilyRole.text = getRoleText(item.role)
val isSelected = item.parentName == selectedFamily
@@ -48,7 +53,7 @@ class FamilyAdapter(
private fun getRoleText(role: String): String {
return when (role) {
"appadmin" ->binding.root.context.getString(R.string.admin_user)
"appadmin" -> binding.root.context.getString(R.string.admin_user)
else -> binding.root.context.getString(R.string.normal_user)
}
}

View File

@@ -9,12 +9,18 @@ import com.example.defenseapplication.databinding.ItemSwitchFamilyBinding
import com.example.defenseapplication.model.FamilyItem
class FamilySwitchAdapter(
private val familyList: List<FamilyItem>,
private var familyList: List<FamilyItem>,
private val onItemClickListener: (FamilyItem) -> Unit
) : RecyclerView.Adapter<FamilySwitchAdapter.FamilyViewHolder>() {
private var selectedPosition = 0
fun updateList(newList: List<FamilyItem>) {
familyList = newList
selectedPosition = 0
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FamilyViewHolder {
val binding = ItemSwitchFamilyBinding.inflate(
LayoutInflater.from(parent.context),

View File

@@ -1,10 +1,29 @@
package com.example.defenseapplication.bean
data class DeviceBean(
val id: String,
val alertAudio: String,
val audioContet: Any,
val container: Any,
val countNum: Any,
val deviceEm: String,
val deviceFamilyId: String,
val deviceImg: Any,
val deviceName: String,
val deviceNo: String,
val deviceSn: String,
val endTime: Any,
val expirationTime: String,
val fwVer: String,
val id: String,
val light: String,
val patternPerception: Any,
val startTime: Any,
val status: String,
val deviceType: String,
val parentId: String,
val createTime: String?
val strikeInterval: Any,
val strikePosition: Any,
val strikeRange: Any,
val userId: String,
val wifiName: String,
val wifiPassword: String,
val workMode: String
)

View File

@@ -0,0 +1,18 @@
package com.example.defenseapplication.bean
data class MessageItem(
val id: String,
val userId: String,
val deviceId: String,
val category: Int,
val categoryName: String,
val image: String?,
val imageUrl: String?,
val video: String?,
val createTime: String
)
data class MessageGroup(
val time: String,
val list: List<MessageItem>
)

View File

@@ -5,6 +5,7 @@ import android.graphics.Color
import android.graphics.Rect
import android.graphics.drawable.GradientDrawable
import android.os.Bundle
import android.util.Log
import android.util.TypedValue
import android.widget.Toast
import androidx.fragment.app.Fragment
@@ -22,6 +23,8 @@ import com.example.defenseapplication.bean.DeviceBean
import com.example.defenseapplication.bean.FamilyBean
import com.example.defenseapplication.bean.SwitchFamilyRequest
import com.example.defenseapplication.databinding.HomeMenuFragmentBinding
import com.example.defenseapplication.utils.FamilySwitchEvent
import com.example.defenseapplication.utils.MessageStatusManager
import com.example.defenseapplication.utils.RetrofitNetwork
import com.example.defenseapplication.utils.UserinfoUtil
import com.example.defenseapplication.view.DefenseDialogs
@@ -42,6 +45,33 @@ class HomeMenuFragment : Fragment() {
private var isFamilyExpanded = false
private lateinit var currentFamily: String
private val unreadCountChangeListener = object : MessageStatusManager.UnreadCountChangeListener {
override fun onUnreadCountChanged(count: Int) {
updateUnreadCountUI(count)
}
}
private val familySwitchListener = object : FamilySwitchEvent.FamilySwitchListener {
override fun onFamilySwitched(familyName: String) {
if (familyName != currentFamily) {
currentFamily = familyName
updateFamilyDisplayText(familyName)
familyAdapter.submitList(familyBeanList, currentFamily)
switchToFamily(familyName)
}
}
}
private fun updateFamilyDisplayText(familyName: String) {
val familyBean = familyBeanList.find { it.parentName == familyName }
val isAdmin = familyBean?.role == "appadmin"
binding.tvCurrentFamily.text = if (isAdmin) {
getString(R.string.my_family)
} else {
"${familyName}${getString(R.string.family_with_normal)}"
}
}
private var familyList: List<String> = emptyList()
private var familyBeanList: List<FamilyBean> = emptyList()
private var deviceBeanList: List<DeviceBean> = emptyList()
@@ -87,6 +117,11 @@ class HomeMenuFragment : Fragment() {
}
fetchFamilyList()
fetchUnreadMessageCount()
MessageStatusManager.addListener(unreadCountChangeListener)
FamilySwitchEvent.addListener(familySwitchListener)
updateUnreadCountUI(MessageStatusManager.getUnreadCount())
}
private fun initView() {
@@ -111,17 +146,49 @@ class HomeMenuFragment : Fragment() {
}
}
private fun fetchUnreadMessageCount() {
CoroutineScope(Dispatchers.IO).launch {
try {
val response = RetrofitNetwork.getNetworkService().getMessage()
withContext(Dispatchers.Main) {
if (response.code == 200 && response.data != null) {
val messageGroups = response.data as List<*>
var unreadCount = 0
messageGroups.forEach { group ->
if (group is Map<*, *>) {
val list = group["list"] as? List<*>
list?.let { unreadCount += it.size }
}
}
MessageStatusManager.setUnreadCount(unreadCount)
}
}
} catch (e: Exception) {
e.printStackTrace()
}
}
}
private fun updateUnreadCountUI(count: Int) {
if (count > 0) {
binding.tvUnreadCount.visibility = View.VISIBLE
binding.tvUnreadCount.text = if (count > 99) "99+" else count.toString()
} else {
binding.tvUnreadCount.visibility = View.GONE
}
}
private fun fetchFamilyList() {
CoroutineScope(Dispatchers.IO).launch {
try {
val response = RetrofitNetwork.getNetworkService().getFamilyList()
withContext(Dispatchers.Main) {
if (response.code == 200 && response.data != null) {
familyBeanList = response.data
familyList = response.data.map { it.parentName }
familyBeanList = response.data.reversed()
familyList = response.data.map { it.parentName }.reversed()
if (familyList.isNotEmpty()) {
currentFamily = familyList.first()
binding.tvCurrentFamily.text = currentFamily
updateFamilyDisplayText(currentFamily)
familyAdapter.submitList(familyBeanList, currentFamily)
val userInfo = UserinfoUtil.getUserInfo()
@@ -144,6 +211,7 @@ class HomeMenuFragment : Fragment() {
}
private fun updateAdminUI() {
Log.d("HomeMenuFragment", "canViewDevice = $canViewDevice")
if (canViewDevice) {
binding.tvDeviceTitle.visibility = View.VISIBLE
binding.rvDeviceList.visibility = View.VISIBLE
@@ -180,7 +248,9 @@ class HomeMenuFragment : Fragment() {
val userInfo = UserinfoUtil.getUserInfo()
canViewDevice = userInfo?.role == "appadmin" && familyBean.role != "member"
updateAdminUI()
updateFamilyDisplayText(familyName)
fetchDeviceList()
FamilySwitchEvent.notifyFamilySwitched(familyName)
} else {
Toast.makeText(requireContext(), response.msg, Toast.LENGTH_SHORT).show()
}
@@ -200,8 +270,10 @@ class HomeMenuFragment : Fragment() {
try {
val response = RetrofitNetwork.getNetworkService().getDeviceList()
withContext(Dispatchers.Main) {
Log.d("DeviceList", "code = ${response.code}, data = ${response.data}")
if (response.code == 200 && response.data != null) {
deviceBeanList = response.data
Log.d("DeviceList", "deviceBeanList size = ${deviceBeanList.size}")
updateDeviceList()
} else {
Toast.makeText(requireContext(), response.msg, Toast.LENGTH_SHORT).show()
@@ -237,15 +309,8 @@ class HomeMenuFragment : Fragment() {
}
private fun updateDeviceList() {
val currentFamilyId = currentFamilyBean?.id
val filteredDevices = if (currentFamilyId != null) {
deviceBeanList.filter { it.parentId == currentFamilyId }
} else {
deviceBeanList
}
val deviceUiList = filteredDevices.map {
DeviceUi(it.deviceName, it.status == "online")
val deviceUiList = deviceBeanList.map {
DeviceUi(it.deviceName, it.status == "0")
}
if (deviceUiList.isEmpty()) {
@@ -307,6 +372,8 @@ class HomeMenuFragment : Fragment() {
super.onDestroyView()
binding.rvFamilyList.adapter = null
binding.rvDeviceList.adapter = null
MessageStatusManager.removeListener(unreadCountChangeListener)
FamilySwitchEvent.removeListener(familySwitchListener)
_binding = null // 避免内存泄漏
}
}

View File

@@ -1,6 +1,7 @@
package com.example.defenseapplication.home
import android.os.Bundle
import android.view.View
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
@@ -8,8 +9,16 @@ import androidx.core.view.WindowInsetsCompat
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.defenseapplication.adapter.MessageListAdapter
import com.example.defenseapplication.adapter.MessageListItem
import com.example.defenseapplication.bean.MessageGroup
import com.example.defenseapplication.bean.MessageItem
import com.example.defenseapplication.databinding.MessageActivityBinding
import com.example.defenseapplication.utils.MessageStatusManager
import com.example.defenseapplication.utils.RetrofitNetwork
import com.gyf.immersionbar.ImmersionBar
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
//消息通知页面
class MessageActivity : AppCompatActivity() {
private lateinit var binding: MessageActivityBinding
@@ -17,80 +26,94 @@ class MessageActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
binding = MessageActivityBinding.inflate(layoutInflater)
setContentView(binding.root)
ImmersionBar.with(this)
.statusBarDarkFont(true)
.titleBar(binding.topBar)
.init()
ViewCompat.setOnApplyWindowInsetsListener(binding.main) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}
initView()
MessageStatusManager.clearUnreadCount()
loadMessageList()
}
private fun initView() {
binding.ivBack.setOnClickListener { finish() }
binding.rvMessageList.layoutManager = LinearLayoutManager(this)
binding.rvMessageList.adapter = messageAdapter
messageAdapter.submitList(buildMockData())
}
private fun buildMockData(): List<MessageListItem> {
return listOf(
MessageListItem.Header("今天"),
MessageListItem.Message(
time = "15:54",
title = "有人入侵",
dateTime = "2026-05-06 15:54:25",
unread = true
),
MessageListItem.Message(
time = "12:54",
title = "有人入侵",
dateTime = "2026-05-06 15:54:25",
unread = true
),
MessageListItem.Message(
time = "11:54",
title = "有人入侵",
dateTime = "2026-05-06 15:54:25",
unread = true
),
MessageListItem.Header("05-05"),
MessageListItem.Message(
time = "15:54",
title = "设备故障",
dateTime = "2026-05-06 15:54:25",
unread = false
),
MessageListItem.Message(
time = "08:07",
title = "设备离线",
dateTime = "2026-05-06 15:54:25",
unread = false
),
MessageListItem.Message(
time = "08:07",
title = "到期提醒",
dateTime = "2026-05-06 15:54:25",
unread = false
),
MessageListItem.Message(
time = "11:54",
title = "有人入侵",
dateTime = "2026-05-06 15:54:25",
unread = false
),
MessageListItem.Message(
time = "11:54",
title = "有人入侵",
dateTime = "2026-05-06 15:54:25",
unread = false
)
)
private fun loadMessageList() {
CoroutineScope(Dispatchers.IO).launch {
try {
val response = RetrofitNetwork.getNetworkService().getMessage()
if (response.code == 0 && response.data != null) {
val messageGroups = response.data as List<MessageGroup>
val items = convertToMessageListItems(messageGroups)
withContext(Dispatchers.Main) {
if (items.isEmpty()) {
showEmptyState()
} else {
hideEmptyState()
messageAdapter.submitList(items)
}
}
} else {
withContext(Dispatchers.Main) {
showEmptyState()
}
}
} catch (e: Exception) {
e.printStackTrace()
withContext(Dispatchers.Main) {
showEmptyState()
}
}
}
}
private fun showEmptyState() {
binding.contentLayout.visibility = View.GONE
binding.emptyLayout.visibility = View.VISIBLE
}
private fun hideEmptyState() {
binding.contentLayout.visibility = View.VISIBLE
binding.emptyLayout.visibility = View.GONE
}
private fun convertToMessageListItems(groups: List<MessageGroup>): List<MessageListItem> {
val items = mutableListOf<MessageListItem>()
groups.forEach { group ->
val headerTitle = formatDate(group.time)
items.add(MessageListItem.Header(headerTitle))
group.list.forEach { message ->
items.add(
MessageListItem.Message(
time = extractTime(message.createTime),
title = message.categoryName,
dateTime = message.createTime,
unread = false
)
)
}
}
return items
}
private fun formatDate(dateStr: String): String {
return if (dateStr == "今天" || dateStr.contains("今天")) {
"今天"
} else {
dateStr
}
}
private fun extractTime(dateTime: String): String {
return if (dateTime.contains(" ")) {
dateTime.split(" ")[1].substring(0, 5)
} else {
dateTime
}
}
}

View File

@@ -6,6 +6,7 @@ import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import com.bumptech.glide.Glide
import com.example.defenseapplication.R
import com.example.defenseapplication.databinding.PersonalFragmentBinding
@@ -13,9 +14,15 @@ import com.example.defenseapplication.liveVideo.LinkedUserActivity
import com.example.defenseapplication.personal.PasswordManagementActivity
import com.example.defenseapplication.personal.PersonalProfileActivity
import com.example.defenseapplication.utils.LanguageUtil
import com.example.defenseapplication.utils.RetrofitNetwork
import com.example.defenseapplication.utils.UserinfoUtil
import com.example.defenseapplication.view.FamilySwitchDialog
import com.example.defenseapplication.view.LanguageDialog
import com.gyf.immersionbar.ImmersionBar
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
//我的碎片
class PersonalFragment : Fragment() {
// ViewBinding
@@ -61,9 +68,36 @@ class PersonalFragment : Fragment() {
val intent= Intent(requireContext(), PasswordManagementActivity::class.java)
startActivity(intent)
}
fetchCurrentFamily()
return binding.root
}
private fun fetchCurrentFamily() {
CoroutineScope(Dispatchers.IO).launch {
try {
val response = RetrofitNetwork.getNetworkService().getFamilyList()
withContext(Dispatchers.Main) {
if (response.code == 200 && response.data != null) {
val userInfo = UserinfoUtil.getUserInfo()
val currentFamily = response.data.find {
it.role == userInfo?.role && it.role != "member"
} ?: response.data.firstOrNull()
currentFamily?.let {
val isAdmin = it.role == "appadmin"
if (isAdmin) {
binding.tvCurrentFamily.text = getString(R.string.my_family)
} else {
binding.tvCurrentFamily.text = "${it.parentName}${getString(R.string.family_with_normal)}"
}
}
}
}
} catch (e: Exception) {
e.printStackTrace()
}
}
}
/**
* 更新当前语言显示
@@ -90,11 +124,39 @@ class PersonalFragment : Fragment() {
*/
private fun showFamilySwitchDialog() {
val dialog = FamilySwitchDialog(requireContext()) { familyName ->
binding.tvCurrentFamily.text = familyName
updateFamilyDisplay(familyName)
}
dialog.show()
}
private fun updateFamilyDisplay(familyName: String) {
CoroutineScope(Dispatchers.IO).launch {
try {
val response = RetrofitNetwork.getNetworkService().getFamilyList()
withContext(Dispatchers.Main) {
if (response.code == 200 && response.data != null) {
val family = response.data.find { it.parentName == familyName }
family?.let {
val isAdmin = it.role == "appadmin"
if (isAdmin) {
binding.tvCurrentFamily.text = getString(R.string.my_family)
} else {
binding.tvCurrentFamily.text = "${it.parentName}${getString(R.string.family_with_normal)}"
}
} ?: run {
binding.tvCurrentFamily.text = familyName
}
} else {
binding.tvCurrentFamily.text = familyName
}
}
} catch (e: Exception) {
e.printStackTrace()
binding.tvCurrentFamily.text = familyName
}
}
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null // 避免内存泄漏

View File

@@ -7,6 +7,7 @@ import com.example.defenseapplication.bean.GetCodeBean
import bean.LoginBean
import bean.LoginRequest
import bean.RegisterRequest
import com.example.defenseapplication.bean.MessageGroup
import com.example.defenseapplication.bean.SwitchFamilyRequest
import retrofit2.http.Body
import retrofit2.http.GET
@@ -55,6 +56,12 @@ interface ApiService {
*/
@GET("/app/getdeviceList")
suspend fun getDeviceList(): GetCodeBean<List<DeviceBean>>
/**
* 查看消息列表
*/
@GET("/app/appMessage/list")
suspend fun getMessage(): GetCodeBean<List<MessageGroup>>
}

View File

@@ -0,0 +1,23 @@
package com.example.defenseapplication.utils
object FamilySwitchEvent {
private val listeners = mutableListOf<FamilySwitchListener>()
interface FamilySwitchListener {
fun onFamilySwitched(familyName: String)
}
fun addListener(listener: FamilySwitchListener) {
if (!listeners.contains(listener)) {
listeners.add(listener)
}
}
fun removeListener(listener: FamilySwitchListener) {
listeners.remove(listener)
}
fun notifyFamilySwitched(familyName: String) {
listeners.forEach { it.onFamilySwitched(familyName) }
}
}

View File

@@ -0,0 +1,44 @@
package com.example.defenseapplication.utils
object MessageStatusManager {
private var unreadCount = 0
private val listeners = mutableListOf<UnreadCountChangeListener>()
fun getUnreadCount(): Int {
return unreadCount
}
fun setUnreadCount(count: Int) {
unreadCount = if (count > 99) 99 else count
notifyListeners()
}
fun incrementUnreadCount() {
unreadCount++
if (unreadCount > 99) unreadCount = 99
notifyListeners()
}
fun clearUnreadCount() {
unreadCount = 0
notifyListeners()
}
fun addListener(listener: UnreadCountChangeListener) {
if (!listeners.contains(listener)) {
listeners.add(listener)
}
}
fun removeListener(listener: UnreadCountChangeListener) {
listeners.remove(listener)
}
private fun notifyListeners() {
listeners.forEach { it.onUnreadCountChanged(unreadCount) }
}
interface UnreadCountChangeListener {
fun onUnreadCountChanged(count: Int)
}
}

View File

@@ -7,21 +7,30 @@ import android.view.Gravity
import android.view.Window
import android.view.WindowManager
import android.widget.TextView
import android.widget.Toast
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.defenseapplication.R
import com.example.defenseapplication.adapter.FamilySwitchAdapter
import com.example.defenseapplication.bean.FamilyBean
import com.example.defenseapplication.bean.SwitchFamilyRequest
import com.example.defenseapplication.model.FamilyItem
import com.example.defenseapplication.utils.FamilySwitchEvent
import com.example.defenseapplication.utils.RetrofitNetwork
import com.example.defenseapplication.utils.UserinfoUtil
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
/**
* 家庭切换对话框
*/
class FamilySwitchDialog(
context: Context,
private val onFamilySelected: (String) -> Unit
) : Dialog(context, R.style.BottomDialogStyle) {
private lateinit var adapter: FamilySwitchAdapter
private var familyBeanList: List<FamilyBean> = emptyList()
private var currentFamilyName: String = ""
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -38,6 +47,7 @@ class FamilySwitchDialog(
window?.setDimAmount(0.5f)
initViews()
fetchFamilyList()
}
private fun initViews() {
@@ -45,12 +55,7 @@ class FamilySwitchDialog(
val tvConfirm = findViewById<TextView>(R.id.tvConfirm)
val rvMessageList = findViewById<RecyclerView>(R.id.rvMessageList)
val familyList = listOf(
FamilyItem("1", context.getString(R.string.my_family)),
FamilyItem("2", "张三的家庭")
)
adapter = FamilySwitchAdapter(familyList) { familyItem ->
adapter = FamilySwitchAdapter(emptyList()) { familyItem ->
}
rvMessageList.layoutManager = LinearLayoutManager(context)
@@ -61,9 +66,67 @@ class FamilySwitchDialog(
}
tvConfirm.setOnClickListener {
val selectedFamily = adapter.getSelectedItem()
onFamilySelected(selectedFamily.name)
dismiss()
val selectedItem = adapter.getSelectedItem()
val selectedFamily = familyBeanList.find { it.parentName == selectedItem.name }
selectedFamily?.let {
switchToFamily(it)
}
}
}
private fun fetchFamilyList() {
CoroutineScope(Dispatchers.IO).launch {
try {
val response = RetrofitNetwork.getNetworkService().getFamilyList()
withContext(Dispatchers.Main) {
if (response.code == 200 && response.data != null) {
familyBeanList = response.data.reversed()
val familyItems = familyBeanList.map { FamilyItem(it.id, it.parentName) }
adapter.updateList(familyItems)
familyBeanList.firstOrNull()?.let {
currentFamilyName = it.parentName
}
} else {
Toast.makeText(context, response.msg, Toast.LENGTH_SHORT).show()
}
}
} catch (e: Exception) {
e.printStackTrace()
withContext(Dispatchers.Main) {
Toast.makeText(context, R.string.network_error, Toast.LENGTH_SHORT).show()
}
}
}
}
private fun switchToFamily(familyBean: FamilyBean) {
CoroutineScope(Dispatchers.IO).launch {
try {
val userInfo = UserinfoUtil.getUserInfo()
val request = SwitchFamilyRequest(
clientId = "428a8310cd442757ae699df5d894f051",
grantType = "switch",
id = familyBean.id,
userType = "app_user",
role = userInfo?.role ?: ""
)
val response = RetrofitNetwork.getNetworkService().switchFamily(request)
withContext(Dispatchers.Main) {
if (response.code == 200) {
onFamilySelected(familyBean.parentName)
FamilySwitchEvent.notifyFamilySwitched(familyBean.parentName)
dismiss()
} else {
Toast.makeText(context, response.msg, Toast.LENGTH_SHORT).show()
}
}
} catch (e: Exception) {
e.printStackTrace()
withContext(Dispatchers.Main) {
Toast.makeText(context, R.string.network_error, Toast.LENGTH_SHORT).show()
}
}
}
}
}

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#FFFFFF" />
<corners android:radius="12dp" />
<stroke
android:width="1dp"
android:color="#EEEEEE" />
</shape>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#00CED1" />
<corners android:radius="8dp" />
</shape>

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="20dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FFFFFF"
android:pathData="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/>
</vector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -78,11 +78,18 @@
android:layout_height="match_parent"
android:src="@drawable/message"/>
<View
android:layout_width="10dp"
android:layout_height="10dp"
<TextView
android:id="@+id/tvUnreadCount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|top"
android:background="@drawable/ic_red_dot" />
android:background="@drawable/bg_unread_dot"
android:minWidth="16dp"
android:height="16dp"
android:gravity="center"
android:textSize="10sp"
android:textColor="@color/white"
android:visibility="gone" />
</FrameLayout>
<FrameLayout

View File

@@ -2,7 +2,6 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical"
android:background="@drawable/bg_white"
android:layout_marginBottom="14dp"
@@ -29,22 +28,28 @@
android:src="@drawable/go_up" />
</LinearLayout>
<TextView
android:text="防雨机"
android:id="@+id/tvDeviceType"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_marginStart="10dp"
android:textColor="@color/black"
android:textSize="12dp" />
android:textSize="14dp"
android:textStyle="bold"/>
<TextView
android:text="离线"
android:id="@+id/tvDeviceName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginStart="10dp"
android:textColor="@color/black"
android:textSize="12dp" />
android:textSize="12dp"
android:textStyle="bold"/>
</LinearLayout>

View File

@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<RelativeLayout 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:padding="16dp"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/message_bg"
android:orientation="vertical"
tools:context=".home.MessageActivity">
<LinearLayout
@@ -35,15 +35,35 @@
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvMessageList"
<LinearLayout
android:id="@+id/contentLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:paddingStart="16dp"
android:paddingTop="12dp"
android:paddingEnd="16dp"
android:paddingBottom="16dp"
tools:listitem="@layout/item_message_notice" />
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvMessageList"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:paddingTop="12dp"
android:paddingBottom="16dp"
tools:listitem="@layout/item_message_notice" />
</LinearLayout>
<LinearLayout
android:id="@+id/emptyLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:visibility="gone">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/no_message" />
</LinearLayout>
</RelativeLayout>

View File

@@ -15,9 +15,7 @@
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:paddingStart="16dp"
android:paddingEnd="16dp">
app:layout_constraintEnd_toEndOf="parent">
<ImageView
android:id="@+id/backIcon"
android:layout_width="24dp"

View File

@@ -109,6 +109,8 @@
<string name="join_family">加入家庭</string>
<string name="family_code">家庭码</string>
<string name="enter_family_code">请输入家庭码</string>
<string name="family_with_normal">的家庭</string>
<string name="no_device">暂无设备</string>
<!-- User Management -->
<string name="user_management">用户管理</string>

View File

@@ -56,6 +56,7 @@
<string name="profile">Profile</string>
<string name="admin_user">Administrator</string>
<string name="normal_user">Ordinary User</string>
<string name="family_with_normal">s Family</string>
<!-- Home Menu -->