feat: 进港查询筛选弹窗改为内容区嵌入式面板
将筛选条件弹框从 XPopup DrawerPopupView 改为嵌入 Activity 内容区的滑动面板, 使筛选面板从右侧滑入时不遮挡顶部蓝色标题栏,暗色遮罩也只覆盖内容区域。 同时修复首次弹出时因布局测量时序导致的闪烁问题。 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -3,6 +3,9 @@ package com.lukouguoji.gjj.activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.Gravity
|
||||
import android.view.View
|
||||
import android.widget.FrameLayout
|
||||
import com.alibaba.android.arouter.facade.annotation.Route
|
||||
import com.lukouguoji.gjj.R
|
||||
import com.lukouguoji.gjj.databinding.ActivityIntImpQueryBinding
|
||||
@@ -43,10 +46,66 @@ class IntImpQueryActivity :
|
||||
|
||||
viewModel.initAgentList()
|
||||
viewModel.initSpecialCodeList()
|
||||
viewModel.initFilterLists()
|
||||
|
||||
// 观察筛选面板显示状态
|
||||
viewModel.filterVisible.observe(this) { visible ->
|
||||
if (visible) showFilterPanel() else hideFilterPanel()
|
||||
}
|
||||
|
||||
viewModel.refresh()
|
||||
}
|
||||
|
||||
private fun showFilterPanel() {
|
||||
val panel = binding.filterPanel.root
|
||||
val overlay = binding.filterOverlay
|
||||
val panelWidth = window.decorView.width / 3
|
||||
|
||||
panel.layoutParams = (panel.layoutParams as FrameLayout.LayoutParams).apply {
|
||||
width = panelWidth
|
||||
gravity = Gravity.END
|
||||
}
|
||||
|
||||
// 先 INVISIBLE 完成测量,避免第一次显示时闪烁
|
||||
panel.visibility = View.INVISIBLE
|
||||
panel.translationX = panelWidth.toFloat()
|
||||
overlay.visibility = View.VISIBLE
|
||||
overlay.alpha = 0f
|
||||
|
||||
panel.post {
|
||||
panel.visibility = View.VISIBLE
|
||||
panel.animate().translationX(0f).setDuration(250).start()
|
||||
overlay.animate().alpha(1f).setDuration(250).start()
|
||||
}
|
||||
}
|
||||
|
||||
private fun hideFilterPanel() {
|
||||
val panel = binding.filterPanel.root
|
||||
val overlay = binding.filterOverlay
|
||||
|
||||
if (panel.visibility != View.VISIBLE) return
|
||||
|
||||
panel.animate()
|
||||
.translationX(panel.width.toFloat())
|
||||
.setDuration(250)
|
||||
.withEndAction { panel.visibility = View.GONE }
|
||||
.start()
|
||||
|
||||
overlay.animate()
|
||||
.alpha(0f)
|
||||
.setDuration(250)
|
||||
.withEndAction { overlay.visibility = View.GONE }
|
||||
.start()
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
if (viewModel.filterVisible.value == true) {
|
||||
viewModel.closeFilter()
|
||||
} else {
|
||||
super.onBackPressed()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun start(context: Context) {
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
package com.lukouguoji.gjj.dialog
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.ColorStateList
|
||||
import android.graphics.Color
|
||||
import android.view.View
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.lukouguoji.gjj.R
|
||||
import com.lukouguoji.gjj.databinding.DialogIntImpQueryFilterBinding
|
||||
import com.lukouguoji.module_base.base.BaseDialogModel
|
||||
import com.lxj.xpopup.XPopup
|
||||
import com.lxj.xpopup.enums.PopupPosition
|
||||
import dev.DevUtils
|
||||
import com.lukouguoji.module_base.util.DictUtils
|
||||
import dev.utils.app.info.KeyValue
|
||||
|
||||
/**
|
||||
* 国际进港查询筛选抽屉
|
||||
*/
|
||||
class IntImpQueryFilterDialogModel(
|
||||
val spCode: MutableLiveData<String>,
|
||||
val spCodeList: MutableLiveData<List<KeyValue>>,
|
||||
val flightNo: MutableLiveData<String>,
|
||||
val origin: MutableLiveData<String>,
|
||||
val awbType: MutableLiveData<String>,
|
||||
val businessType: MutableLiveData<String>,
|
||||
val goodsCn: MutableLiveData<String>,
|
||||
private val onConfirm: () -> Unit
|
||||
) : BaseDialogModel<DialogIntImpQueryFilterBinding>(DIALOG_TYPE_DRAWER) {
|
||||
|
||||
val awbTypeList = MutableLiveData<List<KeyValue>>(emptyList())
|
||||
|
||||
val businessTypeList = MutableLiveData<List<KeyValue>>(emptyList())
|
||||
|
||||
override fun layoutId() = R.layout.dialog_int_imp_query_filter
|
||||
|
||||
override fun onBuild(builder: XPopup.Builder) {
|
||||
super.onBuild(builder)
|
||||
builder.popupPosition(PopupPosition.Right)
|
||||
val activity = DevUtils.getTopActivity()
|
||||
val activityWidth = activity.window.decorView.width
|
||||
builder.maxWidth(activityWidth / 3)
|
||||
builder.popupWidth(activityWidth / 3)
|
||||
}
|
||||
|
||||
override fun onDialogCreated(context: Context) {
|
||||
binding.model = this
|
||||
binding.lifecycleOwner = context as? androidx.lifecycle.LifecycleOwner
|
||||
|
||||
val titleColor = Color.parseColor("#666666")
|
||||
binding.root.findViewById<TextView>(R.id.title_name)?.text = "筛选条件"
|
||||
binding.root.findViewById<TextView>(R.id.title_name)?.setTextColor(titleColor)
|
||||
binding.root.findViewById<TextView>(R.id.tool_tv_back)?.setTextColor(titleColor)
|
||||
binding.root.findViewById<ImageView>(R.id.tool_iv_back)?.imageTintList = ColorStateList.valueOf(titleColor)
|
||||
binding.root.findViewById<View>(R.id.toolbar)?.setBackgroundColor(Color.WHITE)
|
||||
|
||||
binding.root.findViewById<View>(R.id.tool_back)?.setOnClickListener {
|
||||
dismiss()
|
||||
}
|
||||
|
||||
DictUtils.getWaybillTypeList(type = "II", addAll = true, checkedValue = awbType.value) {
|
||||
awbTypeList.postValue(it)
|
||||
}
|
||||
DictUtils.getBusinessTypeList(type = "II", addAll = true, checkedValue = businessType.value) {
|
||||
businessTypeList.postValue(it)
|
||||
}
|
||||
}
|
||||
|
||||
fun onResetClick() {
|
||||
spCode.value = ""
|
||||
flightNo.value = ""
|
||||
origin.value = ""
|
||||
awbType.value = ""
|
||||
businessType.value = ""
|
||||
goodsCn.value = ""
|
||||
}
|
||||
|
||||
fun onConfirmClick() {
|
||||
dismiss()
|
||||
onConfirm()
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,6 @@ import android.content.Intent
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.lukouguoji.gjj.R
|
||||
import com.lukouguoji.gjj.activity.IntImpQueryEditActivity
|
||||
import com.lukouguoji.gjj.dialog.IntImpQueryFilterDialogModel
|
||||
import com.lukouguoji.gjj.holder.IntImpQueryViewHolder
|
||||
import com.lukouguoji.gjj.activity.IntImpQueryDetailsActivity
|
||||
import com.lukouguoji.module_base.base.BasePageViewModel
|
||||
@@ -59,6 +58,11 @@ class IntImpQueryViewModel : BasePageViewModel(), IOnItemClickListener {
|
||||
// ==================== 特码下拉 ====================
|
||||
val spCodeList = MutableLiveData<List<KeyValue>>(emptyList())
|
||||
|
||||
// ==================== 筛选面板 ====================
|
||||
val filterVisible = MutableLiveData(false)
|
||||
val awbTypeList = MutableLiveData<List<KeyValue>>(emptyList())
|
||||
val businessTypeList = MutableLiveData<List<KeyValue>>(emptyList())
|
||||
|
||||
// ==================== 筛选条件 ====================
|
||||
val spCode = MutableLiveData("")
|
||||
val flightNo = MutableLiveData("")
|
||||
@@ -80,17 +84,34 @@ class IntImpQueryViewModel : BasePageViewModel(), IOnItemClickListener {
|
||||
}
|
||||
|
||||
fun filterClick() {
|
||||
val filterDialog = IntImpQueryFilterDialogModel(
|
||||
spCode = spCode,
|
||||
spCodeList = spCodeList,
|
||||
flightNo = flightNo,
|
||||
origin = origin,
|
||||
awbType = awbType,
|
||||
businessType = businessType,
|
||||
goodsCn = goodsCn,
|
||||
onConfirm = { refresh() }
|
||||
)
|
||||
filterDialog.show()
|
||||
filterVisible.value = true
|
||||
}
|
||||
|
||||
fun closeFilter() {
|
||||
filterVisible.value = false
|
||||
}
|
||||
|
||||
fun resetFilter() {
|
||||
spCode.value = ""
|
||||
flightNo.value = ""
|
||||
origin.value = ""
|
||||
awbType.value = ""
|
||||
businessType.value = ""
|
||||
goodsCn.value = ""
|
||||
}
|
||||
|
||||
fun confirmFilter() {
|
||||
filterVisible.value = false
|
||||
refresh()
|
||||
}
|
||||
|
||||
fun initFilterLists() {
|
||||
DictUtils.getWaybillTypeList(type = "II", addAll = true, checkedValue = awbType.value) {
|
||||
awbTypeList.postValue(it)
|
||||
}
|
||||
DictUtils.getBusinessTypeList(type = "II", addAll = true, checkedValue = businessType.value) {
|
||||
businessTypeList.postValue(it)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getData() {
|
||||
|
||||
@@ -17,9 +17,21 @@
|
||||
android:background="@color/color_f2"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- 标题栏 -->
|
||||
<!-- 标题栏(始终在最上层,不被遮挡) -->
|
||||
<include layout="@layout/title_tool_bar" />
|
||||
|
||||
<!-- 内容区域(FrameLayout 包裹,筛选面板和遮罩只在此区域内) -->
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1">
|
||||
|
||||
<!-- 原有内容 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- 搜索区域 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
@@ -180,4 +192,29 @@
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 遮罩层(只覆盖内容区域) -->
|
||||
<View
|
||||
android:id="@+id/filter_overlay"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#80000000"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:onClick="@{()-> viewModel.closeFilter()}"
|
||||
android:visibility="gone" />
|
||||
|
||||
<!-- 筛选面板(从右侧滑入,只在内容区域内) -->
|
||||
<include
|
||||
android:id="@+id/filter_panel"
|
||||
layout="@layout/layout_int_imp_query_filter"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="end"
|
||||
android:visibility="gone"
|
||||
app:viewModel="@{viewModel}" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</layout>
|
||||
|
||||
@@ -5,24 +5,40 @@
|
||||
<import type="com.lukouguoji.module_base.ui.weight.data.layout.DataLayoutType" />
|
||||
|
||||
<variable
|
||||
name="model"
|
||||
type="com.lukouguoji.gjj.dialog.IntImpQueryFilterDialogModel" />
|
||||
name="viewModel"
|
||||
type="com.lukouguoji.gjj.viewModel.IntImpQueryViewModel" />
|
||||
</data>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/white"
|
||||
android:elevation="8dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- 状态栏占位 -->
|
||||
<View
|
||||
<!-- 筛选标题栏 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="25dp"
|
||||
android:background="@color/white" />
|
||||
android:layout_height="50dp"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingHorizontal="15dp">
|
||||
|
||||
<!-- 标题栏 -->
|
||||
<include layout="@layout/title_tool_bar" />
|
||||
<ImageView
|
||||
android:layout_width="15dp"
|
||||
android:layout_height="15dp"
|
||||
android:onClick="@{()-> viewModel.closeFilter()}"
|
||||
android:src="@mipmap/left_icon"
|
||||
android:tint="#666666" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:text="筛选条件"
|
||||
android:textColor="#666666"
|
||||
android:textSize="16sp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.divider.MaterialDivider
|
||||
android:layout_width="match_parent"
|
||||
@@ -42,72 +58,72 @@
|
||||
|
||||
<!-- 特码 -->
|
||||
<com.lukouguoji.module_base.ui.weight.data.layout.PadDataLayoutNew
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="10dp"
|
||||
hint='@{"请选择特码"}'
|
||||
list="@{model.spCodeList}"
|
||||
list="@{viewModel.spCodeList}"
|
||||
title='@{"特码"}'
|
||||
titleLength="@{4}"
|
||||
type="@{DataLayoutType.SPINNER}"
|
||||
value='@={model.spCode}'
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="10dp" />
|
||||
value='@={viewModel.spCode}' />
|
||||
|
||||
<!-- 航班号 -->
|
||||
<com.lukouguoji.module_base.ui.weight.data.layout.PadDataLayoutNew
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="10dp"
|
||||
hint='@{"请输入航班号"}'
|
||||
title='@{"航班号"}'
|
||||
titleLength="@{4}"
|
||||
type="@{DataLayoutType.INPUT}"
|
||||
value='@={model.flightNo}'
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="10dp" />
|
||||
value='@={viewModel.flightNo}' />
|
||||
|
||||
<!-- 始发港 -->
|
||||
<com.lukouguoji.module_base.ui.weight.data.layout.PadDataLayoutNew
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="10dp"
|
||||
hint='@{"请输入始发港"}'
|
||||
title='@{"始发港"}'
|
||||
titleLength="@{4}"
|
||||
type="@{DataLayoutType.INPUT}"
|
||||
value='@={model.origin}'
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="10dp" />
|
||||
value='@={viewModel.origin}' />
|
||||
|
||||
<!-- 运单类型 -->
|
||||
<com.lukouguoji.module_base.ui.weight.data.layout.PadDataLayoutNew
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="10dp"
|
||||
hint='@{"请选择运单类型"}'
|
||||
list="@{model.awbTypeList}"
|
||||
list="@{viewModel.awbTypeList}"
|
||||
title='@{"运单类型"}'
|
||||
titleLength="@{4}"
|
||||
type="@{DataLayoutType.SPINNER}"
|
||||
value='@={model.awbType}'
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="10dp" />
|
||||
value='@={viewModel.awbType}' />
|
||||
|
||||
<!-- 业务类型 -->
|
||||
<com.lukouguoji.module_base.ui.weight.data.layout.PadDataLayoutNew
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="10dp"
|
||||
hint='@{"请选择业务类型"}'
|
||||
list="@{model.businessTypeList}"
|
||||
list="@{viewModel.businessTypeList}"
|
||||
title='@{"业务类型"}'
|
||||
titleLength="@{4}"
|
||||
type="@{DataLayoutType.SPINNER}"
|
||||
value='@={model.businessType}'
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="10dp" />
|
||||
value='@={viewModel.businessType}' />
|
||||
|
||||
<!-- 品名(中) -->
|
||||
<com.lukouguoji.module_base.ui.weight.data.layout.PadDataLayoutNew
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="10dp"
|
||||
hint='@{"请输入品名"}'
|
||||
title='@{"品名(中)"}'
|
||||
titleLength="@{4}"
|
||||
type="@{DataLayoutType.INPUT}"
|
||||
value='@={model.goodsCn}'
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="10dp" />
|
||||
value='@={viewModel.goodsCn}' />
|
||||
|
||||
<!-- 底部按钮区域 -->
|
||||
<LinearLayout
|
||||
@@ -127,7 +143,7 @@
|
||||
android:layout_weight="1"
|
||||
android:background="@drawable/bg_primary_radius_4"
|
||||
android:gravity="center"
|
||||
android:onClick="@{()-> model.onResetClick()}"
|
||||
android:onClick="@{()-> viewModel.resetFilter()}"
|
||||
android:text="重置"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="16sp" />
|
||||
@@ -138,7 +154,7 @@
|
||||
android:layout_weight="1"
|
||||
android:background="@drawable/bg_primary_radius_4"
|
||||
android:gravity="center"
|
||||
android:onClick="@{()-> model.onConfirmClick()}"
|
||||
android:onClick="@{()-> viewModel.confirmFilter()}"
|
||||
android:text="搜索"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="16sp" />
|
||||
Reference in New Issue
Block a user