feat: 考勤面板UI优化(5项改进)
1. 打卡状态文字:显示"已上班 07:02"/"已下班 17:05" 2. NFC扫描倒计时:显示"请贴近信标(8s)" 3. 底部收回指示条:灰色短横线,点击可收回面板 4. 药丸形按钮:大圆角28dp + 蓝色渐变(源码#4CBAF1→#339AFB) 5. 撤销按钮主次分明:窄灰底红字(0.4) + 宽蓝色下班(0.6) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -172,9 +172,12 @@ class HomeFragment : BaseFragment<FragmentHomeBinding>() {
|
|||||||
viewLifecycleOwner.lifecycleScope.launch {
|
viewLifecycleOwner.lifecycleScope.launch {
|
||||||
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
|
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||||
punchViewModel.uiState.collect { state ->
|
punchViewModel.uiState.collect { state ->
|
||||||
// 更新面板按钮
|
// 更新面板按钮和状态文字
|
||||||
punchPanel.updateButtons(state)
|
punchPanel.updateButtons(state)
|
||||||
|
|
||||||
|
// 更新 NFC 倒计时
|
||||||
|
punchPanel.updateNfcCountdown(state.nfcCountdown)
|
||||||
|
|
||||||
// 处理打卡结果(一次性事件)
|
// 处理打卡结果(一次性事件)
|
||||||
state.punchResult?.let { result ->
|
state.punchResult?.let { result ->
|
||||||
punchViewModel.consumePunchResult()
|
punchViewModel.consumePunchResult()
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package com.xiaoqu.watch.ui.punch
|
package com.xiaoqu.watch.ui.punch
|
||||||
|
|
||||||
import android.animation.ValueAnimator
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
@@ -17,13 +16,13 @@ import com.xiaoqu.watch.util.DateUtil
|
|||||||
*
|
*
|
||||||
* 交互方式:
|
* 交互方式:
|
||||||
* - 调用 show() 展开面板
|
* - 调用 show() 展开面板
|
||||||
* - 点击遮罩区域收回
|
* - 点击遮罩 / 底部指示条收回
|
||||||
* - 打卡完成后自动收回
|
* - 打卡完成后自动收回
|
||||||
*
|
*
|
||||||
* 按钮显示规则(来自源码分析,已评审修正):
|
* 按钮显示规则(来自源码分析,已评审修正):
|
||||||
* - onPunchState=0 → "上班打卡"
|
* - onPunchState=0 → "上班打卡"
|
||||||
* - onPunchState=1, offPunchState=0 → "下班打卡"
|
* - onPunchState=1, offPunchState=0 → "下班打卡" + 状态文字"已上班 HH:MM"
|
||||||
* - onPunchState=1, offPunchState=1 → "撤销打卡" + "下班打卡"
|
* - onPunchState=1, offPunchState=1 → "撤销" + "下班打卡" + 状态文字"已下班 HH:MM"
|
||||||
*/
|
*/
|
||||||
class PunchPanelView @JvmOverloads constructor(
|
class PunchPanelView @JvmOverloads constructor(
|
||||||
context: Context,
|
context: Context,
|
||||||
@@ -35,10 +34,12 @@ class PunchPanelView @JvmOverloads constructor(
|
|||||||
private val overlay: View
|
private val overlay: View
|
||||||
private val panelContent: LinearLayout
|
private val panelContent: LinearLayout
|
||||||
private val tvPunchTime: TextView
|
private val tvPunchTime: TextView
|
||||||
|
private val tvPunchStatus: TextView
|
||||||
private val tvNfcHint: TextView
|
private val tvNfcHint: TextView
|
||||||
private val btnPunchIn: TextView
|
private val btnPunchIn: TextView
|
||||||
private val btnPunchOut: TextView
|
private val btnPunchOut: TextView
|
||||||
private val btnRevoke: TextView
|
private val btnRevoke: TextView
|
||||||
|
private val dismissBar: View
|
||||||
|
|
||||||
/** 面板是否正在显示 */
|
/** 面板是否正在显示 */
|
||||||
var isShowing = false
|
var isShowing = false
|
||||||
@@ -48,27 +49,27 @@ class PunchPanelView @JvmOverloads constructor(
|
|||||||
var onPunchInClick: (() -> Unit)? = null
|
var onPunchInClick: (() -> Unit)? = null
|
||||||
var onPunchOutClick: (() -> Unit)? = null
|
var onPunchOutClick: (() -> Unit)? = null
|
||||||
var onRevokeClick: (() -> Unit)? = null
|
var onRevokeClick: (() -> Unit)? = null
|
||||||
/** 面板关闭回调(用于通知 HomeFragment 恢复 ViewPager2 滑动) */
|
/** 面板关闭回调 */
|
||||||
var onDismiss: (() -> Unit)? = null
|
var onDismiss: (() -> Unit)? = null
|
||||||
|
|
||||||
init {
|
init {
|
||||||
// 加载布局
|
|
||||||
LayoutInflater.from(context).inflate(R.layout.view_punch_panel, this, true)
|
LayoutInflater.from(context).inflate(R.layout.view_punch_panel, this, true)
|
||||||
|
|
||||||
// 默认隐藏
|
|
||||||
visibility = GONE
|
visibility = GONE
|
||||||
|
|
||||||
// 绑定 View
|
// 绑定 View
|
||||||
overlay = findViewById(R.id.overlay)
|
overlay = findViewById(R.id.overlay)
|
||||||
panelContent = findViewById(R.id.panelContent)
|
panelContent = findViewById(R.id.panelContent)
|
||||||
tvPunchTime = findViewById(R.id.tvPunchTime)
|
tvPunchTime = findViewById(R.id.tvPunchTime)
|
||||||
|
tvPunchStatus = findViewById(R.id.tvPunchStatus)
|
||||||
tvNfcHint = findViewById(R.id.tvNfcHint)
|
tvNfcHint = findViewById(R.id.tvNfcHint)
|
||||||
btnPunchIn = findViewById(R.id.btnPunchIn)
|
btnPunchIn = findViewById(R.id.btnPunchIn)
|
||||||
btnPunchOut = findViewById(R.id.btnPunchOut)
|
btnPunchOut = findViewById(R.id.btnPunchOut)
|
||||||
btnRevoke = findViewById(R.id.btnRevoke)
|
btnRevoke = findViewById(R.id.btnRevoke)
|
||||||
|
dismissBar = findViewById(R.id.dismissBar)
|
||||||
|
|
||||||
// 点击遮罩收回面板
|
// 点击遮罩 / 指示条 收回面板
|
||||||
overlay.setOnClickListener { dismiss() }
|
overlay.setOnClickListener { dismiss() }
|
||||||
|
dismissBar.setOnClickListener { dismiss() }
|
||||||
|
|
||||||
// 按钮点击
|
// 按钮点击
|
||||||
btnPunchIn.setOnClickListener { onPunchInClick?.invoke() }
|
btnPunchIn.setOnClickListener { onPunchInClick?.invoke() }
|
||||||
@@ -80,11 +81,8 @@ class PunchPanelView @JvmOverloads constructor(
|
|||||||
fun show() {
|
fun show() {
|
||||||
if (isShowing) return
|
if (isShowing) return
|
||||||
isShowing = true
|
isShowing = true
|
||||||
|
|
||||||
// 更新时间
|
|
||||||
updateClock()
|
updateClock()
|
||||||
|
|
||||||
// 显示并播放动画
|
|
||||||
visibility = VISIBLE
|
visibility = VISIBLE
|
||||||
panelContent.translationY = -panelContent.height.toFloat().coerceAtLeast(300f)
|
panelContent.translationY = -panelContent.height.toFloat().coerceAtLeast(300f)
|
||||||
panelContent.animate()
|
panelContent.animate()
|
||||||
@@ -94,10 +92,7 @@ class PunchPanelView @JvmOverloads constructor(
|
|||||||
.start()
|
.start()
|
||||||
|
|
||||||
overlay.alpha = 0f
|
overlay.alpha = 0f
|
||||||
overlay.animate()
|
overlay.animate().alpha(1f).setDuration(200).start()
|
||||||
.alpha(1f)
|
|
||||||
.setDuration(200)
|
|
||||||
.start()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 收回面板 */
|
/** 收回面板 */
|
||||||
@@ -105,7 +100,6 @@ class PunchPanelView @JvmOverloads constructor(
|
|||||||
if (!isShowing) return
|
if (!isShowing) return
|
||||||
isShowing = false
|
isShowing = false
|
||||||
|
|
||||||
// 收回动画
|
|
||||||
panelContent.animate()
|
panelContent.animate()
|
||||||
.translationY(-panelContent.height.toFloat().coerceAtLeast(300f))
|
.translationY(-panelContent.height.toFloat().coerceAtLeast(300f))
|
||||||
.setDuration(200)
|
.setDuration(200)
|
||||||
@@ -113,49 +107,61 @@ class PunchPanelView @JvmOverloads constructor(
|
|||||||
.withEndAction {
|
.withEndAction {
|
||||||
visibility = GONE
|
visibility = GONE
|
||||||
tvNfcHint.visibility = GONE
|
tvNfcHint.visibility = GONE
|
||||||
|
tvPunchStatus.visibility = GONE
|
||||||
onDismiss?.invoke()
|
onDismiss?.invoke()
|
||||||
}
|
}
|
||||||
.start()
|
.start()
|
||||||
|
|
||||||
overlay.animate()
|
overlay.animate().alpha(0f).setDuration(200).start()
|
||||||
.alpha(0f)
|
|
||||||
.setDuration(200)
|
|
||||||
.start()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新按钮显示状态
|
* 更新面板显示状态
|
||||||
* @param state 考勤状态
|
* @param state 考勤状态
|
||||||
*/
|
*/
|
||||||
fun updateButtons(state: PunchUiState) {
|
fun updateButtons(state: PunchUiState) {
|
||||||
val onState = state.onPunchState
|
val onState = state.onPunchState
|
||||||
val offState = state.offPunchState
|
val offState = state.offPunchState
|
||||||
|
|
||||||
// 重置所有按钮
|
// 重置按钮
|
||||||
btnPunchIn.visibility = GONE
|
btnPunchIn.visibility = GONE
|
||||||
btnPunchOut.visibility = GONE
|
btnPunchOut.visibility = GONE
|
||||||
btnRevoke.visibility = GONE
|
btnRevoke.visibility = GONE
|
||||||
|
|
||||||
|
// 重置按钮权重(单按钮时 weight=1,双按钮时撤销0.4+下班0.6)
|
||||||
when {
|
when {
|
||||||
// 未上班打卡 → 显示"上班打卡"
|
// 未上班打卡 → "上班打卡"
|
||||||
onState == 0 -> {
|
onState == 0 -> {
|
||||||
btnPunchIn.visibility = VISIBLE
|
btnPunchIn.visibility = VISIBLE
|
||||||
|
setWeight(btnPunchIn, 1f)
|
||||||
|
// 无状态文字
|
||||||
|
tvPunchStatus.visibility = GONE
|
||||||
}
|
}
|
||||||
// 已上班,已下班 → 显示"撤销打卡" + "下班打卡"
|
// 已上班,已下班 → "撤销" + "下班打卡"
|
||||||
onState == 1 && offState == 1 -> {
|
onState == 1 && offState == 1 -> {
|
||||||
btnRevoke.visibility = VISIBLE
|
btnRevoke.visibility = VISIBLE
|
||||||
btnPunchOut.visibility = VISIBLE
|
btnPunchOut.visibility = VISIBLE
|
||||||
|
setWeight(btnRevoke, 0.4f)
|
||||||
|
setWeight(btnPunchOut, 0.6f)
|
||||||
|
// 状态:已下班 HH:MM
|
||||||
|
tvPunchStatus.visibility = VISIBLE
|
||||||
|
tvPunchStatus.text = "已下班 ${state.actualOffTime ?: ""}"
|
||||||
|
tvPunchStatus.setTextColor(context.getColor(R.color.text_secondary))
|
||||||
}
|
}
|
||||||
// 已上班,未下班 → 仅"下班打卡"
|
// 已上班,未下班 → "下班打卡"
|
||||||
onState == 1 && offState == 0 -> {
|
onState == 1 && offState == 0 -> {
|
||||||
btnPunchOut.visibility = VISIBLE
|
btnPunchOut.visibility = VISIBLE
|
||||||
|
setWeight(btnPunchOut, 1f)
|
||||||
|
// 状态:已上班 HH:MM
|
||||||
|
tvPunchStatus.visibility = VISIBLE
|
||||||
|
tvPunchStatus.text = "已上班 ${state.actualOnTime ?: ""}"
|
||||||
|
tvPunchStatus.setTextColor(context.getColor(R.color.success))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NFC 扫描中 → 显示提示
|
// NFC 扫描中
|
||||||
if (state.isNfcScanning) {
|
if (state.isNfcScanning) {
|
||||||
tvNfcHint.visibility = VISIBLE
|
tvNfcHint.visibility = VISIBLE
|
||||||
// 扫描中禁用按钮
|
|
||||||
btnPunchIn.isEnabled = false
|
btnPunchIn.isEnabled = false
|
||||||
btnPunchOut.isEnabled = false
|
btnPunchOut.isEnabled = false
|
||||||
btnRevoke.isEnabled = false
|
btnRevoke.isEnabled = false
|
||||||
@@ -167,8 +173,28 @@ class PunchPanelView @JvmOverloads constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 更新时钟显示 */
|
/**
|
||||||
|
* 更新 NFC 扫描倒计时
|
||||||
|
* @param secondsLeft 剩余秒数,-1 表示不显示
|
||||||
|
*/
|
||||||
|
fun updateNfcCountdown(secondsLeft: Int) {
|
||||||
|
if (secondsLeft > 0) {
|
||||||
|
tvNfcHint.text = "请贴近信标(${secondsLeft}s)"
|
||||||
|
tvNfcHint.visibility = VISIBLE
|
||||||
|
} else {
|
||||||
|
tvNfcHint.visibility = GONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 更新时钟 */
|
||||||
fun updateClock() {
|
fun updateClock() {
|
||||||
tvPunchTime.text = DateUtil.formatTimeShort()
|
tvPunchTime.text = DateUtil.formatTimeShort()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 设置 View 的 layout_weight */
|
||||||
|
private fun setWeight(view: View, weight: Float) {
|
||||||
|
val lp = view.layoutParams as LinearLayout.LayoutParams
|
||||||
|
lp.weight = weight
|
||||||
|
view.layoutParams = lp
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,12 +107,16 @@ class PunchViewModel @Inject constructor(
|
|||||||
handleNfcResult(nfcId, punchType)
|
handleNfcResult(nfcId, punchType)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. 超时自动关闭
|
// 3. 倒计时 + <20><>时自动关闭
|
||||||
nfcTimeoutJob = viewModelScope.launch {
|
nfcTimeoutJob = viewModelScope.launch {
|
||||||
delay(nfcTimeoutMs)
|
val totalSeconds = (nfcTimeoutMs / 1000).toInt()
|
||||||
|
for (i in totalSeconds downTo 1) {
|
||||||
|
_uiState.update { it.copy(nfcCountdown = i) }
|
||||||
|
delay(1000)
|
||||||
|
}
|
||||||
Timber.d("考勤: NFC超时自动关闭")
|
Timber.d("考勤: NFC超时自动关闭")
|
||||||
closeNfc()
|
closeNfc()
|
||||||
_uiState.update { it.copy(isNfcScanning = false, scanningPunchType = -1) }
|
_uiState.update { it.copy(isNfcScanning = false, scanningPunchType = -1, nfcCountdown = 0) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,6 +134,8 @@ class PunchViewModel @Inject constructor(
|
|||||||
// 关闭 NFC 硬件(不播关闭音效,成功/失败音效由 API 结果决定)
|
// 关闭 NFC 硬件(不播关闭音效,成功/失败音效由 API 结果决定)
|
||||||
nfcController.stopScan()
|
nfcController.stopScan()
|
||||||
nfcController.close()
|
nfcController.close()
|
||||||
|
// 清除倒计时
|
||||||
|
_uiState.update { it.copy(nfcCountdown = 0) }
|
||||||
|
|
||||||
// 调用打卡 API
|
// 调用打卡 API
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
@@ -266,6 +272,7 @@ data class PunchUiState(
|
|||||||
val actualOffTime: String? = null,
|
val actualOffTime: String? = null,
|
||||||
val isNfcScanning: Boolean = false,
|
val isNfcScanning: Boolean = false,
|
||||||
val scanningPunchType: Int = -1,
|
val scanningPunchType: Int = -1,
|
||||||
|
val nfcCountdown: Int = 0,
|
||||||
val punchResult: PunchResult? = null,
|
val punchResult: PunchResult? = null,
|
||||||
val errorMessage: String? = null
|
val errorMessage: String? = null
|
||||||
)
|
)
|
||||||
|
|||||||
22
app/src/main/res/drawable/bg_btn_pill_blue.xml
Normal file
22
app/src/main/res/drawable/bg_btn_pill_blue.xml
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- 药丸形蓝色渐变按钮(对应源码 #4CBAF1→#339AFB) -->
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:state_pressed="true">
|
||||||
|
<shape android:shape="rectangle">
|
||||||
|
<gradient android:startColor="#FF2B8AD4" android:endColor="#FF2780C8" android:angle="0" />
|
||||||
|
<corners android:radius="28dp" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
<item android:state_enabled="false">
|
||||||
|
<shape android:shape="rectangle">
|
||||||
|
<solid android:color="#FF333333" />
|
||||||
|
<corners android:radius="28dp" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<shape android:shape="rectangle">
|
||||||
|
<gradient android:startColor="#FF4CBAF1" android:endColor="#FF339AFB" android:angle="0" />
|
||||||
|
<corners android:radius="28dp" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
</selector>
|
||||||
16
app/src/main/res/drawable/bg_btn_pill_gray.xml
Normal file
16
app/src/main/res/drawable/bg_btn_pill_gray.xml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- 药丸形灰色按钮(撤销用) -->
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:state_pressed="true">
|
||||||
|
<shape android:shape="rectangle">
|
||||||
|
<solid android:color="#FF424242" />
|
||||||
|
<corners android:radius="28dp" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<shape android:shape="rectangle">
|
||||||
|
<solid android:color="#FF2C2C2E" />
|
||||||
|
<corners android:radius="28dp" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
</selector>
|
||||||
7
app/src/main/res/drawable/bg_dismiss_bar.xml
Normal file
7
app/src/main/res/drawable/bg_dismiss_bar.xml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- 底部收回指示条(灰色圆角短横线) -->
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
<solid android:color="#4DFFFFFF" />
|
||||||
|
<corners android:radius="2dp" />
|
||||||
|
</shape>
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
android:paddingStart="28dp"
|
android:paddingStart="28dp"
|
||||||
android:paddingTop="27dp"
|
android:paddingTop="27dp"
|
||||||
android:paddingEnd="28dp"
|
android:paddingEnd="28dp"
|
||||||
android:paddingBottom="20dp">
|
android:paddingBottom="8dp">
|
||||||
|
|
||||||
<!-- 时间显示(大字体,老年用户) -->
|
<!-- 时间显示(大字体,老年用户) -->
|
||||||
<TextView
|
<TextView
|
||||||
@@ -37,13 +37,23 @@
|
|||||||
android:textColor="@color/text_primary"
|
android:textColor="@color/text_primary"
|
||||||
android:textSize="48sp" />
|
android:textSize="48sp" />
|
||||||
|
|
||||||
<!-- NFC 扫描提示(默认隐藏) -->
|
<!-- 考勤状态文字:"已上班 07:02" / "已下班 17:05"(默认隐藏) -->
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvPunchStatus"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
android:textColor="@color/success"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
<!-- NFC 扫描提示 + 倒计时(默认隐藏) -->
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvNfcHint"
|
android:id="@+id/tvNfcHint"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="12dp"
|
||||||
android:text="请将手表贴近打卡信标"
|
android:text="请贴近信标"
|
||||||
android:textColor="@color/warning"
|
android:textColor="@color/warning"
|
||||||
android:textSize="18sp"
|
android:textSize="18sp"
|
||||||
android:visibility="gone" />
|
android:visibility="gone" />
|
||||||
@@ -57,48 +67,56 @@
|
|||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<!-- 上班打卡按钮 -->
|
<!-- 上班打卡按钮(药丸形,蓝色渐变) -->
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/btnPunchIn"
|
android:id="@+id/btnPunchIn"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="56dp"
|
android:layout_height="56dp"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:background="@drawable/bg_btn_primary"
|
android:background="@drawable/bg_btn_pill_blue"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:text="上班打卡"
|
android:text="上班打卡"
|
||||||
android:textColor="@color/text_primary"
|
android:textColor="@color/text_primary"
|
||||||
android:textSize="20sp"
|
android:textSize="20sp"
|
||||||
android:visibility="gone" />
|
android:visibility="gone" />
|
||||||
|
|
||||||
<!-- 下班打卡按钮 -->
|
<!-- 撤销打卡按钮(窄,灰底红字) -->
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/btnRevoke"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="56dp"
|
||||||
|
android:layout_weight="0.4"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:background="@drawable/bg_btn_pill_gray"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="撤销"
|
||||||
|
android:textColor="@color/error"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
<!-- 下班打卡按钮(宽,蓝色渐变) -->
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/btnPunchOut"
|
android:id="@+id/btnPunchOut"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="56dp"
|
android:layout_height="56dp"
|
||||||
android:layout_weight="1"
|
android:layout_weight="0.6"
|
||||||
android:background="@drawable/bg_btn_primary"
|
android:background="@drawable/bg_btn_pill_blue"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:text="下班打卡"
|
android:text="下班打卡"
|
||||||
android:textColor="@color/text_primary"
|
android:textColor="@color/text_primary"
|
||||||
android:textSize="20sp"
|
android:textSize="20sp"
|
||||||
android:visibility="gone" />
|
android:visibility="gone" />
|
||||||
|
|
||||||
<!-- 撤销打卡按钮 -->
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/btnRevoke"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="56dp"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:layout_marginEnd="8dp"
|
|
||||||
android:background="@drawable/bg_btn_secondary"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="撤销打卡"
|
|
||||||
android:textColor="@color/text_secondary"
|
|
||||||
android:textSize="18sp"
|
|
||||||
android:visibility="gone" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!-- 底部收回指示条 -->
|
||||||
|
<View
|
||||||
|
android:id="@+id/dismissBar"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:layout_height="4dp"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:background="@drawable/bg_dismiss_bar" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|||||||
Reference in New Issue
Block a user