Android电商App:如何默认选中首个地址MaterialCardView
问题描述
开发电商App时,地址列表支持用户添加多个地址,每次操作需手动选择地址。每个地址有独立的address id标识选中项。需求是:当地址列表非空时,默认选中首个地址(位置0的MaterialCardView)。尝试初始化时将selectedAddressPos设为0,仅能显示选中状态,但无法获取对应的address id,地址数据存储在Firebase,无法通过XML设置默认选中。
解决方案
问题核心是仅设置了selectedAddressPos,但未同步更新lastCheckedAddress、lastCheckedCard等状态变量,也未触发选中后的逻辑(比如样式更新、通知外部选中的地址ID)。通过以下步骤修复:
- 在Adapter初始化时同步默认选中的状态变量
- 统一卡片样式设置逻辑,确保默认选中与手动选中的样式一致
- 新增回调通知外部组件默认选中的地址ID
修改后的完整代码
import android.content.Context import android.util.Log import android.util.TypedValue import android.view.LayoutInflater import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView import com.google.android.material.card.MaterialCardView import com.sbhs.stone.R import com.sbhs.stone.data.UserData import com.sbhs.stone.databinding.LayoutAddressCardBinding import com.sbhs.stone.ui.getCompleteAddress private const val TAG = "AddressAdapter" class AddressAdapter( private val context: Context, addresses: List<UserData.Address>, private val isSelect: Boolean, ) : RecyclerView.Adapter<AddressAdapter.ViewHolder>() { lateinit var onClickListener: OnClickListener var data: List<UserData.Address> = addresses var lastCheckedAddress: String? = null private var lastCheckedCard: MaterialCardView? = null var selectedAddressPos = -1 init { // 初始化默认选中首个地址(如果列表非空) if (data.isNotEmpty()) { selectedAddressPos = 0 lastCheckedAddress = data[0].addressId } } inner class ViewHolder(private var binding: LayoutAddressCardBinding) : RecyclerView.ViewHolder(binding.root) { fun bind(address: UserData.Address, position: Int) { val isSelected = position == selectedAddressPos binding.addressCard.isChecked = isSelected // 根据选中状态设置卡片样式 updateCardStyle(binding.addressCard, isSelected) binding.addressPersonNameTv.text = context.getString(R.string.person_name, address.fName, address.lName) binding.addressCompleteAddressTv.text = getCompleteAddress(address) binding.addressMobileTv.text = address.phoneNumber if (isSelect) { binding.addressCard.setOnClickListener { onCardClick(position, address.addressId, it as MaterialCardView) } } binding.addressEditBtn.setOnClickListener { onClickListener.onEditClick(address.addressId) } binding.addressDeleteBtn.setOnClickListener { onClickListener.onDeleteClick(address.addressId) notifyDataSetChanged() } } } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { return ViewHolder( LayoutAddressCardBinding.inflate( LayoutInflater.from(parent.context), parent, false ) ) } override fun onBindViewHolder(holder: ViewHolder, position: Int) { holder.bind(data[position], position) // 首次绑定默认选中项时,保存对应的卡片引用 if (position == selectedAddressPos && lastCheckedCard == null) { lastCheckedCard = holder.binding.addressCard // 通知外部默认选中的地址 onClickListener.onAddressSelected(data[position].addressId) } } override fun getItemCount(): Int = data.size interface OnClickListener { fun onEditClick(addressId: String) fun onDeleteClick(addressId: String) // 新增回调,通知外部选中的地址(包括默认选中) fun onAddressSelected(addressId: String) } private fun onCardClick(position: Int, addressId: String, card: MaterialCardView) { if (addressId != lastCheckedAddress) { updateCardStyle(card, true) lastCheckedCard?.let { updateCardStyle(it, false) } lastCheckedAddress = addressId lastCheckedCard = card selectedAddressPos = position // 通知外部选中的地址 onClickListener.onAddressSelected(addressId) Log.d(TAG, "onCardClick: selected address = $addressId") } } // 统一更新卡片样式的方法 private fun updateCardStyle(card: MaterialCardView, isSelected: Boolean) { card.apply { strokeColor = if (isSelected) { context.getColor(R.color.blue_accent_300) } else { context.getColor(R.color.light_gray) } isChecked = isSelected strokeWidth = TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, if (isSelected) 2F else 1F, resources.displayMetrics ).toInt() } } }
关键修改说明
- 初始化同步状态:在Adapter的
init块中判断地址列表非空时,直接设置selectedAddressPos=0并赋值lastCheckedAddress,确保状态变量同步。 - 统一样式逻辑:提取
updateCardStyle方法,避免重复代码,保证默认选中和手动选中的样式一致。 - 保存卡片引用:在
onBindViewHolder中保存默认选中项的卡片引用,确保后续切换选中时能正确重置之前的样式。 - 新增选中回调:扩展
OnClickListener添加onAddressSelected方法,在默认选中或手动选中时通知外部组件当前的地址ID,解决无法获取地址ID的问题。
内容的提问来源于stack exchange,提问作者kushal bardiya
相关产品推荐
相关产品推荐

