自定义告警弹窗

This commit is contained in:
2026-04-29 15:11:28 +08:00
parent 827d85724e
commit 5004917d66
25 changed files with 985 additions and 9 deletions

View File

@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
@@ -18,6 +19,12 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.DefenseApplication">
<activity
android:name=".personal.PersonalProfileActivity"
android:exported="false" />
<activity
android:name=".home.MessageActivity"
android:exported="false" />
<activity
android:name=".home.HomeActivity"
android:exported="true">
@@ -44,8 +51,7 @@
android:exported="false" />
<activity
android:name=".login.LoginActivity"
android:exported="false"/>
android:exported="false" />
</application>
</manifest>

View File

@@ -11,7 +11,9 @@ data class DeviceUi(
val isOnline: Boolean
)
class DeviceAdapter : RecyclerView.Adapter<DeviceAdapter.DeviceViewHolder>() {
class DeviceAdapter(
private val onItemClick: (DeviceUi) -> Unit = {}
) : RecyclerView.Adapter<DeviceAdapter.DeviceViewHolder>() {
private val items = mutableListOf<DeviceUi>()
@@ -44,6 +46,9 @@ class DeviceAdapter : RecyclerView.Adapter<DeviceAdapter.DeviceViewHolder>() {
binding.tvDeviceStatus.text = "\u25CF 离线"
binding.tvDeviceStatus.setTextColor(binding.root.context.getColor(R.color.red))
}
binding.root.setOnClickListener {
onItemClick(item)
}
}
}
}

View File

@@ -1,5 +1,6 @@
package com.example.defenseapplication.home
import android.content.Intent
import android.graphics.Color
import android.graphics.Rect
import android.graphics.drawable.GradientDrawable
@@ -16,13 +17,15 @@ import com.example.defenseapplication.adapter.DeviceAdapter
import com.example.defenseapplication.adapter.DeviceUi
import com.example.defenseapplication.adapter.FamilyAdapter
import com.example.defenseapplication.databinding.HomeMenuFragmentBinding
import com.example.defenseapplication.view.DefenseDialogs
import com.example.defenseapplication.view.showDefenseDialog
class HomeMenuFragment : Fragment() {
// ViewBinding
private var _binding: HomeMenuFragmentBinding? = null
private val binding get() = _binding!!
private val familyAdapter by lazy { FamilyAdapter(::onFamilySelected) }
private val deviceAdapter by lazy { DeviceAdapter() }
private val deviceAdapter by lazy { DeviceAdapter(::onDeviceClicked) }
private var isFamilyExpanded = false
private var currentFamily = "我的家庭"
@@ -63,6 +66,10 @@ class HomeMenuFragment : Fragment() {
startColor = Color.parseColor("#EBDCED"),
endColor = Color.parseColor("#CAF4FF")
)
binding.message.setOnClickListener {
val intent = Intent(requireContext(), MessageActivity::class.java)
startActivity(intent)
}
}
private fun initView() {
@@ -115,6 +122,13 @@ class HomeMenuFragment : Fragment() {
deviceAdapter.submitList(familyDeviceMap[currentFamily].orEmpty())
}
private fun onDeviceClicked(device: DeviceUi) {
if (device.isOnline) return
showDefenseDialog(
config = DefenseDialogs.deviceOfflineConfig()
)
}
private fun dpToPx(dp: Int): Int {
return TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,

View File

@@ -0,0 +1,92 @@
package com.example.defenseapplication.home
import android.os.Bundle
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
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.databinding.MessageActivityBinding
class MessageActivity : AppCompatActivity() {
private lateinit var binding: MessageActivityBinding
private val messageAdapter by lazy { MessageListAdapter() }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
binding = MessageActivityBinding.inflate(layoutInflater)
setContentView(binding.root)
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()
}
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
)
)
}
}

View File

