如何根据Checkbox状态将EditText内容插入对应Tab购物清单?
问题描述
我正在用Kotlin开发一款购物清单App,主界面设有4个对应不同商店的Tab页面。在新增商品页面,有两个EditText分别用于输入商品名称和数量,还有4个与Tab同名的Checkbox。我希望勾选Checkbox后,能把EditText里的内容插入到对应的Tab页面中,未找到相关实现示例,恳请提供帮助。
附新增页面的XML布局代码:
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" > <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent" android:paddingTop="30sp" tools:context=".ItemInputActivity" > <EditText android:id="@+id/productId" android:layout_width="0dp" android:layout_height="wrap_content" android:visibility="gone" tools:ignore="MissingConstraints" /> <EditText android:id="@+id/inputItem" android:layout_width="0dp" android:layout_height="50dp" android:layout_marginStart="22dp" android:layout_marginTop="26dp" android:layout_marginEnd="22dp" android:ems="10" android:hint="@string/naziv_proizvoda" android:background="@drawable/bg_form" android:paddingStart="10dp" android:paddingEnd="10dp" android:inputType="textPersonName" android:textSize="16sp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.0" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" android:importantForAutofill="no" /> <EditText android:id="@+id/inputNumber" android:layout_width="0dp" android:layout_height="50dp" android:layout_marginStart="22dp" android:layout_marginTop="20sp" android:layout_marginEnd="22dp" android:background="@drawable/bg_form" android:ems="10" android:hint="@string/kolicina_proizvoda" android:importantForAutofill="no" android:inputType="number" android:paddingStart="10dp" android:paddingEnd="10dp" android:textSize="16sp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.0" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/inputItem" /> <CheckBox android:id="@+id/konzumCheck" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="22sp" android:layout_marginEnd="22sp" android:minHeight="48dp" android:text="@string/konzum" app:layout_constraintBottom_toTopOf="@+id/lidlCheck" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/inputNumber" /> <CheckBox android:id="@+id/lidlCheck" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="22sp" android:layout_marginEnd="22sp" android:text="@string/lidl" android:minHeight="48dp" app:layout_constraintTop_toBottomOf="@id/konzumCheck" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintBottom_toTopOf="@+id/kauflandCheck" /> <CheckBox android:id="@+id/kauflandCheck" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="22sp" android:layout_marginEnd="22sp" android:text="@string/kaufland" android:minHeight="48dp" app:layout_constraintTop_toBottomOf="@id/lidlCheck" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintBottom_toTopOf="@+id/sparCheck" /> <CheckBox android:id="@+id/sparCheck" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="22sp" android:layout_marginEnd="22sp" android:text="@string/spar" android:minHeight="48dp" app:layout_constraintTop_toBottomOf="@id/kauflandCheck" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintBottom_toTopOf="@+id/inputButton" /> <Button android:id="@+id/inputButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="35sp" android:text="@string/spremi" android:textSize="12sp" app:layout_constraintEnd_toStartOf="@id/itemListActivity" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/sparCheck" /> <Button android:id="@+id/itemListActivity" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="35sp" android:text="@string/lista_proizvoda" android:textSize="12sp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@id/inputButton" app:layout_constraintTop_toBottomOf="@id/sparCheck" /> </androidx.constraintlayout.widget.ConstraintLayout> </FrameLayout>
实现方案
1. 定义商品数据模型
创建数据类存储商品核心信息:
data class ShoppingItem( val id: Int = 0, val name: String, val quantity: Int, val store: String // 对应商店标识,如"konzum"、"lidl" )
2. 用ViewModel共享跨页面数据
通过ViewModel实现新增页面与Tab页面的数据同步:
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel class ShoppingViewModel : ViewModel() { // 每个商店对应独立的商品列表 val konzumiItems = MutableLiveData<MutableList<ShoppingItem>>(mutableListOf()) val lidlItems = MutableLiveData<MutableList<ShoppingItem>>(mutableListOf()) val kauflandItems = MutableLiveData<MutableList<ShoppingItem>>(mutableListOf()) val sparItems = MutableLiveData<MutableList<ShoppingItem>>(mutableListOf()) // 向指定商店添加商品 fun addItemToStore(item: ShoppingItem) { when (item.store) { "konzum" -> updateList(konzumiItems, item) "lidl" -> updateList(lidlItems, item) "kaufland" -> updateList(kauflandItems, item) "spar" -> updateList(sparItems, item) } } private fun updateList(liveData: MutableLiveData<MutableList<ShoppingItem>>, item: ShoppingItem) { val currentList = liveData.value ?: mutableListOf() currentList.add(item) liveData.postValue(currentList) } }
3. 新增页面逻辑处理
在ItemInputActivity中处理输入验证、Checkbox选择,并调用ViewModel添加商品:
import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import androidx.lifecycle.ViewModelProvider import kotlinx.android.synthetic.main.activity_item_input.* import android.widget.Toast class ItemInputActivity : AppCompatActivity() { private lateinit var viewModel: ShoppingViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_item_input) viewModel = ViewModelProvider(this)[ShoppingViewModel::class.java] inputButton.setOnClickListener { val itemName = inputItem.text.toString().trim() val quantityStr = inputNumber.text.toString().trim() // 输入验证 if (itemName.isEmpty() || quantityStr.isEmpty()) { Toast.makeText(this, "请填写完整信息", Toast.LENGTH_SHORT).show() return@setOnClickListener } val quantity = quantityStr.toInt() // 遍历Checkbox,添加商品到对应商店 val checkedStores = mutableListOf<String>() if (konzumCheck.isChecked) checkedStores.add("konzum") if (lidlCheck.isChecked) checkedStores.add("lidl") if (kauflandCheck.isChecked) checkedStores.add("kaufland") if (sparCheck.isChecked) checkedStores.add("spar") if (checkedStores.isEmpty()) { Toast.makeText(this, "请选择至少一个商店", Toast.LENGTH_SHORT).show() return@setOnClickListener } checkedStores.forEach { store -> viewModel.addItemToStore(ShoppingItem(name = itemName, quantity = quantity, store = store)) } // 清空输入并关闭页面 inputItem.text.clear() inputNumber.text.clear() finish() } // 跳转到主界面按钮逻辑 itemListActivity.setOnClickListener { finish() } } }
4. Tab页面(Fragment)实现
每个Tab对应一个Fragment,观察ViewModel数据变化并更新列表:
import android.os.Bundle import androidx.fragment.app.Fragment import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.lifecycle.ViewModelProvider import androidx.recyclerview.widget.LinearLayoutManager import kotlinx.android.synthetic.main.fragment_store_list.* class KonzumFragment : Fragment() { private lateinit var viewModel: ShoppingViewModel private lateinit var adapter: ShoppingItemAdapter override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { return inflater.inflate(R.layout.fragment_store_list, container, false) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) viewModel = ViewModelProvider(requireActivity())[ShoppingViewModel::class.java] // 初始化RecyclerView adapter = ShoppingItemAdapter() store_recyclerView.layoutManager = LinearLayoutManager(context) store_recyclerView.adapter = adapter // 监听商品列表变化 viewModel.konzumiItems.observe(viewLifecycleOwner) { items -> adapter.updateItems(items) } } }
其他商店Fragment(LidlFragment、KauflandFragment、SparFragment)逻辑一致,仅需替换观察的LiveData对象。
5. 商品列表Adapter
实现RecyclerView的Adapter展示商品:
import android.view.LayoutInflater import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView import kotlinx.android.synthetic.main.item_shopping.view.* class ShoppingItemAdapter : RecyclerView.Adapter<ShoppingItemAdapter.ViewHolder>() { private var items = mutableListOf<ShoppingItem>() fun updateItems(newItems: List<ShoppingItem>) { items.clear() items.addAll(newItems) notifyDataSetChanged() } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val view = LayoutInflater.from(parent.context).inflate(R.layout.item_shopping, parent, false) return ViewHolder(view) } override fun onBindViewHolder(holder: ViewHolder, position: Int) { val item = items[position] holder.itemView.tv_item_name.text = item.name holder.itemView.tv_item_quantity.text = "数量: ${item.quantity}" } override fun getItemCount(): Int = items.size class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) }
6. 主界面Tab配置
用ViewPager2+TabLayout实现Tab切换:
import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import androidx.viewpager2.adapter.FragmentStateAdapter import com.google.android.material.tabs.TabLayoutMediator import kotlinx.android.synthetic.main.activity_main.* class MainActivity : AppCompatActivity() { private val tabTitles = arrayOf("Konzum", "Lidl", "Kaufland", "Spar") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) viewPager2.adapter = object : FragmentStateAdapter(this) { override fun getItemCount(): Int = 4 override fun createFragment(position: Int): Fragment { return when (position) { 0 -> KonzumFragment() 1 -> LidlFragment() 2 -> KauflandFragment() 3 -> SparFragment() else -> KonzumFragment() } } } // 关联TabLayout与ViewPager2 TabLayoutMediator(tabLayout, viewPager2) { tab, position -> tab.text = tabTitles[position] }.attach() } }
内容的提问来源于stack exchange,提问作者Petar Nenadić
相关产品推荐
相关产品推荐

