优化语言

This commit is contained in:
fengjignqi
2026-09-24 17:23:47 +08:00
parent 495e43f017
commit 3d926d3d60
71 changed files with 1896 additions and 542 deletions

View File

@@ -22,7 +22,7 @@ class BindDeviceActivity: BaseActivity<BindDeviceLayoutBinding, DevicePresenter>
}
override fun createPresenter(): DevicePresenter? {
return DevicePresenter(DeviceImpl())
return DevicePresenter(DeviceImpl(mContext), mContext)
}
override fun initWindows() {
@@ -35,7 +35,7 @@ class BindDeviceActivity: BaseActivity<BindDeviceLayoutBinding, DevicePresenter>
}
override fun initView(savedInstanceState: Bundle?) {
binding.includedTitle.tvTitle.setText(R.string.bind_device)
binding.includedTitle.tvTitle.setText(R.string.bind_device) //绑定设备
listOf(
binding.tvBind,
binding.includedTitle.imgBack,
@@ -67,11 +67,11 @@ class BindDeviceActivity: BaseActivity<BindDeviceLayoutBinding, DevicePresenter>
?.trim()
.orEmpty()
if (imei.isBlank()) {
showMessage("请输入设备编码")
showMessage(mContext.getString(R.string.i18n_022)) //请输入设备编码
return
}
if (name.isBlank()) {
showMessage("请输入设备名称")
showMessage(mContext.getString(R.string.i18n_024)) //请输入设备名称
return
}
presenter?.bindDevice(imei, name)
@@ -92,3 +92,5 @@ class BindDeviceActivity: BaseActivity<BindDeviceLayoutBinding, DevicePresenter>
}

View File

@@ -33,7 +33,7 @@ class DeviceDetailActivity :
}
override fun createPresenter(): DevicePresenter? {
return DevicePresenter(DeviceImpl())
return DevicePresenter(DeviceImpl(mContext), mContext)
}
override fun initWindows() {
@@ -48,10 +48,10 @@ class DeviceDetailActivity :
override fun initView(savedInstanceState: Bundle?) {
device = intent.getSerializableExtra(EXTRA_DEVICE) as? DeviceEntity
binding.includeTitle.tvTitle.text = device?.name ?: "设备详情"
binding.includeTitle.tvTitle.text = device?.name ?: mContext.getString(R.string.i18n_074) //设备详情
val deviceNo = device?.deviceNo
if (deviceNo.isNullOrBlank()) {
showError("设备信息无效")
showError(mContext.getString(R.string.i18n_075)) //设备信息无效
} else {
presenter?.getDeviceDetail(deviceNo)
}
@@ -75,7 +75,7 @@ class DeviceDetailActivity :
R.id.img_switch_ctrl ->{
val currentDevice = device ?: return
if (currentDevice.status == "0") {
showMessage("设备已经离线")
showMessage(mContext.getString(R.string.i18n_076)) //设备已经离线
return
}
@@ -102,7 +102,7 @@ class DeviceDetailActivity :
override fun getDeviceDetailSuccess(device: DeviceEntity) {
this.device = device
binding.includeTitle.tvTitle.text = device.name
binding.tvBind.text = "设备编号:${device.deviceNo}"
binding.tvBind.text = getString(R.string.device_number_value, device.deviceNo) //设备编号:%1$s
updateCoverControlState(device.hoodCoverOn == HOOD_COVER_ON)
}
@@ -124,7 +124,11 @@ class DeviceDetailActivity :
private fun updateCoverControlState(coverOn: Boolean) {
binding.switchCtrl.isChecked = coverOn
binding.imgSwitchCtrl.setImageResource(
if (coverOn) R.mipmap.icon_switch_on else R.mipmap.icon_switch_off
if (coverOn) {
R.mipmap.icon_switch_on
} else {
R.mipmap.icon_switch_off
}
)
}
@@ -134,3 +138,5 @@ class DeviceDetailActivity :
}

View File

@@ -35,7 +35,7 @@ class DeviceFragment : BaseFragment<FragmentHomeBinding, DevicePresenter>(),
}
override fun createPresenter(): DevicePresenter {
return DevicePresenter(DeviceImpl())
return DevicePresenter(DeviceImpl(mContext), mContext)
}
override fun initView(savedInstanceState: Bundle?) {
@@ -59,11 +59,11 @@ class DeviceFragment : BaseFragment<FragmentHomeBinding, DevicePresenter>(),
view,
onRename = {
showEditDialog(
title = "重命名设备",
label = "设备名称",
title = mContext.getString(R.string.i18n_077), //重命名设备
label = mContext.getString(R.string.i18n_023), //设备名称
hint = device.name,
tip = "最多支持20个字符,支持中英文、数字和字符。",
confirmText = "确认修改",
tip = mContext.getString(R.string.i18n_078), //最多支持20个字符,支持中英文、数字和字符。
confirmText = mContext.getString(R.string.i18n_042), //确认修改
click = object : OnDialogClick {
override fun onCancelClick() {
}
@@ -76,10 +76,10 @@ class DeviceFragment : BaseFragment<FragmentHomeBinding, DevicePresenter>(),
},
onUnbind = {//解绑设备
showDialogtext(
"提示",
"确定要解绑该设备?",
"确定",
"取消",
mContext.getString(R.string.i18n_063), //提示
mContext.getString(R.string.i18n_079), //确定要解绑该设备?
mContext.getString(R.string.i18n_027), //确定
mContext.getString(R.string.i18n_041), //取消
object : OnDialogClick {
override fun onCancelClick() {
}
@@ -98,7 +98,7 @@ class DeviceFragment : BaseFragment<FragmentHomeBinding, DevicePresenter>(),
val device = deviceAdapter.data[position]
// 没有经纬度时只展示空态,不要把空坐标传给地图
if (device.lat.isNullOrBlank() || device.lng.isNullOrBlank()) {
showMessage("暂无定位")
showMessage(mContext.getString(R.string.i18n_080)) //暂无定位
return@setOnItemChildClickListener
}
// 地图页后续接入,这里先预留点击入口
@@ -136,8 +136,8 @@ class DeviceFragment : BaseFragment<FragmentHomeBinding, DevicePresenter>(),
// 扫一扫:先申请相机权限,授权后再打开扫码页
getMorePermissionRequst(
scanPermissions(),
"相机权限",
"扫一扫功能需要使用相机权限",
mContext.getString(R.string.i18n_081), //相机权限
mContext.getString(R.string.i18n_082), //扫一扫功能需要使用相机权限
REQUEST_CAMERA_AND_ALBUM
)
}
@@ -157,7 +157,11 @@ class DeviceFragment : BaseFragment<FragmentHomeBinding, DevicePresenter>(),
binding.refresh.finishLoadMore()
binding.refresh.setNoMoreData(devices.size < PAGE_SIZE)
binding.relNoMore.visibility =
if (deviceAdapter.data.isEmpty()) View.VISIBLE else View.GONE
if (deviceAdapter.data.isEmpty()) {
View.VISIBLE
} else {
View.GONE
}
}
override fun bindDeviceSuccess(message: String) {
@@ -180,11 +184,17 @@ class DeviceFragment : BaseFragment<FragmentHomeBinding, DevicePresenter>(),
deviceAdapter.data.removeAt(removedPosition)
deviceAdapter.notifyItemRemoved(removedPosition)
binding.relNoMore.visibility =
if (deviceAdapter.data.isEmpty()) View.VISIBLE else View.GONE
if (deviceAdapter.data.isEmpty()) {
View.VISIBLE
} else {
View.GONE
}
}
// 等待 RecyclerView 删除动画完成后再刷新,避免刷新结果立即覆盖动画。
binding.root.postDelayed({
if (!isAdded) return@postDelayed
if (!isAdded) {
return@postDelayed
}
currentPage = FIRST_PAGE
requestDeviceList()
}, REMOVE_ANIMATION_DELAY_MS)
@@ -265,7 +275,7 @@ class DeviceFragment : BaseFragment<FragmentHomeBinding, DevicePresenter>(),
?.joinToString("\n")
.orEmpty()
if (content.isBlank()) {
ToastUtil.showShort(mContext, "未识别到内容")
ToastUtil.showShort(mContext, mContext.getString(R.string.i18n_083)) //未识别到内容
} else {
ToastUtil.showShort(mContext, content)
}
@@ -276,7 +286,7 @@ class DeviceFragment : BaseFragment<FragmentHomeBinding, DevicePresenter>(),
)
ToastUtil.showShort(
mContext,
resultError.takeUnless { it.isNullOrBlank() } ?: "扫码失败"
resultError.takeUnless { it.isNullOrBlank() } ?: mContext.getString(R.string.i18n_084) //扫码失败
)
}
else -> {
@@ -288,3 +298,5 @@ class DeviceFragment : BaseFragment<FragmentHomeBinding, DevicePresenter>(),
}
}

View File

@@ -2,6 +2,8 @@ package com.juhabi.birds.device.adapter
import android.widget.ProgressBar
import androidx.core.content.ContextCompat
import android.graphics.drawable.Drawable
import android.graphics.drawable.ClipDrawable
import com.chad.library.adapter.base.BaseQuickAdapter
import com.chad.library.adapter.base.viewholder.BaseViewHolder
import com.juhabi.birds.R
@@ -9,18 +11,20 @@ import com.juhabi.birds.device.entity.DeviceEntity
/** 临时设备列表适配器,后续可根据设计稿替换 item 展示。 */
class DeviceAdapter : BaseQuickAdapter<DeviceEntity, BaseViewHolder>(R.layout.device_item) {
private val progressDrawables = mutableMapOf<Int, Drawable.ConstantState?>()
init {
addChildClickViewIds(R.id.img_more)
}
override fun convert(holder: BaseViewHolder, item: DeviceEntity) {
//设备名字
holder.setText(R.id.tv_dev_name, item.name.ifBlank { "未命名设备" })
holder.setText(R.id.tv_dev_name, item.name.ifBlank { context.getString(com.juhabi.birds.R.string.i18n_170) }) //未命名设备
//在线状态
if (item.status == "1") {
holder.setText(R.id.tv_dev_online_status, "在线")
holder.setText(R.id.tv_dev_online_status, context.getString(com.juhabi.birds.R.string.i18n_030)) //在线
} else {
holder.setText(R.id.tv_dev_online_status, "离线")
holder.setText(R.id.tv_dev_online_status, context.getString(com.juhabi.birds.R.string.i18n_171)) //离线
}
val statusRes = if (item.status == "1") {
R.drawable.shape_device_online_bg
@@ -41,19 +45,19 @@ class DeviceAdapter : BaseQuickAdapter<DeviceEntity, BaseViewHolder>(R.layout.de
val wifiTextColor: Int
if (item.signalLevel == 0) {
imgResource = R.mipmap.icon_dev_wifi_offline
signalText = "离线"
signalText = context.getString(com.juhabi.birds.R.string.i18n_171) //离线
wifiTextColor = R.color.color_999999
} else if (item.signalLevel == 1) {
imgResource = R.mipmap.icon_dev_wifi_low
signalText = "弱"
signalText = context.getString(com.juhabi.birds.R.string.i18n_172) //弱
wifiTextColor = R.color.color_e34d59
} else if (item.signalLevel == 2) {
imgResource = R.mipmap.icon_dev_wifi_mid
signalText = "一般"
signalText = context.getString(com.juhabi.birds.R.string.i18n_173) //一般
wifiTextColor = R.color.color_ff942a
} else {
imgResource = R.mipmap.icon_dev_wifi_hight
signalText = "强"
signalText = context.getString(com.juhabi.birds.R.string.i18n_033) //强
wifiTextColor = R.color.color_zhu
}
@@ -62,15 +66,23 @@ class DeviceAdapter : BaseQuickAdapter<DeviceEntity, BaseViewHolder>(R.layout.de
holder.setTextColor(R.id.tv_signal_text,wifiTextColor)
holder.setText(
R.id.tv_head_foot_connect_status,
if (item.hoodConnected == "0") "断开" else "已连接"
if (item.hoodConnected == "0") {
context.getString(com.juhabi.birds.R.string.i18n_174)
} else {
context.getString(com.juhabi.birds.R.string.i18n_035)
} //断开 / 已连接
)
}else{
holder.setImageResource(R.id.img_signal, R.mipmap.icon_dev_wifi_offline)
holder.setText(R.id.tv_signal_text, "离线")
holder.setText(R.id.tv_signal_text, context.getString(com.juhabi.birds.R.string.i18n_171)) //离线
holder.setTextColor(R.id.tv_signal_text, R.color.color_999999)
holder.setText(
R.id.tv_head_foot_connect_status,
if (item.hoodConnected == "0") "断开" else "已连接"
if (item.hoodConnected == "0") {
context.getString(com.juhabi.birds.R.string.i18n_174)
} else {
context.getString(com.juhabi.birds.R.string.i18n_035)
} //断开 / 已连接
)
}
@@ -123,20 +135,15 @@ class DeviceAdapter : BaseQuickAdapter<DeviceEntity, BaseViewHolder>(R.layout.de
} else {
R.drawable.progress_offline_bg
}
// mutate 避免两条进度条共用同一份离线 drawable 状态
progressHead.progressDrawable = ContextCompat.getDrawable(
context,
headProgressRes
)?.mutate()
progressFoot.progressDrawable = ContextCompat.getDrawable(
context,
footProgressRes
)?.mutate()
// 替换 drawable 后进度会被重置,需要重新写入
// 每个进度条使用独立 drawable 状态,避免 RecyclerView 复用时 clip 进度互相影响。
progressHead.progressDrawable = getProgressDrawable(headProgressRes)
progressFoot.progressDrawable = getProgressDrawable(footProgressRes)
progressHead.max = 100
progressHead.progress = headBattery
progressFoot.max = 100
progressFoot.progress = footBattery
setProgressDrawableLevel(progressHead, headBattery)
setProgressDrawableLevel(progressFoot, footBattery)
//tv_location_detail 显示地址
holder.setText(R.id.tv_location_detail, item.address)
@@ -158,8 +165,37 @@ class DeviceAdapter : BaseQuickAdapter<DeviceEntity, BaseViewHolder>(R.layout.de
}
}
private fun getProgressDrawable(resourceId: Int): Drawable? {
val constantState = progressDrawables.getOrPut(resourceId) {
ContextCompat.getDrawable(context, resourceId)?.constantState
}
return constantState?.newDrawable(context.resources)?.mutate()
}
private fun setProgressDrawableLevel(progressBar: ProgressBar, progress: Int) {
val drawable = progressBar.progressDrawable ?: return
val clipDrawable = drawable.findClipDrawable() ?: return
clipDrawable.level = (progress * MAX_DRAWABLE_LEVEL / progressBar.max)
.coerceIn(0, MAX_DRAWABLE_LEVEL)
drawable.invalidateSelf()
}
private fun Drawable.findClipDrawable(): ClipDrawable? {
if (this is ClipDrawable) {
return this
}
if (this is android.graphics.drawable.LayerDrawable) {
for (index in 0 until numberOfLayers) {
getDrawable(index).findClipDrawable()?.let { return it }
}
}
return null
}
private companion object {
const val BATTERY_LOW_MAX = 30
const val BATTERY_MID_MAX = 70
const val MAX_DRAWABLE_LEVEL = 10_000
}
}
}

View File

@@ -1,7 +1,9 @@
package com.juhabi.birds.device.mvp
import android.content.Context
import android.os.Handler
import android.os.Looper
import com.juhabi.birds.R
import com.juhabi.birds.device.entity.DeviceEntity
import com.juhabi.birds.network.ApiClient
import com.juhabi.birds.network.BaseBean
@@ -11,7 +13,7 @@ import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
class DeviceImpl : DeviceContract.DataModel {
class DeviceImpl(private val mContext: Context) : DeviceContract.DataModel {
private val mainHandler = Handler(Looper.getMainLooper())
private var deviceListCall: Call<BaseBean<List<DeviceEntity>>>? = null
private var deviceDetailCall: Call<BaseBean<DeviceEntity>>? = null
@@ -42,7 +44,7 @@ class DeviceImpl : DeviceContract.DataModel {
callback.success(devices)
} else {
callback.fail(
bean?.message?.ifBlank { null } ?: "获取设备列表失败"
bean?.message?.ifBlank { null } ?: mContext.getString(R.string.i18n_175) //获取设备列表失败
)
}
}
@@ -54,7 +56,7 @@ class DeviceImpl : DeviceContract.DataModel {
) {
if (!call.isCanceled) {
mainHandler.post {
callback.fail(error.message ?: "网络请求失败")
callback.fail(error.message ?: mContext.getString(R.string.i18n_150)) //网络请求失败
}
}
}
@@ -86,7 +88,7 @@ class DeviceImpl : DeviceContract.DataModel {
callback.success(device)
} else {
callback.fail(
bean?.message?.ifBlank { null } ?: "获取设备详情失败"
bean?.message?.ifBlank { null } ?: mContext.getString(R.string.i18n_176) //获取设备详情失败
)
}
}
@@ -98,7 +100,7 @@ class DeviceImpl : DeviceContract.DataModel {
) {
if (!call.isCanceled) {
mainHandler.post {
callback.fail(error.message ?: "网络请求失败")
callback.fail(error.message ?: mContext.getString(R.string.i18n_150)) //网络请求失败
}
}
}
@@ -130,7 +132,7 @@ class DeviceImpl : DeviceContract.DataModel {
if (response.isSuccessful && (bean?.code == 0 || bean?.code == 200)) {
callback.success(bean)
} else {
callback.fail(bean?.message?.ifBlank { null } ?: "控制眼罩失败")
callback.fail(bean?.message?.ifBlank { null } ?: mContext.getString(R.string.i18n_177)) //控制眼罩失败
}
}
}
@@ -138,7 +140,7 @@ class DeviceImpl : DeviceContract.DataModel {
override fun onFailure(call: Call<BaseBean<Any>>, error: Throwable) {
if (!call.isCanceled) {
mainHandler.post {
callback.fail(error.message ?: "网络请求失败")
callback.fail(error.message ?: mContext.getString(R.string.i18n_150)) //网络请求失败
}
}
}
@@ -169,7 +171,7 @@ class DeviceImpl : DeviceContract.DataModel {
callback.success(bean)
} else {
callback.fail(
bean?.message?.ifBlank { null } ?: "绑定设备失败"
bean?.message?.ifBlank { null } ?: mContext.getString(R.string.i18n_178) //绑定设备失败
)
}
}
@@ -178,7 +180,7 @@ class DeviceImpl : DeviceContract.DataModel {
override fun onFailure(call: Call<BaseBean<Any>>, error: Throwable) {
if (!call.isCanceled) {
mainHandler.post {
callback.fail(error.message ?: "网络请求失败")
callback.fail(error.message ?: mContext.getString(R.string.i18n_150)) //网络请求失败
}
}
}
@@ -206,7 +208,7 @@ class DeviceImpl : DeviceContract.DataModel {
if (response.isSuccessful && (bean?.code == 0 || bean?.code == 200)) {
callback.success(bean)
} else {
callback.fail(bean?.message?.ifBlank { null } ?: "设备重命名失败")
callback.fail(bean?.message?.ifBlank { null } ?: mContext.getString(R.string.i18n_179)) //设备重命名失败
}
}
}
@@ -214,7 +216,7 @@ class DeviceImpl : DeviceContract.DataModel {
override fun onFailure(call: Call<BaseBean<Any>>, error: Throwable) {
if (!call.isCanceled) {
mainHandler.post {
callback.fail(error.message ?: "网络请求失败")
callback.fail(error.message ?: mContext.getString(R.string.i18n_150)) //网络请求失败
}
}
}
@@ -241,7 +243,7 @@ class DeviceImpl : DeviceContract.DataModel {
if (response.isSuccessful && (bean?.code == 0 || bean?.code == 200)) {
callback.success(bean)
} else {
callback.fail(bean?.message?.ifBlank { null } ?: "设备解绑失败")
callback.fail(bean?.message?.ifBlank { null } ?: mContext.getString(R.string.i18n_180)) //设备解绑失败
}
}
}
@@ -249,7 +251,7 @@ class DeviceImpl : DeviceContract.DataModel {
override fun onFailure(call: Call<BaseBean<Any>>, error: Throwable) {
if (!call.isCanceled) {
mainHandler.post {
callback.fail(error.message ?: "网络请求失败")
callback.fail(error.message ?: mContext.getString(R.string.i18n_150)) //网络请求失败
}
}
}
@@ -274,3 +276,4 @@ class DeviceImpl : DeviceContract.DataModel {
mainHandler.removeCallbacksAndMessages(null)
}
}

View File

@@ -1,12 +1,15 @@
package com.juhabi.birds.device.mvp
import android.content.Context
import com.juhabi.birds.R
import com.juhabi.birds.base.BasePresenter
import com.juhabi.birds.device.entity.DeviceEntity
import com.juhabi.birds.network.BaseBean
import org.json.JSONObject
class DevicePresenter(
private val deviceImpl: DeviceImpl
private val deviceImpl: DeviceImpl,
private val mContext: Context
) : BasePresenter<DeviceContract.DeviceView>() {
/** 获取当前账号已经绑定的设备列表。 */
@@ -65,7 +68,7 @@ class DevicePresenter(
override fun success(data: BaseBean<Any>) {
view?.apply {
hideLoading()
controlEyeSuccess(data.message.ifBlank { "眼罩状态已更新" })
controlEyeSuccess(data.message.ifBlank { mContext.getString(R.string.i18n_181) }) //眼罩状态已更新
}
}
@@ -90,7 +93,7 @@ class DevicePresenter(
override fun success(data: BaseBean<Any>) {
view?.apply {
hideLoading()
bindDeviceSuccess(data.message.ifBlank { "设备绑定成功" })
bindDeviceSuccess(data.message.ifBlank { mContext.getString(R.string.i18n_182) }) //设备绑定成功
}
}
@@ -108,7 +111,7 @@ class DevicePresenter(
val currentView = view ?: return
val trimmedName = name.trim()
if (deviceNo.isBlank() || trimmedName.isBlank()) {
currentView.showError("设备编号和名称不能为空")
currentView.showError(mContext.getString(R.string.i18n_183)) //设备编号和名称不能为空
return
}
currentView.showLoading()
@@ -120,7 +123,7 @@ class DevicePresenter(
override fun success(data: BaseBean<Any>) {
view?.apply {
hideLoading()
renameDeviceSuccess(data.message.ifBlank { "设备重命名成功" })
renameDeviceSuccess(data.message.ifBlank { mContext.getString(R.string.i18n_184) }) //设备重命名成功
}
}
@@ -137,7 +140,7 @@ class DevicePresenter(
fun unbindDevice(deviceNo: String) {
val currentView = view ?: return
if (deviceNo.isBlank()) {
currentView.showError("设备编号不能为空")
currentView.showError(mContext.getString(R.string.i18n_185)) //设备编号不能为空
return
}
currentView.showLoading()
@@ -145,7 +148,7 @@ class DevicePresenter(
override fun success(data: BaseBean<Any>) {
view?.apply {
hideLoading()
unbindDeviceSuccess(data.message.ifBlank { "设备解绑成功" })
unbindDeviceSuccess(data.message.ifBlank { mContext.getString(R.string.i18n_186) }) //设备解绑成功
}
}
@@ -164,3 +167,4 @@ class DevicePresenter(
super.onDestroy()
}
}