@@ -1,12 +1,15 @@
package com.example.defenseapplication.home
import android.content.Intent
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.bumptech.glide.Glide
import com.example.defenseapplication.R
import com.example.defenseapplication.databinding.PersonalFragmentBinding
import com.example.defenseapplication.personal.PersonalProfileActivity
class PersonalFragment : Fragment() {
// ViewBinding
@@ -19,6 +22,14 @@ class PersonalFragment : Fragment() {
savedInstanceState: Bundle?
): View {
_binding = PersonalFragmentBinding.inflate(inflater, container, false)
Glide.with(this)
.load(R.mipmap.ic_launcher_round)
.circleCrop()
.into(binding.ivAvatar)
binding.headerLayout.setOnClickListener {
val intent= Intent(requireContext(), PersonalProfileActivity::class.java)
startActivity(intent)
}
return binding.root
}

View File

@@ -0,0 +1,47 @@
package com.example.defenseapplication.personal
import android.os.Bundle
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import com.bumptech.glide.Glide
import com.example.defenseapplication.R
import com.example.defenseapplication.databinding.PersonalProfileActivityBinding
class PersonalProfileActivity : AppCompatActivity() {
private lateinit var binding: PersonalProfileActivityBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
binding = PersonalProfileActivityBinding.inflate(layoutInflater)
setContentView(binding.root)
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()
}
private fun initView() {
binding.ivBack.setOnClickListener { finish() }
// 默认展示数据(后续可接你的用户信息接口/数据库)
Glide.with(this)
.load(R.mipmap.ic_launcher_round)
.circleCrop()
.into(binding.ivAvatar)
binding.tvNickname.text = "这里是我的昵称"
binding.tvPhone.text = "13589898989"
// 点击行可跳转到“修改昵称/修改手机号”等页面
//binding.itemAvatar.setOnClickListener { /* TODO */ }
//binding.itemNickname.setOnClickListener { /* TODO */ }
//binding.itemPhone.setOnClickListener { /* TODO */ }
}
}

View File

