README.md
@@ -317,8 +317,17 @@ 2. 点击事件监听 ```kotlin // 方式1:使用类型常量(推荐) titleBar.setOnItemclickListner(TitleBar.ClickType_LEFT_IMAGE) { finish() } titleBar.setOnItemclickListner(TitleBar.ClickType_RIGHT_TEXT) { showMenu() } titleBar.setOnItemclickListner(TitleBar.ClickType_LEFT_IMAGE) { finish() } titleBar.setOnItemclickListner(TitleBar.ClickType_RIGHT_TEXT) { showMenu() } // 或者使用完整的OnClickListener titleBar.setOnItemclickListner(TitleBar.ClickType_LEFT_IMAGE, View.OnClickListener { finish() }) // 方式2:使用位置和类型常量(已废弃) titleBar.setOnItemclickListner(TitleBar.IMAGE, TitleBar.LEFT) { finish() } @@ -352,6 +361,173 @@ 2. 设置文本或图片时,如果传入null或0,对应的视图将被隐藏 3. 组件默认使用垂直线性布局,确保在布局文件中设置合适的高度 #### 常见使用示例 ```kotlin // 在Activity的initView方法中设置 private fun initView() { // 设置返回按钮点击事件 binding.titleBar.setOnItemclickListner(TitleBar.ClickType_LEFT_IMAGE) { finish() } // 设置右侧文本按钮点击事件 binding.titleBar.setOnItemclickListner(TitleBar.ClickType_RIGHT_TEXT) { // 处理右侧按钮点击逻辑 handleRightButtonClick() } } ``` ## 支付方式动态获取功能 项目中实现了支付方式的动态获取和显示功能,支持从服务器获取支付方式列表并动态创建RadioButton。 ### 数据结构 ```kotlin // 支付方式数据类 data class PaymentMethod( val id: Long, val name: String, val remarks: String, val deleted: Int ) // 支付方式接口返回数据类 data class PaymentMethodResponse( val itemTotal: Any?, val obj: List<PaymentMethod>, val pageCurr: Any?, val pageSize: Any?, val pageTotal: Any? ) ``` ### 使用方式 #### 1. 在Activity中添加支付方式相关属性 ```kotlin class YourActivity : AppCompatActivity() { // 支付方式相关属性 private var paymentMethod: String = "现金" private var paymentId: Long = 0 private var paymentMethodList: List<PaymentMethod> = listOf() // ... 其他代码 } ``` #### 2. 获取支付方式列表 ```kotlin /** * 获取支付方式列表 */ private fun getPaymentMethods() { ApiManager.getInstance().requestGetLoading( this, "sell/paymentmethod/get", PaymentMethodResponse::class.java, null, object : SubscriberListener<BaseResponse<PaymentMethodResponse>>() { override fun onNext(response: BaseResponse<PaymentMethodResponse>) { if (response.success) { val paymentMethods = response.content?.obj ?: listOf() if (paymentMethods.isNotEmpty()) { paymentMethodList = paymentMethods updatePaymentMethodRadioGroup() } } else { Toast.makeText(this@YourActivity, "获取支付方式失败: ${response.msg}", Toast.LENGTH_SHORT).show() } } override fun onError(e: Throwable?) { super.onError(e) Toast.makeText(this@YourActivity, "获取支付方式失败: ${e?.message ?: "网络异常"}", Toast.LENGTH_SHORT).show() } } ) } ``` #### 3. 动态创建RadioButton ```kotlin /** * 更新支付方式RadioGroup */ private fun updatePaymentMethodRadioGroup() { // 清空原有RadioButton binding.paymentMethodRadioGroup.removeAllViews() // 动态添加RadioButton paymentMethodList.forEachIndexed { index, method -> val radioButton = RadioButton(this) radioButton.id = View.generateViewId() radioButton.layoutParams = LinearLayout.LayoutParams(0, resources.getDimensionPixelSize(R.dimen.dimen_40), 1.0f) // 设置样式 radioButton.text = method.name radioButton.background = resources.getDrawable(R.drawable.radio_selector) radioButton.buttonDrawable = null radioButton.gravity = Gravity.CENTER radioButton.setTextColor(resources.getColorStateList(R.color.radio_button_text_color)) radioButton.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14f) // 添加到RadioGroup binding.paymentMethodRadioGroup.addView(radioButton) // 默认选中第一个 if (index == 0) { radioButton.isChecked = true paymentMethod = method.name paymentId = method.id } } // 设置选择监听 binding.paymentMethodRadioGroup.setOnCheckedChangeListener { group, checkedId -> for (i in 0 until group.childCount) { val radioButton = group.getChildAt(i) as RadioButton if (radioButton.id == checkedId) { paymentMethod = radioButton.text.toString() paymentId = paymentMethodList[i].id break } } } } ``` #### 4. 布局文件配置 ```xml <RadioGroup android:id="@+id/paymentMethodRadioGroup" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <!-- 动态添加RadioButton,不需要预定义 --> </RadioGroup> ``` ### 功能特点 1. **动态获取**: 从服务器动态获取支付方式列表,支持后台配置 2. **自动布局**: 根据支付方式数量自动调整RadioButton布局 3. **样式统一**: 所有动态创建的RadioButton使用统一的样式 4. **默认选择**: 自动选中第一个支付方式作为默认选项 5. **事件处理**: 支持选择变化监听,实时更新当前选中的支付方式 ### 注意事项 1. 确保在调用`getPaymentMethods()`前已经初始化了相关的UI组件 2. 动态创建的RadioButton需要设置唯一的ID,使用`View.generateViewId()` 3. 在Activity销毁时注意清理相关资源,避免内存泄漏 4. 网络请求失败时要有相应的错误处理机制 ## 注意事项 1. 数据库迁移 @@ -371,6 +547,200 @@ - 确保异常信息被正确记录和上报 - 避免异常信息泄露敏感数据 5. API异常处理最佳实践 - 针对特定错误码提供友好的用户提示 - 区分网络异常、业务异常和系统异常 - 异常发生后及时重置UI状态,允许用户重试 - 提供明确的操作指引,如"请先进行开卡操作" ### API异常处理示例 ```kotlin // 在API回调中处理不同类型的异常 object : SubscriberListener<BaseResponse<YourDataType>>() { override fun onNext(response: BaseResponse<YourDataType>) { if (response.success) { // 处理成功情况 handleSuccess(response.content) } else { // 处理业务异常 handleBusinessError(response.code, response.msg) } } override fun onError(e: Throwable?) { super.onError(e) // 处理网络异常 handleNetworkError(e) // 重置UI状态 resetViewState() } } // 业务异常处理方法 private fun handleBusinessError(code: String?, msg: String?) { when (code) { "1081" -> ToastUtil.show("该卡片未在系统中注册,请先进行开卡操作") "1001" -> ToastUtil.show("权限不足,请联系管理员") "1002" -> ToastUtil.show("账户余额不足") else -> { val errorMsg = when { msg.isNullOrBlank() -> "操作失败,请重试" msg.contains("数据不存在") -> "数据不存在,请检查输入信息" msg.contains("网络") -> "网络连接异常,请检查网络后重试" msg.contains("超时") -> "请求超时,请重试" else -> "操作失败: $msg" } ToastUtil.show(errorMsg) } } // 重置界面状态 resetViewState() } // 网络异常处理方法 private fun handleNetworkError(e: Throwable?) { val errorMsg = when { e?.message?.contains("timeout") == true -> "网络请求超时,请检查网络连接" e?.message?.contains("network") == true -> "网络连接失败,请检查网络设置" e?.message?.contains("host") == true -> "服务器连接失败,请稍后重试" else -> "网络异常: ${e?.message ?: "未知错误"}" } ToastUtil.show(errorMsg) } ### Dialog弹窗使用最佳实践 项目中提供了多种Dialog组件,用于不同的交互场景。推荐使用项目已有的Dialog组件来保持UI风格的一致性。 #### 常用Dialog组件 1. **ConfirmDialog**: 确认对话框,用于重要操作的二次确认 2. **TipDialog**: 提示对话框,用于显示提示信息 3. **EdtDialog**: 输入对话框,用于获取用户输入 4. **自定义Dialog**: 继承Dialog类实现特定功能 #### ConfirmDialog使用示例 ```kotlin // 基本用法 - 只显示消息 val dialog = ConfirmDialog(context, "操作成功") dialog.show() // 带标题的用法 val dialog = ConfirmDialog(context, "提示", "确认要删除这条记录吗?") { // 点击确认按钮的回调 deleteRecord() dialog.dismiss() } dialog.show() // 在异常处理中使用 private fun handleError(title: String, message: String) { activity?.let { activity -> val confirmDialog = ConfirmDialog(activity, title, message) { // 点击确认后的操作 resetViewState() } confirmDialog.show() } } ``` #### TipDialog使用示例 ```kotlin // 简单提示 val tipDialog = TipDialog(context, "操作完成") tipDialog.show() // 带回调的提示 val tipDialog = TipDialog(context, "确认退出应用?", object : TipUtil.TipListener { override fun onCancle() { // 取消操作 } }) tipDialog.show() ``` #### 自定义Dialog最佳实践 ```kotlin class CustomDialog(context: Context) : Dialog(context, R.style.ws_pay_showSelfDialog) { private lateinit var binding: DialogCustomBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = DialogCustomBinding.inflate(layoutInflater) setContentView(binding.root) // 设置对话框属性 setupDialog() // 初始化视图 initViews() } private fun setupDialog() { // 设置对话框宽度为屏幕宽度的85% window?.apply { val params = attributes params.width = (context.resources.displayMetrics.widthPixels * 0.85).toInt() params.height = ViewGroup.LayoutParams.WRAP_CONTENT params.gravity = Gravity.CENTER attributes = params setBackgroundDrawableResource(android.R.color.transparent) } // 设置点击外部不取消 setCanceledOnTouchOutside(false) } private fun initViews() { binding.btnConfirm.setOnClickListener { // 处理确认逻辑 dismiss() } binding.btnCancel.setOnClickListener { dismiss() } } } ``` #### Dialog使用注意事项 1. **内存泄漏防护**: 确保在Activity销毁时关闭Dialog ```kotlin override fun onDestroy() { super.onDestroy() dialog?.dismiss() } ``` 2. **生命周期管理**: 在Fragment中使用Dialog时注意生命周期 ```kotlin // 在Fragment中安全显示Dialog activity?.let { activity -> if (!activity.isFinishing && !activity.isDestroyed) { dialog.show() } } ``` 3. **样式一致性**: 使用项目统一的Dialog样式 ```kotlin // 使用项目定义的Dialog样式 super(context, R.style.ws_pay_showSelfDialog) ``` 4. **用户体验优化**: - 重要操作使用ConfirmDialog进行二次确认 - 错误信息使用带标题的Dialog,提供清晰的错误分类 - 长时间操作显示加载Dialog,避免用户误操作 ## 贡献指南 1. Fork 项目 generallibrary/src/main/AndroidManifest.xml
@@ -42,6 +42,7 @@ <activity android:name="com.dayu.general.activity.NewCardActivity" /> <activity android:name="com.dayu.general.activity.ManageListActivity" /> <activity android:name="com.dayu.general.activity.SearchUserListActivity" /> <activity android:name="com.dayu.general.activity.RechargeDetailActivity" /> <activity android:name="com.dayu.general.activity.NfcWreatActivity" android:exported="false" @@ -90,6 +91,8 @@ <!-- 写卡成功页面 --> <activity android:name=".activity.CardWriteSuccessActivity" /> <!-- 挂失页面 --> <activity android:name=".activity.LossCardActivity"/> <meta-data android:name="BUGLY_APP_VERSION" generallibrary/src/main/java/com/dayu/general/activity/BSCardFragment.kt
@@ -42,9 +42,7 @@ startActivity(intent) } binding.homeLossLL.setOnClickListener { val intent = Intent(context, SearchCardListActivity::class.java).apply{ putExtra("type", "loss") } val intent = Intent(context, LossCardActivity::class.java) startActivity(intent) } binding.homeReplaceLL.setOnClickListener{ generallibrary/src/main/java/com/dayu/general/activity/LossCardActivity.kt
New file @@ -0,0 +1,306 @@ package com.dayu.general.activity import android.os.Bundle import androidx.recyclerview.widget.LinearLayoutManager import com.dayu.baselibrary.net.subscribers.SubscriberListener import com.dayu.baselibrary.utils.ToastUtil import com.dayu.baselibrary.view.TitleBar.ClickType_LEFT_IMAGE import com.dayu.baselibrary.view.TitleBar.ClickType_RIGHT_IMAGE import com.dayu.general.BaseApplication import com.dayu.general.adapter.CardListAdapter import com.dayu.general.bean.net.SearchCardResult import com.dayu.general.databinding.ActivityCardListBinding import com.dayu.general.net.ApiManager import com.dayu.general.net.BaseResponse import com.dayu.general.view.CardRefundDialog import com.dayu.general.view.SearchDialog import com.scwang.smart.refresh.layout.api.RefreshLayout import com.scwang.smart.refresh.layout.listener.OnRefreshLoadMoreListener /** * Description: * Author: zuo * Date: 2025/6/11 */ class LossCardActivity : BaseActivity() { var binding: ActivityCardListBinding? = null private var cardAdapter: CardListAdapter? = null var searchDialog: SearchDialog? = null // 分页相关变量 private var currentPage = 1 private val pageSize = 20 private var hasMoreData = true // 保存当前搜索条件 private var currentFarmerId = "" private var currentFarmerName = "" private var currentCardNumber = "" override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityCardListBinding.inflate(layoutInflater) setContentView(binding?.root) initView() setupRecyclerView() setupRefreshLayout() // 确保Footer初始状态正确 binding?.refreshLayout?.setEnableLoadMore(true) } fun initView() { searchDialog = SearchDialog(this) searchDialog?.show() binding?.titleBar?.setOnItemclickListner(ClickType_LEFT_IMAGE) { this.finish() } // 设置搜索监听器 searchDialog?.setOnSearchListener(object : SearchDialog.OnSearchListener { override fun onSearch(farmerId: String, farmerName: String, cardNumber: String) { // 保存当前搜索条件 currentCardNumber = cardNumber currentFarmerId = farmerId currentFarmerName = farmerName // 重置分页状态 currentPage = 1 hasMoreData = true // 重置无更多数据状态 binding?.refreshLayout?.resetNoMoreData() // 执行搜索 searchCards(currentFarmerId, currentFarmerName, currentCardNumber, true) } }) binding?.titleBar?.setOnItemclickListner(ClickType_RIGHT_IMAGE) { // 显示搜索对话框 searchDialog?.show() } } private fun setupRecyclerView() { cardAdapter = CardListAdapter(this) binding?.recyclerView?.apply { layoutManager = LinearLayoutManager(this@LossCardActivity) adapter = cardAdapter } // 设置列表项点击事件 cardAdapter?.setOnItemClickListener { card -> // 显示退款对话框 val refundDialog = CardRefundDialog(this) refundDialog.show() // 先显示对话框 refundDialog.setUserInfo( card.clientName.toString(), card.cardNum.toString(), card.money.toString() ) refundDialog.setOnConfirmListener { refundAmount, remark -> // TODO: 处理退款逻辑 lossPost(card.idCard.toString()) } } } private fun setupRefreshLayout() { binding?.refreshLayout?.apply { // 设置Footer跟随功能,确保无更多数据时Footer能正确显示 setEnableFooterFollowWhenNoMoreData(true) // 设置加载更多完成后滚动内容显示新数据 setEnableScrollContentWhenLoaded(true) // 禁用纯滚动模式,确保Footer能正常工作 setEnableOverScrollDrag(false) // 设置刷新和加载更多监听器 setOnRefreshLoadMoreListener(object : OnRefreshLoadMoreListener { override fun onRefresh(refreshLayout: RefreshLayout) { // 重置页码并刷新数据 currentPage = 1 hasMoreData = true // 重置无更多数据状态 refreshLayout.resetNoMoreData() searchCards(currentFarmerId, currentFarmerName, currentCardNumber, true) } override fun onLoadMore(refreshLayout: RefreshLayout) { // 如果还有更多数据,加载下一页 if (hasMoreData) { currentPage++ searchCards(currentFarmerId, currentFarmerName, currentCardNumber, false) } else { // 完成加载并显示已到底状态 refreshLayout.finishLoadMoreWithNoMoreData() } } }) } } /** * 根据卡号、客户编号和客户姓名搜索卡片 * * 此函数构建一个参数映射,根据提供的卡号、客户编号和客户姓名来搜索卡片 * 它仅包含有效的、非空的搜索参数,以确保搜索请求的准确性和效率 * * @param cardNumber 卡号 * @param clientNumber 客户编号 * @param clientName 客户姓名 * @param isRefresh 是否为刷新操作 */ private fun searchCards( farmerId: String, farmerName: String, cardNumber: String, isRefresh: Boolean = true ) { val map = mutableMapOf<String, Any>() if (cardNumber.isNotEmpty()) { map["cardNum"] = cardNumber } if (farmerId.isNotEmpty()) { map["clientNum"] = farmerId } if (farmerName.isNotEmpty()) { map["clientName"] = farmerName } // 添加分页参数 map["pageCurr"] = currentPage map["pageSize"] = pageSize // 使用正确的类型参数 ApiManager.getInstance().requestGetLoading( this, "sell/clientcard/getcards", SearchCardResult::class.java, map, object : SubscriberListener<BaseResponse<SearchCardResult>>() { override fun onNext(t: BaseResponse<SearchCardResult>) { if (t.success) { // 处理搜索成功的情况 val result = t.content if (result != null) { // 处理搜索结果 if (result.obj.isNotEmpty()) { // 根据是否为刷新操作决定如何更新数据 if (isRefresh) { cardAdapter?.setData(result.obj) } else { cardAdapter?.addData(result.obj) } // 判断是否还有更多数据:根据当前页码和总页数判断 hasMoreData = currentPage < result.pageTotal // 完成刷新或加载动作 if (isRefresh) { binding?.refreshLayout?.finishRefresh(true) } else { // 如果没有更多数据了,设置已到底状态 if (!hasMoreData) { binding?.refreshLayout?.finishLoadMoreWithNoMoreData() } else { binding?.refreshLayout?.finishLoadMore(true) } } } else { if (isRefresh) { cardAdapter?.setData(emptyList()) binding?.refreshLayout?.finishRefresh(true) ToastUtil.show("未找到匹配的卡片") } else { hasMoreData = false // 使用finishLoadMoreWithNoMoreData显示已到底状态 binding?.refreshLayout?.finishLoadMoreWithNoMoreData() } } } else { if (isRefresh) { cardAdapter?.setData(emptyList()) binding?.refreshLayout?.finishRefresh(true) ToastUtil.show("未找到匹配的卡片") } else { hasMoreData = false binding?.refreshLayout?.finishLoadMoreWithNoMoreData() } } } else { // 处理搜索失败的情况 finishRefreshOrLoad(isRefresh) ToastUtil.show(t.msg) } } override fun onError(e: Throwable?) { super.onError(e) // 完成刷新或加载动作 finishRefreshOrLoad(isRefresh) ToastUtil.show("搜索失败: ${e?.message ?: "未知错误"}") } } ) } private fun lossPost(cardNumber: String) { val map = mutableMapOf<String, Any>() map["cardNum"] = cardNumber map["operator"] = BaseApplication.userId ApiManager.getInstance().requestGetLoading( this, "/sell/card/loss", SearchCardResult::class.java, map, object : SubscriberListener<BaseResponse<SearchCardResult>>() { override fun onNext(t: BaseResponse<SearchCardResult>) { if (t.success) { } else { // 处理搜索失败的情况 ToastUtil.show(t.msg) } } override fun onError(e: Throwable?) { super.onError(e) // 完成刷新或加载动作 ToastUtil.show("搜索失败: ${e?.message ?: "未知错误"}") } } ) } /** * 完成刷新或加载操作 * @param isRefresh 是否为刷新操作 */ private fun finishRefreshOrLoad(isRefresh: Boolean) { if (isRefresh) { binding?.refreshLayout?.finishRefresh(true) } else { // 如果没有更多数据,不在这里调用finishLoadMore,由具体逻辑调用finishLoadMoreWithNoMoreData // 如果有更多数据,则正常调用finishLoadMore if (hasMoreData) { binding?.refreshLayout?.finishLoadMore(true) } // 注意:当hasMoreData为false时,不调用任何finish方法, // 因为已经在具体逻辑中调用了finishLoadMoreWithNoMoreData() } } override fun onDestroy() { super.onDestroy() searchDialog?.dismiss() } } generallibrary/src/main/java/com/dayu/general/activity/RechargeDetailActivity.kt
New file @@ -0,0 +1,254 @@ package com.dayu.general.activity import android.content.Context import android.content.Intent import android.os.Bundle import android.util.TypedValue import android.view.View import android.widget.RadioButton import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import com.dayu.baselibrary.net.subscribers.SubscriberListener import com.dayu.baselibrary.utils.ToastUtil import com.dayu.baselibrary.view.TitleBar import com.dayu.general.R import com.dayu.general.bean.net.CardInfoResult import com.dayu.general.bean.net.PaymentMethod import com.dayu.general.bean.net.PaymentMethodResponse import com.dayu.general.databinding.ActivityRechargeDetailBinding import com.dayu.general.net.ApiManager import com.dayu.general.net.BaseResponse class RechargeDetailActivity : AppCompatActivity() { private lateinit var binding: ActivityRechargeDetailBinding private var cardInfo: CardInfoResult? = null private var cardAddress: String? = null // 支付方式相关属性 private var paymentMethod: String = "现金" private var paymentId: Long = 0 private var paymentMethodList: List<PaymentMethod> = listOf() companion object { private const val EXTRA_CARD_INFO = "extra_card_info" private const val EXTRA_CARD_ADDRESS = "extra_card_address" fun start(context: Context, cardInfo: CardInfoResult?, cardAddress: String?) { val intent = Intent(context, RechargeDetailActivity::class.java) intent.putExtra(EXTRA_CARD_INFO, cardInfo) intent.putExtra(EXTRA_CARD_ADDRESS, cardAddress) context.startActivity(intent) } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityRechargeDetailBinding.inflate(layoutInflater) setContentView(binding.root) // 隐藏默认ActionBar supportActionBar?.hide() // 获取传递的数据 cardInfo = intent.getSerializableExtra(EXTRA_CARD_INFO) as? CardInfoResult cardAddress = intent.getStringExtra(EXTRA_CARD_ADDRESS) initView() displayCardInfo() // 获取支付方式 getPaymentMethods() } private fun initView() { // 设置TitleBar的返回按钮点击事件 binding.titleBar.setOnItemclickListner(TitleBar.ClickType_LEFT_IMAGE) { finish() } // 设置按钮点击事件 binding.rechargeRegistBtn.setOnClickListener { // 处理写卡逻辑 handleWriteCard() } } /** * 获取支付方式列表 */ private fun getPaymentMethods() { ApiManager.getInstance().requestGetLoading( this, "sell/paymentmethod/get", PaymentMethodResponse::class.java, null, object : SubscriberListener<BaseResponse<PaymentMethodResponse>>() { override fun onNext(response: BaseResponse<PaymentMethodResponse>) { if (response.success) { // 获取支付方式列表 val paymentMethods = response.content?.obj ?: listOf() if (paymentMethods.isNotEmpty()) { paymentMethodList = paymentMethods // 更新支付方式显示 updatePaymentMethodRadioGroup() } } else { Toast.makeText( this@RechargeDetailActivity, "获取支付方式失败: ${response.msg}", Toast.LENGTH_SHORT ).show() } } override fun onError(e: Throwable?) { super.onError(e) Toast.makeText( this@RechargeDetailActivity, "获取支付方式失败: ${e?.message ?: "网络异常"}", Toast.LENGTH_SHORT ).show() } } ) } /** * 更新支付方式RadioGroup */ private fun updatePaymentMethodRadioGroup() { // 清空原有RadioButton binding.newCardPaymentMethod.removeAllViews() // 动态添加RadioButton paymentMethodList.forEachIndexed { index, method -> val radioButton = RadioButton(this) radioButton.id = View.generateViewId() // 生成唯一ID radioButton.layoutParams = android.widget.LinearLayout.LayoutParams( 0, resources.getDimensionPixelSize(R.dimen.dimen_40), 1.0f ) // 如果不是最后一个按钮,添加右边距 if (index < paymentMethodList.size - 1) { (radioButton.layoutParams as android.widget.LinearLayout.LayoutParams).rightMargin = resources.getDimensionPixelSize(R.dimen.dimen_15) } radioButton.text = method.name radioButton.background = resources.getDrawable(R.drawable.radio_selector) radioButton.buttonDrawable = null radioButton.gravity = android.view.Gravity.CENTER radioButton.setTextColor(resources.getColorStateList(R.color.radio_button_text_color)) radioButton.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14f) // 添加到RadioGroup binding.newCardPaymentMethod.addView(radioButton) // 默认选中第一个 if (index == 0) { radioButton.isChecked = true paymentMethod = method.name paymentId = method.id } } // 设置支付方式选择监听 binding.newCardPaymentMethod.setOnCheckedChangeListener { group, checkedId -> // 根据选中的ID获取支付方式 for (i in 0 until group.childCount) { val radioButton = group.getChildAt(i) as RadioButton if (radioButton.id == checkedId) { paymentMethod = radioButton.text.toString() paymentId = paymentMethodList[i].id break } } } } private fun displayCardInfo() { if (cardInfo == null) { ToastUtil.show("卡信息为空") finish() return } cardInfo?.let { info -> // 设置卡片信息 binding.redInitCode.text = cardAddress ?: "" binding.userName.text = info.userName ?: "" binding.redCardNum.text = info.cardNum ?: "" binding.redRemainderBlance.text = "${info.balance ?: 0} 元" // 设置卡状态和对应颜色 val cardStatus = when (info.status) { 1 -> "正常" 2 -> "挂失" 3 -> "锁定" 4 -> "无效卡片" else -> "未知" } binding.redStatu.text = cardStatus // 根据卡状态设置不同颜色 val statusColor = when (info.status) { 1 -> android.graphics.Color.parseColor("#4CAF50") // 绿色-正常 2 -> android.graphics.Color.parseColor("#FF9800") // 橙色-挂失 3 -> android.graphics.Color.parseColor("#F44336") // 红色-锁定 else -> android.graphics.Color.parseColor("#757575") // 灰色-未知 } binding.redStatu.setTextColor(statusColor) } } private fun handleWriteCard() { // 验证充值金额 val rechargeAmountStr = binding.rechargeMorny.text.toString().trim() if (rechargeAmountStr.isEmpty()) { ToastUtil.show("请输入充值金额") return } val rechargeAmount = try { rechargeAmountStr.toDouble() } catch (e: NumberFormatException) { ToastUtil.show("请输入有效的充值金额") return } if (rechargeAmount <= 0) { ToastUtil.show("充值金额必须大于0") return } // 获取赠送金额(可选) val bonusAmountStr = binding.rechargeWater.text.toString().trim() val bonusAmount = if (bonusAmountStr.isNotEmpty()) { try { bonusAmountStr.toDouble() } catch (e: NumberFormatException) { 0.0 } } else { 0.0 } // 显示确认信息 val totalAmount = rechargeAmount + bonusAmount val confirmMessage = """ 确认充值信息: 卡号:${cardAddress} 充值金额:${rechargeAmount}元 赠送金额:${bonusAmount}元 总金额:${totalAmount}元 支付方式:${paymentMethod} """.trimIndent() ToastUtil.show(confirmMessage) // TODO: 调用写卡API // 这里可以添加实际的写卡逻辑 } } generallibrary/src/main/java/com/dayu/general/activity/RechargeFragment.kt
@@ -9,6 +9,7 @@ import com.dayu.baselibrary.net.subscribers.SubscriberListener import com.dayu.baselibrary.tools.nfc.NfcReadAdapter import com.dayu.baselibrary.utils.ToastUtil import com.dayu.baselibrary.view.ConfirmDialog import com.dayu.general.bean.net.CardInfoResult import com.dayu.general.databinding.FragmentRechargeBinding import com.dayu.general.net.ApiManager @@ -18,7 +19,6 @@ class RechargeFragment : Fragment() { var binding: FragmentRechargeBinding? = null private var cardNumber: String? = null private var cardInfo: CardInfoResult? = null override fun onCreateView( inflater: LayoutInflater, @@ -38,7 +38,6 @@ private fun initView() { // 初始化界面显示读卡状态 binding?.rechargeReadLL?.visibility = View.VISIBLE binding?.rechargeTextLL?.visibility = View.GONE } @@ -46,8 +45,6 @@ private fun resetView() { // 重置界面显示读卡状态 binding?.rechargeReadLL?.visibility = View.VISIBLE binding?.rechargeTextLL?.visibility = View.GONE cardInfo = null } /** @@ -71,10 +68,7 @@ ToastUtil.show("读卡失败,请重新刷卡") return } // 显示读到的卡号 binding?.redInitCode?.text = cardNumber // 根据卡号获取卡片详细信息 getCardInfo(cardNumber!!) } catch (e: Exception) { @@ -89,28 +83,29 @@ */ private fun getCardInfo(cardNumber: String) { activity?.let { activity -> val map = mutableMapOf<String, Any>() map["cardAddr"] = cardNumber ApiManager.getInstance().requestGetLoading( activity, "card/getCardInfo/$cardNumber", // 假设API路径 "terminal/card/readCard", // 假设API路径 CardInfoResult::class.java, null, map, object : SubscriberListener<BaseResponse<CardInfoResult>>() { override fun onNext(t: BaseResponse<CardInfoResult>) { if (t.success) { // 保存卡片信息 cardInfo = t.content // 显示卡片信息 displayCardInfo(t.content) // 跳转到充值详情页面 RechargeDetailActivity.start(activity, t.content, cardNumber) } else { // 处理获取失败的情况 ToastUtil.show(t.msg) binding?.redStatu?.text = "卡状态异常" handleCardInfoError(t.code, t.msg) } } override fun onError(e: Throwable?) { super.onError(e) ToastUtil.show("获取卡信息失败: ${e?.message ?: "未知错误"}") ToastUtil.show("获取卡信息失败: ${e?.message ?: "网络异常,请检查网络连接"}") // 重置界面状态 resetView() } } ) @@ -118,35 +113,38 @@ } /** * 显示卡片信息 * 处理卡信息获取错误 */ private fun displayCardInfo(cardInfo: CardInfoResult?) { if (cardInfo == null) { ToastUtil.show("卡信息为空") return private fun handleCardInfoError(code: String?, msg: String?) { val errorTitle: String val errorMessage: String when (code) { "1001" -> { // 数据不存在的特殊处理 errorTitle = "卡片未注册" errorMessage = "该卡片未在系统中注册,请先进行开卡操作后再充值。" } else -> { // 其他错误的通用处理 errorTitle = "获取卡信息失败" errorMessage = when { msg.isNullOrBlank() -> "获取卡信息失败,请重新刷卡重试。" msg.contains("数据不存在") -> "该卡片未在系统中注册,请先进行开卡操作后再充值。" msg.contains("网络") -> "网络连接异常,请检查网络连接后重新刷卡。" msg.contains("超时") -> "网络请求超时,请重新刷卡重试。" else -> "获取卡信息失败:$msg\n\n请重新刷卡重试。" } } } // 切换到显示信息界面 binding?.rechargeReadLL?.visibility = View.GONE binding?.rechargeTextLL?.visibility = View.VISIBLE // 设置卡片信息 binding?.userName?.text = cardInfo.userName ?: "" binding?.redUserCode?.text = cardInfo.userCode ?: "" binding?.redRemainderBlance?.text = "${cardInfo.balance ?: 0} 元" // 设置卡状态 val cardStatus = when(cardInfo.status) { 1 -> "正常" 2 -> "挂失" 3 -> "锁定" else -> "未知" // 显示确认对话框 activity?.let { activity -> val confirmDialog = ConfirmDialog(activity, errorTitle, errorMessage) { // 点击确认按钮后关闭对话框并重置界面 resetView() } confirmDialog.show() } binding?.redStatu?.text = cardStatus } } generallibrary/src/main/java/com/dayu/general/activity/SearchUserListActivity.kt
@@ -44,6 +44,9 @@ initView() setupRecyclerView() setupRefreshLayout() // 确保Footer初始状态正确 binding?.refreshLayout?.setEnableLoadMore(true) } @@ -62,6 +65,9 @@ // 重置分页状态 currentPage = 1 hasMoreData = true // 重置无更多数据状态 binding?.refreshLayout?.resetNoMoreData() // 执行搜索 searchUser(farmerId, farmerName, cardNumber, true) @@ -95,12 +101,21 @@ private fun setupRefreshLayout() { binding?.refreshLayout?.apply { // 设置Footer跟随功能,确保无更多数据时Footer能正确显示 setEnableFooterFollowWhenNoMoreData(true) // 设置加载更多完成后滚动内容显示新数据 setEnableScrollContentWhenLoaded(true) // 禁用纯滚动模式,确保Footer能正常工作 setEnableOverScrollDrag(false) // 设置刷新和加载更多监听器 setOnRefreshLoadMoreListener(object : OnRefreshLoadMoreListener { override fun onRefresh(refreshLayout: RefreshLayout) { // 重置页码并刷新数据 currentPage = 1 hasMoreData = true // 重置无更多数据状态 refreshLayout.resetNoMoreData() searchUser(currentFarmerId, currentFarmerName, currentCardNumber, true) } @@ -110,9 +125,8 @@ currentPage++ searchUser(currentFarmerId, currentFarmerName, currentCardNumber, false) } else { // 完成加载并提示没有更多数据 refreshLayout.finishLoadMore(500, true, false) ToastUtil.show("没有更多数据了") // 完成加载并显示已到底状态 refreshLayout.finishLoadMoreWithNoMoreData() } } }) @@ -162,9 +176,6 @@ map, object : SubscriberListener<BaseResponse<SearchUserResult>>() { override fun onNext(t: BaseResponse<SearchUserResult>) { // 完成刷新或加载动作 finishRefreshOrLoad(isRefresh) if (t.success) { // 处理搜索成功的情况 val result = t.content @@ -180,23 +191,42 @@ // 判断是否还有更多数据:根据当前页码和总页数判断 hasMoreData = currentPage < result.pageTotal // 完成刷新或加载动作 if (isRefresh) { binding?.refreshLayout?.finishRefresh(true) } else { // 如果没有更多数据了,设置已到底状态 if (!hasMoreData) { binding?.refreshLayout?.finishLoadMoreWithNoMoreData() } else { binding?.refreshLayout?.finishLoadMore(true) } } } else { if (isRefresh) { userAdapter?.setData(emptyList()) binding?.refreshLayout?.finishRefresh(true) ToastUtil.show("未找到匹配的用户") } else { hasMoreData = false ToastUtil.show("没有更多数据了") // 使用finishLoadMoreWithNoMoreData显示已到底状态 binding?.refreshLayout?.finishLoadMoreWithNoMoreData() } } } else { if (isRefresh) { userAdapter?.setData(emptyList()) binding?.refreshLayout?.finishRefresh(true) ToastUtil.show("未找到匹配的用户") } else { hasMoreData = false binding?.refreshLayout?.finishLoadMoreWithNoMoreData() } } } else { // 处理搜索失败的情况 finishRefreshOrLoad(isRefresh) ToastUtil.show(t.msg) } } @@ -219,7 +249,13 @@ if (isRefresh) { binding?.refreshLayout?.finishRefresh(true) } else { binding?.refreshLayout?.finishLoadMore(true) // 如果没有更多数据,不在这里调用finishLoadMore,由具体逻辑调用finishLoadMoreWithNoMoreData // 如果有更多数据,则正常调用finishLoadMore if (hasMoreData) { binding?.refreshLayout?.finishLoadMore(true) } // 注意:当hasMoreData为false时,不调用任何finish方法, // 因为已经在具体逻辑中调用了finishLoadMoreWithNoMoreData() } } generallibrary/src/main/java/com/dayu/general/bean/net/CardInfoResult.kt
@@ -1,10 +1,12 @@ package com.dayu.general.bean.net import java.io.Serializable /** * 卡片信息结果实体类 */ data class CardInfoResult( val cardId: String? = null, // 卡号 val cardNum: String? = null, // 卡号 val userName: String? = null, // 用户姓名 val userCode: String? = null, // 用户编号 val phone: String? = null, // 手机号 @@ -13,4 +15,4 @@ val status: Int? = 0, // 卡状态: 1-正常, 2-挂失, 3-锁定 val createTime: String? = null, // 创建时间 val updateTime: String? = null // 更新时间 ) ) : Serializable generallibrary/src/main/java/com/dayu/general/view/CardRefundDialog.kt
@@ -5,15 +5,21 @@ import android.os.Bundle import android.view.Gravity import android.view.WindowManager import com.dayu.baselibrary.net.subscribers.SubscriberListener import com.dayu.baselibrary.utils.ToastUtil import com.dayu.general.BaseApplication import com.dayu.general.R import com.dayu.general.databinding.DialogCardRefundBinding import com.dayu.general.net.ApiManager import com.dayu.general.net.BaseResponse /** * *卡片挂失对话框 */ class CardRefundDialog(context: Context) : Dialog(context) { private var binding: DialogCardRefundBinding? = null private var onConfirmListener: (( String, String) -> Unit)? = null private var onConfirmListener: ((String, String) -> Unit)? = null private var onSuccessListener: (() -> Unit)? = null private var username: String? = null private var cardNumber: String? = null private var balance: String? = null @@ -40,14 +46,9 @@ binding?.btnConfirm?.setOnClickListener { val refundAmount = binding?.etRefundAmount?.text.toString() val remark = binding?.etRemark?.text.toString() if (refundAmount.isEmpty()) { // TODO: 显示错误提示 return@setOnClickListener } onConfirmListener?.invoke(refundAmount, remark) dismiss() // 调用挂失接口 callReportLossApi(refundAmount, remark) } // 如果有预设的用户信息,设置它们 @@ -71,15 +72,66 @@ this.username = username this.cardNumber = cardNumber this.balance = balance binding?.apply { tvUsernameValue.text = username tvCardNumberValue.text = cardNumber etBalance.setText(balance+"元") etBalance.setText(balance + "元") } } fun setOnConfirmListener(listener: ( String, String) -> Unit) { fun setOnConfirmListener(listener: (String, String) -> Unit) { onConfirmListener = listener } fun setOnSuccessListener(listener: () -> Unit) { onSuccessListener = listener } /** * 调用挂失接口 */ private fun callReportLossApi(refundAmount: String, remark: String) { val params = mutableMapOf<String, Any>() params["cardNum"] = cardNumber ?: "" // 处理余额格式,去除千位分隔符逗号和"元"字符 val balanceValue = balance?.replace("元", "")?.replace(",", "")?.toFloatOrNull() ?: 0f params["money"] = balanceValue params["refund"] = refundAmount.toFloatOrNull() ?: 0f params["remarks"] = remark.ifEmpty { "挂失" } params["operator"] = BaseApplication.userId ApiManager.getInstance().requestPostLoading( context, "terminal/card/termReportLoss", ReportLossResult::class.java, params, object : SubscriberListener<BaseResponse<ReportLossResult>>() { override fun onNext(response: BaseResponse<ReportLossResult>) { if (response.success && response.code == "0001") { ToastUtil.show("挂失成功") onConfirmListener?.invoke(refundAmount, remark) onSuccessListener?.invoke() dismiss() } else { ToastUtil.show(response.msg ?: "挂失失败") } } override fun onError(e: Throwable?) { super.onError(e) ToastUtil.show("挂失失败: ${e?.message ?: "网络错误"}") } } ) } /** * 挂失接口返回结果 */ data class ReportLossResult( val content: Boolean? = null ) } generallibrary/src/main/res/drawable/edit_text_bg.xml
@@ -1,14 +1,17 @@ <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <solid android:color="#FFFFFF" /> <corners android:radius="8dp" /> <stroke android:width="1dp" android:color="#E0E0E0" /> <padding android:bottom="8dp" android:left="12dp" android:right="12dp" android:top="8dp" /> </shape> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_focused="true"> <shape android:shape="rectangle"> <solid android:color="@android:color/white" /> <stroke android:width="2dp" android:color="@color/base_blue_bg" /> <corners android:radius="8dp" /> </shape> </item> <item> <shape android:shape="rectangle"> <solid android:color="@android:color/white" /> <stroke android:width="1dp" android:color="#e0e0e0" /> <corners android:radius="8dp" /> </shape> </item> </selector> generallibrary/src/main/res/layout/activity_card_list.xml
@@ -43,8 +43,10 @@ android:overScrollMode="never" /> <com.scwang.smart.refresh.footer.ClassicsFooter android:id="@+id/footer" android:layout_width="match_parent" android:layout_height="wrap_content" /> android:layout_height="wrap_content" app:srlClassicsSpinnerStyle="Translate" /> </com.scwang.smart.refresh.layout.SmartRefreshLayout> generallibrary/src/main/res/layout/activity_card_write_success.xml
New file @@ -0,0 +1,88 @@ <?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" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/colorBackground"> <com.dayu.baselibrary.view.TitleBar android:id="@+id/titleBar" android:layout_width="match_parent" android:layout_height="@dimen/dimen_title_height" android:background="@color/title_bar_bg" android:elevation="4dp" app:centerText="写卡结果" app:leftImage="@mipmap/icon_back" app:layout_constraintTop_toTopOf="parent" /> <androidx.cardview.widget.CardView android:id="@+id/successContainer" android:layout_width="match_parent" android:layout_height="0dp" android:layout_marginStart="16dp" android:layout_marginTop="24dp" android:layout_marginEnd="16dp" android:layout_marginBottom="80dp" app:cardBackgroundColor="@android:color/white" app:cardCornerRadius="12dp" app:cardElevation="4dp" app:layout_constraintBottom_toTopOf="@id/btnConfirm" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/titleBar"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical" android:padding="32dp"> <ImageView android:id="@+id/successIcon" android:layout_width="150dp" android:layout_height="150dp" android:scaleType="fitCenter" android:src="@drawable/icon_success" /> <TextView android:id="@+id/successTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="24dp" android:text="写卡成功" android:textColor="#4CAF50" android:textSize="24sp" android:textStyle="bold" /> <TextView android:id="@+id/successMessage" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="16dp" android:gravity="center" android:text="卡片信息已成功写入\n请妥善保管您的卡片" android:textColor="#666666" android:textSize="16sp" android:lineSpacingExtra="4dp" /> </LinearLayout> </androidx.cardview.widget.CardView> <Button android:id="@+id/btnConfirm" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginStart="32dp" android:layout_marginEnd="32dp" android:layout_marginBottom="24dp" android:background="@drawable/bg_button_primary" android:text="确定" android:textColor="@android:color/white" android:textSize="18sp" android:textStyle="bold" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout> generallibrary/src/main/res/layout/activity_recharge_detail.xml
New file @@ -0,0 +1,407 @@ <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/base_green_bg"> <com.dayu.baselibrary.view.TitleBar android:id="@+id/titleBar" android:layout_width="match_parent" android:layout_height="@dimen/dimen_title_height" android:background="@color/title_bar_bg" android:elevation="4dp" app:centerText="充值" app:leftImage="@mipmap/icon_back" app:layout_constraintTop_toTopOf="parent" /> <ScrollView android:id="@+id/recharge_scrollView" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@+id/titleBar" android:layout_above="@+id/recharge_registBtn" android:fillViewport="true" android:scrollbars="none"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="12dp"> <!-- 卡片信息卡片 --> <androidx.cardview.widget.CardView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="10dp" app:cardCornerRadius="8dp" app:cardElevation="2dp" app:cardBackgroundColor="@android:color/white"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="12dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:layout_marginBottom="12dp"> <View android:layout_width="3dp" android:layout_height="16dp" android:background="@color/base_blue_bg" android:layout_marginEnd="8dp" android:layout_gravity="center_vertical" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="卡片信息" android:textColor="#333333" android:textSize="16sp" android:textStyle="bold" android:layout_gravity="center_vertical" /> </LinearLayout> <!-- 姓名和用户编号合并为一行 --> <LinearLayout android:layout_width="match_parent" android:layout_height="40dp" android:layout_marginBottom="6dp" android:orientation="horizontal" android:background="@drawable/item_bg_selector" android:paddingLeft="12dp" android:paddingRight="12dp" android:gravity="center_vertical"> <TextView android:layout_width="70dp" android:layout_height="wrap_content" android:text="姓名:" android:textColor="#666666" android:textSize="13sp" /> <TextView android:id="@+id/userName" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:textColor="#333333" android:textSize="14sp" /> <TextView android:layout_width="70dp" android:layout_height="wrap_content" android:text="卡状态:" android:textColor="#666666" android:textSize="13sp" /> <TextView android:id="@+id/red_statu" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:textColor="@color/red" android:textSize="14sp" android:textStyle="bold" /> </LinearLayout> <!-- 卡号 --> <LinearLayout android:layout_width="match_parent" android:layout_height="40dp" android:layout_marginBottom="6dp" android:orientation="horizontal" android:background="@drawable/item_bg_selector" android:paddingLeft="12dp" android:paddingRight="12dp" android:gravity="center_vertical"> <TextView android:layout_width="70dp" android:layout_height="wrap_content" android:text="卡地址:" android:textColor="#666666" android:textSize="13sp" /> <TextView android:id="@+id/red_initCode" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="" android:textColor="#333333" android:textSize="14sp" android:textStyle="bold" /> </LinearLayout> <!-- 卡状态 --> <LinearLayout android:layout_width="match_parent" android:layout_height="40dp" android:layout_marginBottom="6dp" android:orientation="horizontal" android:background="@drawable/item_bg_selector" android:paddingLeft="12dp" android:paddingRight="12dp" android:gravity="center_vertical"> <TextView android:layout_width="70dp" android:layout_height="wrap_content" android:text="卡编号:" android:textColor="#666666" android:textSize="13sp" /> <TextView android:id="@+id/red_cardNum" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="" android:textColor="#333333" android:textSize="14sp" /> </LinearLayout> <!-- 当前余额 --> <LinearLayout android:layout_width="match_parent" android:layout_height="40dp" android:orientation="horizontal" android:background="@drawable/item_bg_selector" android:paddingLeft="12dp" android:paddingRight="12dp" android:gravity="center_vertical"> <TextView android:layout_width="70dp" android:layout_height="wrap_content" android:text="当前余额:" android:textColor="#666666" android:textSize="13sp" /> <TextView android:id="@+id/red_remainder_blance" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:textColor="@color/base_blue_bg" android:textSize="16sp" android:textStyle="bold" /> </LinearLayout> </LinearLayout> </androidx.cardview.widget.CardView> <!-- 充值信息卡片 --> <androidx.cardview.widget.CardView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="10dp" app:cardCornerRadius="8dp" app:cardElevation="2dp" app:cardBackgroundColor="@android:color/white"> <LinearLayout android:id="@+id/recharge_LL" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="12dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:layout_marginBottom="12dp"> <View android:layout_width="3dp" android:layout_height="16dp" android:background="@color/red" android:layout_marginEnd="8dp" android:layout_gravity="center_vertical" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="充值信息" android:textColor="#333333" android:textSize="16sp" android:textStyle="bold" android:layout_gravity="center_vertical" /> </LinearLayout> <!-- 充值金额和赠送金额合并为一行 --> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:layout_marginBottom="8dp"> <LinearLayout android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:orientation="vertical" android:layout_marginEnd="8dp"> <TextView android:id="@+id/recharge_tx" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="6dp" android:text="充值金额(元):" android:textColor="@color/red" android:textSize="14sp" android:textStyle="bold" /> <EditText android:id="@+id/recharge_morny" android:layout_width="match_parent" android:layout_height="42dp" android:background="@drawable/edit_text_bg" android:hint="请输入充值金额" android:inputType="numberDecimal" android:padding="12dp" android:textSize="14sp" android:maxLines="1" /> </LinearLayout> <LinearLayout android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:orientation="vertical" android:layout_marginStart="8dp"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="6dp" android:text="赠送金额(元):" android:textColor="#666666" android:textSize="14sp" /> <EditText android:id="@+id/recharge_water" android:layout_width="match_parent" android:layout_height="42dp" android:background="@drawable/edit_text_bg" android:hint="赠送金额(选填)" android:inputType="numberDecimal" android:padding="12dp" android:textSize="14sp" android:maxLines="1" /> </LinearLayout> </LinearLayout> </LinearLayout> </androidx.cardview.widget.CardView> <!-- 支付方式卡片 --> <androidx.cardview.widget.CardView android:layout_width="match_parent" android:layout_height="wrap_content" app:cardCornerRadius="8dp" app:cardElevation="2dp" app:cardBackgroundColor="@android:color/white"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="12dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:layout_marginBottom="12dp"> <View android:layout_width="3dp" android:layout_height="16dp" android:background="@color/base_blue_bg" android:layout_marginEnd="8dp" android:layout_gravity="center_vertical" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="支付方式" android:textColor="#333333" android:textSize="16sp" android:textStyle="bold" android:layout_gravity="center_vertical" /> </LinearLayout> <RadioGroup android:id="@+id/newCard_paymentMethod" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <RadioButton android:id="@+id/newCard_cashPayment" android:layout_width="0dp" android:layout_height="42dp" android:layout_marginEnd="8dp" android:layout_weight="1" android:background="@drawable/radio_selector" android:button="@null" android:checked="true" android:gravity="center" android:text="现金" android:textColor="@color/radio_button_text_color" android:textSize="14sp" /> <RadioButton android:id="@+id/newCard_posPayment" android:layout_width="0dp" android:layout_height="42dp" android:layout_marginEnd="8dp" android:layout_weight="1" android:background="@drawable/radio_selector" android:button="@null" android:gravity="center" android:text="POS机" android:textColor="@color/radio_button_text_color" android:textSize="14sp" /> <RadioButton android:id="@+id/newCard_bankTransfer" android:layout_width="0dp" android:layout_height="42dp" android:layout_weight="1" android:background="@drawable/radio_selector" android:button="@null" android:gravity="center" android:text="银行转账" android:textColor="@color/radio_button_text_color" android:textSize="14sp" /> </RadioGroup> </LinearLayout> </androidx.cardview.widget.CardView> </LinearLayout> </ScrollView> <Button android:id="@+id/recharge_registBtn" android:layout_width="match_parent" android:layout_height="50dp" android:layout_alignParentBottom="true" android:layout_marginLeft="12dp" android:layout_marginTop="6dp" android:layout_marginRight="12dp" android:layout_marginBottom="12dp" android:background="@drawable/recharge_button_ripple" android:elevation="4dp" android:gravity="center" android:text="确认充值(写卡)" android:textColor="@color/white" android:textSize="16sp" android:textStyle="bold" /> </RelativeLayout> generallibrary/src/main/res/layout/fragment_recharge.xml
@@ -5,7 +5,6 @@ android:layout_height="match_parent" android:background="@color/base_green_bg"> <LinearLayout android:id="@+id/recharge_read_LL" android:layout_width="match_parent" @@ -19,7 +18,6 @@ android:layout_height="match_parent" android:layout_margin="16dp" app:cardCornerRadius="8dp" app:cardElevation="2dp"> <RelativeLayout @@ -53,7 +51,6 @@ android:layout_centerVertical="true" android:layout_marginBottom="40dp" android:gravity="center" android:text="请将卡贴在设备上进行读卡" android:textColor="#333333" android:textSize="@dimen/text_size" @@ -67,323 +64,22 @@ android:layout_gravity="center" android:scaleType="fitCenter" android:src="@mipmap/nfc_write" /> <!-- 显示读到的卡号 --> <TextView android:id="@+id/red_initCode" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="20dp" android:gravity="center" android:text="" android:textColor="#333333" android:textSize="@dimen/new_card_size" android:textStyle="bold" /> </LinearLayout> </RelativeLayout> </androidx.cardview.widget.CardView> </LinearLayout> <ScrollView android:layout_width="match_parent" android:layout_height="match_parent" android:layout_above="@+id/recharge_registBtn" android:fillViewport="true" android:visibility="gone"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="16dp"> <LinearLayout android:id="@+id/recharge_text_LL" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:visibility="visible"> <androidx.cardview.widget.CardView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="10dp" app:cardCornerRadius="8dp" app:cardElevation="2dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="12dp"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="12dp" android:text="卡片信息" android:textColor="#333333" android:textSize="16sp" android:textStyle="bold" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="5dp" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="卡号:" android:textColor="#666666" android:textSize="@dimen/text_size" /> <TextView android:id="@+id/red_initCode" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="" android:textColor="#333333" android:textSize="@dimen/new_card_size" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="5dp" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="卡状态:" android:textColor="#666666" android:textSize="@dimen/text_size" /> <TextView android:id="@+id/red_statu" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="@color/red" android:textSize="@dimen/new_card_size" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="5dp" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="姓名:" android:textColor="#666666" android:textSize="@dimen/new_card_size" /> <TextView android:id="@+id/userName" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#333333" android:textSize="@dimen/new_card_size" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="5dp" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="用户编号:" android:textColor="#666666" android:textSize="@dimen/text_size" /> <TextView android:id="@+id/red_userCode" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="" android:textColor="#333333" android:textSize="@dimen/new_card_size" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="5dp" android:orientation="horizontal" android:visibility="visible"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="当前余额:" android:textColor="#666666" android:textSize="@dimen/text_size" /> <TextView android:id="@+id/red_remainder_blance" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#333333" android:textSize="@dimen/new_card_size" /> </LinearLayout> </LinearLayout> </androidx.cardview.widget.CardView> <androidx.cardview.widget.CardView android:layout_width="match_parent" android:layout_height="wrap_content" app:cardCornerRadius="8dp" app:cardElevation="2dp"> <LinearLayout android:id="@+id/recharge_LL" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="12dp"> <TextView android:id="@+id/red_recharge_water" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="8dp" android:text="充值水量:" android:textColor="#333333" android:textSize="@dimen/text_size" android:visibility="gone" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/base_green_bg" android:orientation="vertical" android:padding="12dp"> <TextView android:id="@+id/recharge_tx" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="8dp" android:text="充值金额(元):" android:textColor="@color/red" android:textSize="@dimen/new_card_size" android:textStyle="bold" /> <EditText android:id="@+id/recharge_morny" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@android:color/white" android:hint="请输入充值的金额" android:inputType="numberDecimal" android:padding="5dp" android:textSize="@dimen/new_card_size" /> <EditText android:id="@+id/recharge_water" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="5dp" android:background="@android:color/white" android:hint="请输入赠送的金额(选填)" android:inputType="numberDecimal" android:padding="5dp" android:textSize="@dimen/new_card_size" /> </LinearLayout> </LinearLayout> </androidx.cardview.widget.CardView> <androidx.cardview.widget.CardView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" app:cardCornerRadius="8dp" app:cardElevation="2dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="12dp"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="10dp" android:text="支付方式" android:textColor="#333333" android:textSize="18sp" android:textStyle="bold" /> <RadioGroup android:id="@+id/newCard_paymentMethod" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <RadioButton android:id="@+id/newCard_cashPayment" android:layout_width="0dp" android:layout_height="40dp" android:layout_marginRight="15dp" android:layout_weight="1" android:background="@drawable/radio_selector" android:button="@null" android:checked="true" android:gravity="center" android:text="现金" android:textColor="@color/radio_button_text_color" android:textSize="@dimen/new_card_size" /> <RadioButton android:id="@+id/newCard_posPayment" android:layout_width="0dp" android:layout_height="40dp" android:layout_marginRight="15dp" android:layout_weight="1" android:background="@drawable/radio_selector" android:button="@null" android:gravity="center" android:text="POS机" android:textColor="@color/radio_button_text_color" android:textSize="@dimen/new_card_size" /> <RadioButton android:id="@+id/newCard_bankTransfer" android:layout_width="0dp" android:layout_height="40dp" android:layout_weight="1" android:background="@drawable/radio_selector" android:button="@null" android:gravity="center" android:text="银行转账" android:textColor="@color/radio_button_text_color" android:textSize="@dimen/new_card_size" /> </RadioGroup> </LinearLayout> </androidx.cardview.widget.CardView> </LinearLayout> </LinearLayout> </ScrollView> <Button android:id="@+id/recharge_registBtn" android:layout_width="match_parent" android:layout_height="50dp" android:layout_alignParentBottom="true" android:layout_marginLeft="16dp" android:layout_marginTop="10dp" android:layout_marginRight="16dp" android:layout_marginBottom="10dp" android:background="@drawable/recharge_button_ripple" android:elevation="2dp" android:gravity="center" android:text="下一步(写卡)" android:textColor="@color/white" android:textSize="@dimen/new_card_size" android:textStyle="bold" android:visibility="gone" /> </RelativeLayout>