如何根据游戏关卡完成状态设置RecyclerView项的可点击性?
实现RecyclerView递进解锁关卡列表的方案
1. 先定义关卡数据模型
创建一个简单的数据类,存关卡的核心状态:
data class Level( val id: Int, // 关卡ID,从1开始计数 val name: String, // 比如"关卡1" val isCompleted: Boolean, // 是否通关 var isLocked: Boolean // 是否锁定,后续逻辑控制 )
2. 初始化关卡列表并计算锁定状态
核心逻辑是只有前一关完成,当前关才解锁,初始化时直接按这个规则生成列表:
fun initLevelList(): List<Level> { // 先创建基础关卡数据,第一关默认解锁 val levels = mutableListOf( Level(1, "关卡1", isCompleted = false, isLocked = false), Level(2, "关卡2", isCompleted = false, isLocked = true), Level(3, "关卡3", isCompleted = false, isLocked = true), // 按需添加更多关卡 ) // 遍历更新锁定状态(从第二关开始) for (i in 1 until levels.size) { val prevLevel = levels[i-1] // 前一关没完成,当前关就锁定;反之解锁 levels[i].isLocked = !prevLevel.isCompleted } return levels }
3. 实现RecyclerView的Adapter
Adapter负责根据关卡状态渲染UI,锁定的关卡置灰、不可点击,完成的关卡显示通关标识:
3.1 ViewHolder定义
class LevelViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { val tvLevelName: TextView = itemView.findViewById(R.id.tv_level_name) val ivLock: ImageView = itemView.findViewById(R.id.iv_lock) val ivCompleted: ImageView = itemView.findViewById(R.id.iv_completed) val levelCard: CardView = itemView.findViewById(R.id.level_card) }
3.2 Adapter核心代码
class LevelAdapter( private val levels: MutableList<Level>, private val onLevelClick: (Level) -> Unit ) : RecyclerView.Adapter<LevelViewHolder>() { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LevelViewHolder { val view = LayoutInflater.from(parent.context) .inflate(R.layout.item_level, parent, false) return LevelViewHolder(view) } override fun onBindViewHolder(holder: LevelViewHolder, position: Int) { val level = levels[position] holder.tvLevelName.text = level.name // 根据状态切换UI if (level.isLocked) { holder.ivLock.visibility = View.VISIBLE holder.ivCompleted.visibility = View.GONE holder.levelCard.alpha = 0.5f // 置灰 holder.levelCard.isClickable = false // 锁定时禁止点击 } else { holder.ivLock.visibility = View.GONE holder.ivCompleted.visibility = if (level.isCompleted) View.VISIBLE else View.GONE holder.levelCard.alpha = 1.0f holder.levelCard.isClickable = true } // 关卡点击事件 holder.levelCard.setOnClickListener { onLevelClick(level) } } override fun getItemCount() = levels.size // 更新关卡状态后刷新列表,同时解锁下一关(如果当前关卡完成) fun updateLevel(updatedLevel: Level) { val index = levels.indexOfFirst { it.id == updatedLevel.id } if (index != -1) { levels[index] = updatedLevel // 当前关卡完成,且不是最后一关时,解锁下一关 if (updatedLevel.isCompleted && index < levels.size - 1) { val nextLevel = levels[index + 1] nextLevel.isLocked = false notifyItemChanged(index + 1) } notifyItemChanged(index) } } }
4. 关卡项布局(item_level.xml)
简单的横向布局示例,可根据需求调整样式:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="16dp" android:orientation="horizontal" android:gravity="center_vertical"> <TextView android:id="@+id/tv_level_name" android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content" android:textSize="18sp"/> <ImageView android:id="@+id/iv_lock" android:layout_width="24dp" android:layout_height="24dp" android:src="@drawable/ic_lock" android:visibility="gone"/> <ImageView android:id="@+id/iv_completed" android:layout_width="24dp" android:layout_height="24dp" android:src="@drawable/ic_check" android:visibility="gone"/> </LinearLayout>
5. 在Activity/Fragment中使用
class MainActivity : AppCompatActivity() { private lateinit var recyclerView: RecyclerView private lateinit var adapter: LevelAdapter private lateinit var levelList: MutableList<Level> override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) recyclerView = findViewById(R.id.recycler_view) levelList = initLevelList().toMutableList() adapter = LevelAdapter(levelList) { level -> // 这里处理关卡点击逻辑,比如跳转到游戏界面 // 假设游戏结束后,标记当前关卡为完成 val updatedLevel = level.copy(isCompleted = true) // 保存通关状态到本地,避免重启丢失 saveCompletedLevel(updatedLevel.id) adapter.updateLevel(updatedLevel) } recyclerView.adapter = adapter recyclerView.layoutManager = LinearLayoutManager(this) } // 从SharedPreferences读取已通关关卡,初始化时恢复进度 private fun initLevelList(): List<Level> { val savedCompleted = getSharedPreferences("GameData", MODE_PRIVATE) .getStringSet("completedLevels", emptySet()) ?: emptySet() val levels = mutableListOf<Level>() for (i in 1..10) { // 假设有10个关卡 val isCompleted = savedCompleted.contains(i.toString()) levels.add(Level(i, "关卡$i", isCompleted, isLocked = false)) } // 重新计算锁定状态 for (i in 1 until levels.size) { levels[i].isLocked = !levels[i-1].isCompleted } return levels } // 保存已通关关卡到本地 private fun saveCompletedLevel(levelId: Int) { val sharedPref = getSharedPreferences("GameData", MODE_PRIVATE) val completedSet = sharedPref.getStringSet("completedLevels", mutableSetOf()) ?: mutableSetOf() completedSet.add(levelId.toString()) sharedPref.edit().putStringSet("completedLevels", completedSet).apply() } }
内容的提问来源于stack exchange,提问作者Anil Pandey
相关产品推荐
相关产品推荐