@@ -0,0 +1,255 @@
package com.example.defenseapplication.view
import android.app.Dialog
import android.os.Bundle
import android.text.InputType
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import android.widget.LinearLayout
import android.widget.EditText
import android.widget.TextView
import androidx.core.os.bundleOf
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.FragmentManager
import com.example.defenseapplication.R
class CustomDialogFragment : androidx.fragment.app.DialogFragment() {
data class Config(
val title: String,
val message: String = "",
val positiveText: String = "确定",
val negativeText: String? = "取消",
val cancelOnTouchOutside: Boolean = true,
val showInput: Boolean = false,
val inputHint: String = "",
val inputText: String = "",
val inputType: Int = InputType.TYPE_CLASS_TEXT
)
private var onPositiveClick: ((String) -> Unit)? = null
private var onNegativeClick: (() -> Unit)? = null
private lateinit var config: Config
fun setOnPositiveClick(block: (String) -> Unit): CustomDialogFragment = apply {
onPositiveClick = block
}
fun setOnNegativeClick(block: () -> Unit): CustomDialogFragment = apply {
onNegativeClick = block
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
config = Config(
title = requireArguments().getString(ARG_TITLE).orEmpty(),
message = requireArguments().getString(ARG_MESSAGE).orEmpty(),
positiveText = requireArguments().getString(ARG_POSITIVE_TEXT).orEmpty(),
negativeText = requireArguments().getString(ARG_NEGATIVE_TEXT),
cancelOnTouchOutside = requireArguments().getBoolean(ARG_CANCEL_ON_TOUCH_OUTSIDE),
showInput = requireArguments().getBoolean(ARG_SHOW_INPUT),
inputHint = requireArguments().getString(ARG_INPUT_HINT).orEmpty(),
inputText = requireArguments().getString(ARG_INPUT_TEXT).orEmpty(),
inputType = requireArguments().getInt(ARG_INPUT_TYPE)
)
isCancelable = config.cancelOnTouchOutside
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return super.onCreateDialog(savedInstanceState).apply {
setCanceledOnTouchOutside(config.cancelOnTouchOutside)
}
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
return inflater.inflate(R.layout.dialog_custom, container, false)
}
override fun onStart() {
super.onStart()
dialog?.window?.let { window ->
window.setLayout(
(resources.displayMetrics.widthPixels * 0.88f).toInt(),
WindowManager.LayoutParams.WRAP_CONTENT
)
window.setBackgroundDrawableResource(android.R.color.transparent)
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val tvTitle = view.findViewById<TextView>(R.id.tv_title)
val tvMessage = view.findViewById<TextView>(R.id.tv_message)
val etInput = view.findViewById<EditText>(R.id.et_input)
val btnNegative = view.findViewById<TextView>(R.id.btn_negative)
val btnPositive = view.findViewById<TextView>(R.id.btn_positive)
val dividerCenter = view.findViewById<View>(R.id.v_divider_center)
tvTitle.text = config.title
tvMessage.text = config.message
tvMessage.visibility = if (config.message.isBlank()) View.GONE else View.VISIBLE
etInput.visibility = if (config.showInput) View.VISIBLE else View.GONE
etInput.hint = config.inputHint
etInput.setText(config.inputText)
etInput.inputType = config.inputType
btnPositive.text = config.positiveText
val hasNegative = !config.negativeText.isNullOrBlank()
btnNegative.visibility = if (hasNegative) View.VISIBLE else View.GONE
dividerCenter.visibility = if (hasNegative) View.VISIBLE else View.GONE
if (hasNegative) {
btnNegative.text = config.negativeText
} else {
btnPositive.layoutParams = LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
}
btnNegative.setOnClickListener {
onNegativeClick?.invoke()
dismissAllowingStateLoss()
}
btnPositive.setOnClickListener {
onPositiveClick?.invoke(etInput.text?.toString().orEmpty())
dismissAllowingStateLoss()
}
}
companion object {
private const val ARG_TITLE = "arg_title"
private const val ARG_MESSAGE = "arg_message"
private const val ARG_POSITIVE_TEXT = "arg_positive_text"
private const val ARG_NEGATIVE_TEXT = "arg_negative_text"
private const val ARG_CANCEL_ON_TOUCH_OUTSIDE = "arg_cancel_on_touch_outside"
private const val ARG_SHOW_INPUT = "arg_show_input"
private const val ARG_INPUT_HINT = "arg_input_hint"
private const val ARG_INPUT_TEXT = "arg_input_text"
private const val ARG_INPUT_TYPE = "arg_input_type"
fun newInstance(config: Config): CustomDialogFragment {
return CustomDialogFragment().apply {
arguments = bundleOf(
ARG_TITLE to config.title,
ARG_MESSAGE to config.message,
ARG_POSITIVE_TEXT to config.positiveText,
ARG_NEGATIVE_TEXT to config.negativeText,
ARG_CANCEL_ON_TOUCH_OUTSIDE to config.cancelOnTouchOutside,
ARG_SHOW_INPUT to config.showInput,
ARG_INPUT_HINT to config.inputHint,
ARG_INPUT_TEXT to config.inputText,
ARG_INPUT_TYPE to config.inputType
)
}
}
}
}
object DefenseDialogs {
private const val DEFAULT_TAG = "custom_dialog_fragment"
fun showDialog(
activity: FragmentActivity,
config: CustomDialogFragment.Config,
tag: String = DEFAULT_TAG,
onPositiveClick: (String) -> Unit = {},
onNegativeClick: () -> Unit = {}
): CustomDialogFragment {
return CustomDialogFragment.newInstance(config)
.setOnPositiveClick(onPositiveClick)
.setOnNegativeClick(onNegativeClick)
.also { it.show(activity.supportFragmentManager, tag) }
}
fun showDialog(
fragment: Fragment,
config: CustomDialogFragment.Config,
tag: String = DEFAULT_TAG,
onPositiveClick: (String) -> Unit = {},
onNegativeClick: () -> Unit = {}
): CustomDialogFragment {
return CustomDialogFragment.newInstance(config)
.setOnPositiveClick(onPositiveClick)
.setOnNegativeClick(onNegativeClick)
.also { it.show(fragment.parentFragmentManager, tag) }
}
fun intrusionAlertConfig(deviceName: String, timeText: String): CustomDialogFragment.Config {
return CustomDialogFragment.Config(
title = "入侵告警",
message = "${timeText}有人入侵\n${deviceName}",
positiveText = "去看一下",
negativeText = "取消"
)
}
fun warmPromptConfig(deviceName: String, runDays: Int): CustomDialogFragment.Config {
return CustomDialogFragment.Config(
title = "温馨提示",
message = "${deviceName}】设备已经运行\n${runDays}天请及时维护",
positiveText = "知道了",
negativeText = null
)
}
fun deviceOfflineConfig(): CustomDialogFragment.Config {
return CustomDialogFragment.Config(
title = "设备离线",
message = "设备已离线请检查设备的WIF及电\n源情况",
positiveText = "知道了",
negativeText = null
)
}
fun strikeDistanceConfig(defaultDistance: String): CustomDialogFragment.Config {
return CustomDialogFragment.Config(
title = "打击距离",
message = "",
positiveText = "确定",
negativeText = "取消",
showInput = true,
inputHint = "请输入打击距离",
inputText = defaultDistance,
inputType = InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_FLAG_DECIMAL
)
}
}
fun FragmentActivity.showDefenseDialog(
config: CustomDialogFragment.Config,
tag: String = "custom_dialog_fragment",
onPositiveClick: (String) -> Unit = {},
onNegativeClick: () -> Unit = {}
): CustomDialogFragment {
return DefenseDialogs.showDialog(this, config, tag, onPositiveClick, onNegativeClick)
}
fun Fragment.showDefenseDialog(
config: CustomDialogFragment.Config,
tag: String = "custom_dialog_fragment",
onPositiveClick: (String) -> Unit = {},
onNegativeClick: () -> Unit = {}
): CustomDialogFragment {
return DefenseDialogs.showDialog(this, config, tag, onPositiveClick, onNegativeClick)
}
fun FragmentManager.showDefenseDialog(
config: CustomDialogFragment.Config,
tag: String = "custom_dialog_fragment",
onPositiveClick: (String) -> Unit = {},
onNegativeClick: () -> Unit = {}
): CustomDialogFragment {
return CustomDialogFragment.newInstance(config)
.setOnPositiveClick(onPositiveClick)
.setOnNegativeClick(onNegativeClick)
.also { it.show(this, tag) }
}

View File

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

View File

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

View File

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

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 626 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 432 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 648 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 265 B

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 595 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 651 B

View File

@@ -0,0 +1,92 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/round_bg"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical"
android:paddingStart="24dp"
android:paddingTop="32dp"
android:paddingEnd="24dp"
android:paddingBottom="28dp">
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:textColor="@color/black"
android:textSize="16dp"
android:textStyle="bold" />
<TextView
android:id="@+id/tv_message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="18dp"
android:gravity="center"
android:lineSpacingExtra="2dp"
android:textColor="@color/gray"
android:textSize="14dp" />
<EditText
android:id="@+id/et_input"
android:layout_width="match_parent"
android:layout_height="52dp"
android:layout_marginTop="18dp"
android:background="@drawable/textinput_white_bg"
android:gravity="center_vertical"
android:hint="请输入"
android:inputType="numberDecimal"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:textColor="@color/black"
android:textColorHint="@color/gray"
android:textSize="16sp"
android:visibility="gone" />
</LinearLayout>
<View
android:id="@+id/v_divider_top"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/dialog_view" />
<LinearLayout
android:id="@+id/layout_actions"
android:layout_width="match_parent"
android:layout_height="56dp"
android:orientation="horizontal">
<TextView
android:id="@+id/btn_negative"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:textColor="@color/black"
android:textSize="18sp"
android:textStyle="bold" />
<View
android:id="@+id/v_divider_center"
android:layout_width="1dp"
android:layout_height="match_parent"
android:background="@color/dialog_view" />
<TextView
android:id="@+id/btn_positive"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:textColor="@color/green"
android:textSize="18sp"
android:textStyle="bold" />
</LinearLayout>
</LinearLayout>

View File

@@ -45,7 +45,7 @@
<ImageView
android:id="@+id/ivFamilyArrow"
android:layout_width="12dp"
android:layout_height="6dp"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:src="@drawable/triangle" />
</LinearLayout>
@@ -57,6 +57,7 @@
android:orientation="horizontal">
<FrameLayout
android:id="@+id/message"
android:layout_width="38dp"
android:layout_height="38dp"
android:layout_marginEnd="10dp"

View File

@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:background="@color/message_bg"
tools:context=".home.MessageActivity">
<ImageView
android:id="@+id/ivBack"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginStart="16dp"
android:layout_marginTop="10dp"
android:contentDescription="@null"
android:src="@mipmap/back"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tvTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="消息列表"
android:textColor="#333333"
android:textSize="24sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvMessageList"
android:layout_width="0dp"
android:layout_height="0dp"
android:clipToPadding="false"
android:paddingStart="16dp"
android:paddingTop="12dp"
android:paddingEnd="16dp"
android:paddingBottom="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvTitle"
tools:listitem="@layout/item_message_notice" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -3,12 +3,224 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:orientation="vertical"
tools:context=".home.PersonalFragment">
<TextView
android:layout_width="wrap_content"
<LinearLayout
android:id="@+id/headerLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="个人 Fragment"
android:textSize="20sp"/>
android:background="@drawable/bg_personal_header_gradient"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingHorizontal="16dp"
android:paddingTop="16dp"
android:paddingBottom="18dp">
<ImageView
android:id="@+id/ivAvatar"
android:layout_width="60dp"
android:layout_height="60dp"
android:padding="2dp"
android:src="@mipmap/ic_launcher_round" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_weight="1"
android:orientation="vertical">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:id="@+id/tvNickname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="这里是昵称"
android:textColor="@color/black"
android:textSize="16dp"
android:textStyle="bold" />
<TextView
android:id="@+id/tvRoleTag"
android:layout_width="wrap_content"
android:layout_height="18dp"
android:layout_marginStart="8dp"
android:background="@drawable/rounded_blue_bg"
android:gravity="center"
android:paddingHorizontal="8dp"
android:text="管理员"
android:textColor="@color/white"
android:textSize="11sp"
android:textStyle="bold" />
</LinearLayout>
<TextView
android:id="@+id/tvPhone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:text="13589898989"
android:textColor="#666666"
android:textSize="16dp" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/itemSwitchFamily"
android:layout_width="match_parent"
android:layout_height="72dp"
android:background="@color/white"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingHorizontal="16dp">
<ImageView
android:layout_width="44dp"
android:layout_height="44dp"
android:background="@drawable/bg_detail_border"
android:padding="8dp"
android:src="@drawable/switch_family" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:text="切换家庭"
android:textColor="@color/black"
android:textSize="16dp" />
<TextView
android:id="@+id/tvCurrentFamily"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="end"
android:text="我的家庭"
android:textColor="@color/green"
android:textSize="14dp" />
<ImageView
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_marginStart="8dp"
android:src="@drawable/right_back" />
</LinearLayout>
<LinearLayout
android:id="@+id/itemUserManage"
android:layout_width="match_parent"
android:layout_height="72dp"
android:background="@color/white"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingHorizontal="16dp">
<ImageView
android:layout_width="44dp"
android:layout_height="44dp"
android:background="@drawable/bg_user_manage"
android:padding="8dp"
android:src="@drawable/user_manage" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_weight="1"
android:text="用户管理"
android:textColor="@color/black"
android:textSize="16dp" />
<ImageView
android:layout_width="16dp"
android:layout_height="16dp"
android:src="@drawable/right_back" />
</LinearLayout>
<LinearLayout
android:id="@+id/itemPwdManage"
android:layout_width="match_parent"
android:layout_height="72dp"
android:background="@color/white"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingHorizontal="16dp">
<ImageView
android:layout_width="44dp"
android:layout_height="44dp"
android:background="@drawable/bg_pwd_manager"
android:padding="8dp"
android:src="@drawable/pwd_manager" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_weight="1"
android:text="密码管理"
android:textColor="@color/black"
android:textSize="16dp" />
<ImageView
android:layout_width="16dp"
android:layout_height="16dp"
android:src="@drawable/right_back" />
</LinearLayout>
<LinearLayout
android:id="@+id/itemFaceManage"
android:layout_width="match_parent"
android:layout_height="72dp"
android:background="@color/white"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingHorizontal="16dp">
<ImageView
android:layout_width="44dp"
android:layout_height="44dp"
android:background="@drawable/bg_face_manage"
android:padding="8dp"
android:src="@drawable/face_manage" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_weight="1"
android:text="人脸管理"
android:textColor="@color/black"
android:textSize="16dp" />
<ImageView
android:layout_width="16dp"
android:layout_height="16dp"
android:src="@drawable/right_back" />
</LinearLayout>
<Space
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<TextView
android:id="@+id/btnLogout"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginHorizontal="24dp"
android:layout_marginBottom="28dp"
android:background="@drawable/bg_logout_button"
android:gravity="center"
android:text="退出登录"
android:textColor="#9B9B9B"
android:textSize="14dp" />
</LinearLayout>

View File

@@ -0,0 +1,161 @@
<?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:background="@color/message_bg"
android:orientation="vertical"
tools:context=".personal.PersonalProfileActivity">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/topBar"
android:layout_width="match_parent"
android:layout_height="56dp">
<ImageView
android:id="@+id/ivBack"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginStart="16dp"
android:src="@mipmap/back"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tvTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="个人资料"
android:textColor="@color/black"
android:textSize="16dp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="200dp"
android:gravity="center">
<ImageView
android:id="@+id/ivAvatar"
android:layout_width="112dp"
android:layout_height="112dp"
android:padding="2dp"
android:src="@mipmap/ic_launcher_round" />
<RelativeLayout
android:gravity="center"
android:layout_width="33dp"
android:layout_height="33dp"
android:layout_alignBottom="@id/ivAvatar"
android:layout_alignEnd="@id/ivAvatar"
android:layout_marginBottom="5dp"
android:background="@drawable/bg_white"
android:layout_marginEnd="12dp">
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:padding="8dp"
android:src="@drawable/phone"/>
</RelativeLayout>
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingHorizontal="16dp">
<LinearLayout
android:id="@+id/itemNickname"
android:layout_width="match_parent"
android:layout_height="60dp"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingHorizontal="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="昵称"
android:textColor="@color/black"
android:textSize="16dp" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="end|center_vertical"
android:orientation="horizontal">
<TextView
android:id="@+id/tvNickname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:gravity="end"
android:maxLines="1"
android:text="这里是昵称"
android:textColor="@color/gray"
android:textSize="14dp" />
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginStart="12dp"
android:src="@drawable/right_back" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/itemPhone"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_marginTop="8dp"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingHorizontal="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="绑定手机"
android:textColor="@color/black"
android:textSize="16dp" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="end|center_vertical"
android:orientation="horizontal">
<TextView
android:id="@+id/tvPhone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:gravity="end"
android:maxLines="1"
android:text="13589898989"
android:textColor="@color/gray"
android:textSize="14dp" />
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginStart="12dp"
android:src="@drawable/right_back" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>

View File

@@ -11,5 +11,7 @@
<color name="ic_selected">#000000 </color>
<color name="ic_normal">#999999 </color>
<color name="ic_gray">#99000000 </color>
<color name="dialog_view">#E7E7E7 </color>
<color name="message_bg">#F9F9F9 </color>
</resources>