Kotlin中如何在ExpandableListView头部正确显示子项数量
Hey there, let's fix that ExpandableListView header count issue you're dealing with. I’ve walked through your problem context, and here’s a step-by-step solution to get those group headers showing the correct number of child items, paired with your API-fetched today/tomorrow/upcoming tasks.
Most often, the wrong count in group headers comes from:
- Incorrect mapping of API data into grouped lists
- A bug in the adapter's
getChildrenCount()method returning fixed values instead of real child counts - Mistakes when binding the count value to the header TextView
2.1 Ensure Your API Data is Grouped Correctly
First, let's confirm your API response model and data parsing. Assume your API returns data like this:
// API Response Models data class TaskResponse( val todayTasks: List<Task>, val tomorrowTasks: List<Task>, val upcomingTasks: List<Task> ) data class Task( val id: String, val title: String, val description: String )
In your Activity, after fetching the API data, restructure it into a format that's easy for the ExpandableListView adapter to use:
// Inside your Activity's API success callback val groupedTasks = listOf( "今日任务" to apiResponse.todayTasks, "明日任务" to apiResponse.tomorrowTasks, "未来任务" to apiResponse.upcomingTasks )
2.2 Fix the ExpandableListAdapter
The adapter needs to reliably return child counts and bind them to the header. Here's the corrected adapter code:
class TaskExpandableAdapter( private val context: Context, private val groupedTasks: List<Pair<String, List<Task>>> ) : BaseExpandableListAdapter() { // Return total number of groups (3: today/tomorrow/upcoming) override fun getGroupCount(): Int = groupedTasks.size // Critical: Return REAL child count for the selected group override fun getChildrenCount(groupPosition: Int): Int = groupedTasks[groupPosition].second.size override fun getGroup(groupPosition: Int): Any = groupedTasks[groupPosition].first override fun getChild(groupPosition: Int, childPosition: Int): Any = groupedTasks[groupPosition].second[childPosition] override fun getGroupId(groupPosition: Int): Long = groupPosition.toLong() override fun getChildId(groupPosition: Int, childPosition: Int): Long = childPosition.toLong() override fun hasStableIds(): Boolean = true // Bind group header with correct count override fun getGroupView( groupPosition: Int, isExpanded: Boolean, convertView: View?, parent: ViewGroup? ): View { val headerView = convertView ?: LayoutInflater.from(context) .inflate(R.layout.group_header_layout, parent, false) // Get header views val groupTitleTv = headerView.findViewById<TextView>(R.id.tv_group_title) val childCountTv = headerView.findViewById<TextView>(R.id.tv_child_count) val expandIconIv = headerView.findViewById<ImageView>(R.id.iv_expand_icon) // Set title and count val groupData = groupedTasks[groupPosition] groupTitleTv.text = groupData.first childCountTv.text = "(${groupData.second.size})" // Update expand/collapse icon (optional) expandIconIv.setImageResource( if (isExpanded) R.drawable.ic_collapse_arrow else R.drawable.ic_expand_arrow ) return headerView } // Bind child task items override fun getChildView( groupPosition: Int, childPosition: Int, isLastChild: Boolean, convertView: View?, parent: ViewGroup? ): View { val childView = convertView ?: LayoutInflater.from(context) .inflate(R.layout.task_child_item, parent, false) val task = getChild(groupPosition, childPosition) as Task childView.findViewById<TextView>(R.id.tv_task_title).text = task.title childView.findViewById<TextView>(R.id.tv_task_desc).text = task.description return childView } override fun isChildSelectable(groupPosition: Int, childPosition: Int): Boolean = true }
2.3 Initialize Adapter Correctly in Activity
Make sure you set up the adapter after the API data is fetched:
class TaskListActivity : AppCompatActivity() { private lateinit var expandableListView: ExpandableListView private lateinit var taskAdapter: TaskExpandableAdapter override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_task_list) expandableListView = findViewById(R.id.expandable_list_task) fetchTasksFromApi() } private fun fetchTasksFromApi() { // Replace with your actual API call (Retrofit, OkHttp, etc.) val apiCall = /* Your API request logic */ apiCall.enqueue(object : Callback<TaskResponse> { override fun onResponse(call: Call<TaskResponse>, response: Response<TaskResponse>) { response.body()?.let { taskData -> val groupedTasks = listOf( "今日任务" to taskData.todayTasks, "明日任务" to taskData.tomorrowTasks, "未来任务" to taskData.upcomingTasks ) taskAdapter = TaskExpandableAdapter(this@TaskListActivity, groupedTasks) expandableListView.setAdapter(taskAdapter) // Optional: Expand all groups by default for (i in 0 until taskAdapter.groupCount) { expandableListView.expandGroup(i) } } } override fun onFailure(call: Call<TaskResponse>, t: Throwable) { // Handle API failure } }) } }
If the count still doesn't show correctly, check these:
- Verify your API response is returning the correct task lists (no empty lists where they shouldn't be)
- Double-check that
getChildrenCount()isn't returning a hardcoded value (e.g.,return 2instead of the real list size) - Ensure the header layout's TextView IDs match what you're using in the adapter
- If you're refreshing data later, call
taskAdapter.notifyDataSetChanged()to update the views
内容的提问来源于stack exchange,提问作者Jay Mistry

