app/src/main/java/com/xw/yunwei/push/MessageHandler.kt
@@ -136,7 +136,6 @@ } 9, 10 -> { // 变更协议内容 if (strategy == 9 && isPush) return if (strategy == 9) { currentShowActivity.startActivity( Intent(currentShowActivity, ProtocolActivity::class.java) app/src/main/java/com/xw/yunwei/ui/task/accident/handle/AccidentProcessActivity.kt
@@ -3,10 +3,18 @@ import android.annotation.SuppressLint import android.net.Uri import android.os.Bundle import android.text.StaticLayout import android.text.TextPaint import android.text.TextUtils import android.util.TypedValue import android.view.Gravity import android.view.View import android.view.ViewGroup import android.view.WindowManager import android.widget.LinearLayout import android.widget.TextView import androidx.core.os.bundleOf import androidx.core.view.isVisible import androidx.databinding.DataBindingUtil import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.LinearLayoutManager @@ -29,11 +37,15 @@ import com.xw.yunwei.constants.Key import com.xw.yunwei.databinding.ActivityAccidentProcessBinding import com.xw.yunwei.databinding.DialogAccidentFilterBinding import com.xw.yunwei.extension.colorIdToColorValue import com.xw.yunwei.extension.dpToPx import com.xw.yunwei.extension.spToPx import com.xw.yunwei.model.TaskAccidentModel import com.xw.yunwei.ui.task.create.LeftCategoryAdapter import com.xw.yunwei.ui.task.create.RightItemAdapter import com.xw.yunwei.utils.DialogFactory import com.xw.yunwei.utils.PictureSelectorFactory import kotlin.math.ceil /** * 事故处理页面 @@ -56,6 +68,9 @@ /** 右侧事故子类 Adapter */ private lateinit var rightAdapter: RightItemAdapter //用于测量 private val textPaint = TextPaint() companion object { //获取跳转该页面参数 @@ -86,14 +101,16 @@ resources.getColor(R.color.white), "shape_blue_5_bg_4" ) viewModel.getTypeList { binding.tvAccidentFilter.text = if (viewModel.getSelectType().isEmpty()) "" else "选好了" } viewModel.getTypeList { refreshFilterData() } } override fun setListener() { super.setListener() binding.llFilters.setOnClickListener { viewModel.getTypeList { showFilterDialog() } } // 点击事故类型筛选按钮,先拉取类型列表再弹窗 binding.tvAccidentFilter.setOnClickListener { viewModel.getTypeList { @@ -280,10 +297,7 @@ } // 弹窗关闭时更新筛选按钮文案(已选则显示"选好了") filterDialog!!.setOnDismissListener { binding.tvAccidentFilter.text = if (viewModel.getSelectType().isEmpty()) "" else "选好了" } filterDialog!!.setOnDismissListener { refreshFilterData() } } filterDialog?.show() @@ -312,4 +326,112 @@ rightAdapter = RightItemAdapter(viewModel.categories[0].items) bind.rightRecyclerView.adapter = rightAdapter } //刷新筛选数据 private fun refreshFilterData() { val selectTypeName = viewModel.getSelectTypeName() binding.llFilters.isVisible = selectTypeName.isNotEmpty() binding.tvAccidentFilter.isVisible = selectTypeName.isEmpty() binding.llFilters.removeAllViews() if (selectTypeName.isNotEmpty()) { binding.llFilters.post { fill(binding.llFilters, binding.llFilters.width, selectTypeName) } } } //填充数据 private fun fill(parent: LinearLayout, parenWidth: Int, list: List<String>) { val itemWidths = list.map { calculationItemViewWidth(it, 8, 4) } val pair = findWrapIndex(parenWidth, itemWidths) val numItemWidth = if (pair.second) { calculationItemViewWidth("+${list.size - pair.first - 1}", 4, 0) } else { 0 } val needWeight = pair.second && pair.first == 0 && itemWidths.first() >= (parenWidth - numItemWidth) list.subList(0, pair.first + 1).forEach { parent.addView(getFilterItemView(it, 8, 4, if (needWeight) 1f else 0f)) } if (pair.second) { parent.addView(getFilterItemView("+${list.size - pair.first - 1}", 4, 0)) } } //查找合适的下标 private fun findWrapIndex( parenWidth: Int, list: List<Int>, needLastNum: Boolean = true ): Pair<Int, Boolean> { val size = list.size var itemWidthCount = 0 for ((index, itemWidth) in list.withIndex()) { if (itemWidthCount + itemWidth == parenWidth) { return Pair(index, false) } if (itemWidthCount + itemWidth > parenWidth) { if (needLastNum) { if (index == 0) { return Pair(index, size > 1) } //末尾的计数 val numberItemWidth = calculationItemViewWidth("+${size - index}", 4, 0) //剩余内容宽度 val surplusContentWidth = parenWidth - numberItemWidth //将剩余内容宽度带入,重新找适合的下标 val wrapIndex = findWrapIndex(surplusContentWidth, list, false) return Pair(wrapIndex.first, true) } else { return Pair(index - 1, false) } } itemWidthCount += itemWidth } return Pair(size - 1, false) } //计算item控件宽度 private fun calculationItemViewWidth(item: String, padHorizontal: Int, marginEnd: Int): Int { textPaint.textSize = 12f.spToPx(this@AccidentProcessActivity) val sl = StaticLayout.Builder.obtain(item, 0, item.length, textPaint, Int.MAX_VALUE) .setIncludePad(false) // 看你期望要不要 TextView 默认那套 pad .build() val line0Width = sl.getLineWidth(0) // 这一行的“排版宽度” val padWidth = padHorizontal.dpToPx(this) * 2//两侧内间距宽度 return ceil(line0Width + padWidth + marginEnd.dpToPx(this)).toInt() } //获取筛选item控件 private fun getFilterItemView( item: String, padHorizontal: Int, marginEnd: Int, weight: Float = 0f, ): View { return TextView(this).apply { setBackgroundResource(com.xw.yunwei.R.drawable.shape_gray11_bg_4) layoutParams = LinearLayout.LayoutParams( if (weight > 0) 0 else LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT, weight ).apply { this.marginEnd = marginEnd.dpToPx(this@AccidentProcessActivity) } setPadding( padHorizontal.dpToPx(this@AccidentProcessActivity), 4.dpToPx(this@AccidentProcessActivity), padHorizontal.dpToPx(this@AccidentProcessActivity), 4.dpToPx(this@AccidentProcessActivity), ) setTextColor(R.color.gray_9.colorIdToColorValue(this@AccidentProcessActivity)) setTextSize(TypedValue.COMPLEX_UNIT_SP, 12f) text = item maxLines = 1 ellipsize = TextUtils.TruncateAt.END } } } app/src/main/java/com/xw/yunwei/ui/task/accident/handle/AccidentProcessVM.kt
@@ -264,4 +264,14 @@ categories.forEach { items.addAll(it.items) } return items.filter { it.isSelected }.map { it.id }.joinToString() } /** * 获取当前已选中的事故类型 name 列表 * */ fun getSelectTypeName(): List<String> { val items = mutableListOf<Item>() categories.forEach { items.addAll(it.items) } return items.filter { it.isSelected }.map { it.name } } } app/src/main/java/com/xw/yunwei/ui/task/create/CreateTaskActivity.kt
@@ -3,9 +3,17 @@ import android.annotation.SuppressLint import android.net.Uri import android.os.Bundle import android.text.StaticLayout import android.text.TextPaint import android.text.TextUtils import android.util.TypedValue import android.view.Gravity import android.view.View import android.view.ViewGroup import android.view.WindowManager import android.widget.LinearLayout import android.widget.TextView import androidx.core.view.isVisible import androidx.databinding.DataBindingUtil import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.LinearLayoutManager @@ -34,10 +42,14 @@ import com.xw.yunwei.BaseBusinessActivity import com.xw.yunwei.databinding.ActivityCreateTaskBinding import com.xw.yunwei.databinding.DialogAccidentFilterBinding import com.xw.yunwei.extension.colorIdToColorValue import com.xw.yunwei.extension.dpToPx import com.xw.yunwei.extension.spToPx import com.xw.yunwei.model.CacheAccidentModel import com.xw.yunwei.model.CarModel import com.xw.yunwei.utils.DialogFactory import com.xw.yunwei.utils.PictureSelectorFactory import kotlin.math.ceil /** * 事故上报页面 @@ -53,19 +65,25 @@ * * 实现 [GpsHelper.OnMapLocation] 接口以接收定位结果。 */ class CreateTaskActivity : BaseBusinessActivity<ActivityCreateTaskBinding, CreateTaskVM>(), GpsHelper.OnMapLocation { class CreateTaskActivity : BaseBusinessActivity<ActivityCreateTaskBinding, CreateTaskVM>(), GpsHelper.OnMapLocation { override fun getBindingVariable() = BR.viewModel /** 事故类型筛选弹窗 */ private var filterDialog: MaterialDialog? = null /** 左侧事故大类 Adapter */ private lateinit var leftAdapter: LeftCategoryAdapter /** 右侧事故子类 Adapter */ private lateinit var rightAdapter: RightItemAdapter /** 高德定位辅助类 */ // lateinit var gpsHelper : GpsHelper /** 从 MMKV 恢复的草稿数据 */ var cacheData: CacheAccidentModel? = null //用于测量 private val textPaint = TextPaint() override fun myCreate(savedInstanceState: Bundle?) { super.myCreate(savedInstanceState) @@ -95,8 +113,8 @@ viewModel.taskLevel.value = it.taskLevel viewModel.taskDesc.value = it.taskDesc viewModel.adapter.setList(it.files) binding.tvAccidentFilter.text = if (viewModel.getSelectType().isEmpty()) "" else "选好了" } ?: run{ viewModel.selectCar.value = selectCar } refreshFilterData() } ?: run { viewModel.selectCar.value = selectCar } // if (viewModel.selectCar.value == null) { // startActivityForResult( @@ -115,7 +133,7 @@ override fun setObservable() { super.setObservable() // 监听选中车辆变化,更新车辆信息布局 viewModel.selectCar.observe(this){ viewModel.selectCar.observe(this) { initCarLayout(it) } viewModel.carLocationInfo.observe(this) { @@ -125,9 +143,14 @@ override fun setListener() { super.setListener() binding.llFilters.setOnClickListener { viewModel.getTypeList { showFilterDialog() } } // 点击事故类型筛选按钮,先拉取类型列表再弹窗 binding.tvAccidentFilter.setOnClickListener { viewModel.getTypeList{ viewModel.getTypeList { showFilterDialog() } } @@ -150,9 +173,7 @@ imgList.add(item1.localPath.ifEmpty { item1.url }) } ShowImgListDialog( this@CreateTaskActivity, imgList, imgList.indexOf(item.localPath) this@CreateTaskActivity, imgList, imgList.indexOf(item.localPath) ).show() } @@ -183,9 +204,7 @@ @SuppressLint("SourceLockedOrientationActivity") private fun enterGallery() { PictureSelectorFactory.enterGallery( this, viewModel.maxSize - viewModel.adapter.data.size, resultCallbackListener this, viewModel.maxSize - viewModel.adapter.data.size, resultCallbackListener ) } @@ -194,7 +213,7 @@ */ // 拍照 private fun takeAPhotograph() { PictureSelectorFactory.takeAPhotograph(this,resultCallbackListener) PictureSelectorFactory.takeAPhotograph(this, resultCallbackListener) } /** @@ -209,11 +228,12 @@ dataList.addAll(viewModel.adapter.data) for (item in selectList) { val path: String = item.availablePath var imgPath = if (PictureMimeType.isContent(path) && !item.isCut && !item.isCompressed) { UriUtils.uri2File(Uri.parse(path)).absolutePath } else { path } var imgPath = if (PictureMimeType.isContent(path) && !item.isCut && !item.isCompressed) { UriUtils.uri2File(Uri.parse(path)).absolutePath } else { path } dataList.add(FileSelectBean(localPath = imgPath, type = "img")) } viewModel.adapter.setList(dataList) @@ -266,7 +286,7 @@ } // 右侧按钮:确认选择并关闭弹窗 it.btnRight.setOnClickListener { if(viewModel.getSelectType().isEmpty()){ if (viewModel.getSelectType().isEmpty()) { ToastUtilCommon.showWarn("还未选择事故类型") return@setOnClickListener } @@ -274,7 +294,7 @@ } // 确定按钮:确认选择并关闭弹窗 it.sure.setOnClickListener { if(viewModel.getSelectType().isEmpty()){ if (viewModel.getSelectType().isEmpty()) { ToastUtilCommon.showWarn("还未选择事故类型") return@setOnClickListener } @@ -284,9 +304,7 @@ } // 弹窗关闭时更新筛选按钮文案(已选则显示"选好了") filterDialog!!.setOnDismissListener { binding.tvAccidentFilter.text = if(viewModel.getSelectType().isEmpty()) "" else "选好了" } filterDialog!!.setOnDismissListener { refreshFilterData() } } filterDialog?.show() @@ -331,8 +349,11 @@ * @param item 当前选中的车辆信息 */ @SuppressLint("SetTextI18n") private fun initCarLayout(item: CarModel){ ViewAdapter.loadImage(binding.icon, ImageDefault(item.getShowVehiclePicture(), com.xw.yunwei.R.mipmap.img_work_car)) private fun initCarLayout(item: CarModel) { ViewAdapter.loadImage( binding.icon, ImageDefault(item.getShowVehiclePicture(), com.xw.yunwei.R.mipmap.img_work_car) ) binding.name.text = item.plateNumber binding.color.text = "${item.vehicleColor} | 车身编码:${item.vehicleCode}" @@ -344,34 +365,22 @@ // 1=运营中 2=维修中 3=已收车 4=车辆异常 when (item.operatingStatus) { 1 -> { setStatus( getResColor(R.color.blue_5), R.color.blue_1 ) setStatus(getResColor(R.color.blue_5), R.color.blue_1) binding.status.text = "运营中" } 2 -> { setStatus( getResColor(R.color.red_5), R.color.red_1 ) setStatus(getResColor(R.color.red_5), R.color.red_1) binding.status.text = "维修中" } 3 -> { setStatus( getResColor(R.color.gray_7), R.color.gray_3 ) setStatus(getResColor(R.color.gray_7), R.color.gray_3) binding.status.text = "已收车" } 4 -> { setStatus( getResColor(R.color.orange_5), R.color.orange_1 ) setStatus(getResColor(R.color.orange_5), R.color.orange_1) binding.status.text = "车辆异常" } } @@ -419,7 +428,10 @@ super.onBackPressedHandel() } else { CommonDialog.showTipsDialog( this, "是否保存当前事故数据", "不保存", "保存", this, "是否保存当前事故数据", "不保存", "保存", leftBlock = { super.onBackPressedHandel() true @@ -431,4 +443,112 @@ }) } } //刷新筛选数据 private fun refreshFilterData() { val selectTypeName = viewModel.getSelectTypeName() binding.llFilters.isVisible = selectTypeName.isNotEmpty() binding.tvAccidentFilter.isVisible = selectTypeName.isEmpty() binding.llFilters.removeAllViews() if (selectTypeName.isNotEmpty()) { binding.llFilters.post { fill(binding.llFilters, binding.llFilters.width, selectTypeName) } } } //填充数据 private fun fill(parent: LinearLayout, parenWidth: Int, list: List<String>) { val itemWidths = list.map { calculationItemViewWidth(it, 8, 4) } val pair = findWrapIndex(parenWidth, itemWidths) val numItemWidth = if (pair.second) { calculationItemViewWidth("+${list.size - pair.first - 1}", 4, 0) } else { 0 } val needWeight = pair.second && pair.first == 0 && itemWidths.first() >= (parenWidth - numItemWidth) list.subList(0, pair.first + 1).forEach { parent.addView(getFilterItemView(it, 8, 4, if (needWeight) 1f else 0f)) } if (pair.second) { parent.addView(getFilterItemView("+${list.size - pair.first - 1}", 4, 0)) } } //查找合适的下标 private fun findWrapIndex( parenWidth: Int, list: List<Int>, needLastNum: Boolean = true ): Pair<Int, Boolean> { val size = list.size var itemWidthCount = 0 for ((index, itemWidth) in list.withIndex()) { if (itemWidthCount + itemWidth == parenWidth) { return Pair(index, false) } if (itemWidthCount + itemWidth > parenWidth) { if (needLastNum) { if (index == 0) { return Pair(index, size > 1) } //末尾的计数 val numberItemWidth = calculationItemViewWidth("+${size - index}", 4, 0) //剩余内容宽度 val surplusContentWidth = parenWidth - numberItemWidth //将剩余内容宽度带入,重新找适合的下标 val wrapIndex = findWrapIndex(surplusContentWidth, list, false) return Pair(wrapIndex.first, true) } else { return Pair(index - 1, false) } } itemWidthCount += itemWidth } return Pair(size - 1, false) } //计算item控件宽度 private fun calculationItemViewWidth(item: String, padHorizontal: Int, marginEnd: Int): Int { textPaint.textSize = 12f.spToPx(this@CreateTaskActivity) val sl = StaticLayout.Builder.obtain(item, 0, item.length, textPaint, Int.MAX_VALUE) .setIncludePad(false) // 看你期望要不要 TextView 默认那套 pad .build() val line0Width = sl.getLineWidth(0) // 这一行的“排版宽度” val padWidth = padHorizontal.dpToPx(this) * 2//两侧内间距宽度 return ceil(line0Width + padWidth + marginEnd.dpToPx(this)).toInt() } //获取筛选item控件 private fun getFilterItemView( item: String, padHorizontal: Int, marginEnd: Int, weight: Float = 0f, ): View { return TextView(this).apply { setBackgroundResource(com.xw.yunwei.R.drawable.shape_gray11_bg_4) layoutParams = LinearLayout.LayoutParams( if (weight > 0) 0 else LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT, weight ).apply { this.marginEnd = marginEnd.dpToPx(this@CreateTaskActivity) } setPadding( padHorizontal.dpToPx(this@CreateTaskActivity), 4.dpToPx(this@CreateTaskActivity), padHorizontal.dpToPx(this@CreateTaskActivity), 4.dpToPx(this@CreateTaskActivity), ) setTextColor(R.color.gray_9.colorIdToColorValue(this@CreateTaskActivity)) setTextSize(TypedValue.COMPLEX_UNIT_SP, 12f) text = item maxLines = 1 ellipsize = TextUtils.TruncateAt.END } } } app/src/main/java/com/xw/yunwei/ui/task/create/CreateTaskVM.kt
@@ -57,11 +57,13 @@ // } /** 任务紧急等级:0 = P0(最紧急), 1 = P1 , 2 = P2 , 3 = P3(最不紧急),默认 P3 */ val taskLevel: MutableLiveData<Int> = MutableLiveData(2) /** 任务描述文本 */ val taskDesc = MutableLiveData("") //车辆实时位置信息 val carLocationInfo = MutableLiveData<VehicleLocationInfo?>() /** 页面点击事件统一处理:选择车辆、等级切换、提交 */ var onClick = View.OnClickListener { when (it.id) { @@ -83,6 +85,7 @@ /** 图片选择适配器 */ lateinit var adapter: ImageSelectAdapter /** 图片最大可上传数量 */ val maxSize = 6 @@ -217,6 +220,16 @@ } /** * 获取当前已选中的事故类型 name 列表 * */ fun getSelectTypeName(): List<String> { val items = mutableListOf<Item>() categories.forEach { items.addAll(it.items) } return items.filter { it.isSelected }.map { it.name } } /** * 获取当前数据填写情况,用于判断是否需要保存草稿 * * 当事故类型、任务等级、任务描述、相关照片均未填写时返回 null, app/src/main/java/com/xw/yunwei/ui/task/list/TaskListAdapter.kt
@@ -298,7 +298,7 @@ bind.second.text = if (list[2] < 10) "0${list[2]}" else "${list[2]}" // 当剩余时间不足3分钟时,切换为红色警示样式 val showRed = list[0] == 0L && list[1] <= 3L val showRed = list[0] == 0L && list[1] <= 2L val countdownId = if (showRed) R.mipmap.img_task_item_top_bg_red else R.mipmap.img_task_item_top_bg_blue app/src/main/java/com/xw/yunwei/ui/task/selectCar/SelectCarVM.kt
@@ -35,9 +35,13 @@ val filterStatus = listOf( "全部", "运营中", "维修中", "出车中", "接单中", "停止接单", "已收车", "车辆异常", "维修中", "充电中", ) /** 用户已选中的区域列表 */ val selectArea = mutableListOf<AreaModel>() @@ -77,8 +81,8 @@ map["pageNum"] = index map["pageSize"] = pageSize map["plateNumber"] = search.value // 查询参数 // 运营状态:1运营中 2维修中 3已收车 4车辆异常;选择"全部"或不选时不传 map["status"] = // 1=运营中,2=出车中,3=接单中,4=停止接单,5=已收车,6=车辆异常,7=维修中,8=充电中 map["vehicleStatus"] = if (selectStatus.contains("全部")) null else { if (selectStatus.isNotEmpty()) selectStatus.map { filterStatus.indexOf(it) }.joinToString(",") app/src/main/java/com/xw/yunwei/ui/user/mine/set/SetActivity.kt
@@ -97,7 +97,7 @@ .updateForceUpdateFlag(it.forceUpdateFlag ?: 0) .show() } else { ToastUtilCommon.show("当前也是最新版本") ToastUtilCommon.show("当前已是最新版本") } } } app/src/main/java/com/xw/yunwei/ui/work/car/manage/CarManageVM.kt
@@ -16,9 +16,13 @@ val filterStatus = listOf( "全部", "运营中", "维修中", "出车中", "接单中", "停止接单", "已收车", "车辆异常", "维修中", "充电中", ) val selectArea = mutableListOf<AreaModel>() @@ -37,12 +41,12 @@ val map = mutableMapOf<String, Any?>() map["pageNum"] = 1 map["pageSize"] = 1000 map["status"] = map["vehicleStatus"] = if (selectStatus.contains("全部")) null else { if (selectStatus.isNotEmpty()) selectStatus.map { filterStatus.indexOf(it) } .joinToString(",") else null // 运营状态 1运营中 2维修中 3已收车 4车辆异常 else null // 1=运营中,2=出车中,3=接单中,4=停止接单,5=已收车,6=车辆异常,7=维修中,8=充电中 } map["electronicId"] = if (selectArea.isNotEmpty()) selectArea.map { it.id ?: 0L }.joinToString(",") app/src/main/res/layout/activity_accident_process.xml
@@ -292,11 +292,19 @@ android:textColor="@color/gray_9" android:textSize="@dimen/sp_16" /> <LinearLayout android:id="@+id/ll_filters" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="@dimen/dp_20" android:layout_weight="1" android:gravity="center_vertical|end" android:orientation="horizontal" /> <androidx.appcompat.widget.AppCompatTextView android:id="@+id/tvAccidentFilter" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="@dimen/dp_20" android:layout_weight="1" android:gravity="end" android:hint="请选择" app/src/main/res/layout/activity_create_task.xml
@@ -167,11 +167,19 @@ android:textColor="@color/gray_9" android:textSize="@dimen/sp_16" /> <LinearLayout android:id="@+id/ll_filters" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="@dimen/dp_20" android:layout_weight="1" android:gravity="center_vertical|end" android:orientation="horizontal" /> <androidx.appcompat.widget.AppCompatTextView android:id="@+id/tvAccidentFilter" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="@dimen/dp_20" android:layout_weight="1" android:gravity="end" android:hint="请选择" app/src/main/res/layout/activity_scheduling.xml
@@ -256,6 +256,8 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@color/orange_1" android:gravity="center" android:minWidth="@dimen/dp_49" android:paddingHorizontal="@dimen/dp_8" android:paddingVertical="@dimen/dp_2" android:text="未打卡" @@ -339,6 +341,8 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@color/orange_1" android:gravity="center" android:minWidth="@dimen/dp_49" android:paddingHorizontal="@dimen/dp_8" android:paddingVertical="@dimen/dp_2" android:text="未打卡"