如何在可扩展列表视图 Kotlin 中获取标题中的子项计数

Posted

技术标签:

【中文标题】如何在可扩展列表视图 Kotlin 中获取标题中的子项计数【英文标题】:How to get child Count in Header in expandable list view Kotlin 【发布时间】:2021-03-29 19:46:25 【问题描述】:

enter image description here

如何让孩子的数量与标题中的图片相同。

API 响应:-

data class ToDoListResponse(
val message: String = "",
val success: Int = 0,
val todays_task_list: MutableList<TodaysTask>,
val todays_task_total: Int = 0,
val tomorows_task_list: MutableList<TodaysTask>,
val tomorrow_task_total: Int = 0,
val upcomming_task_list: MutableList<TodaysTask>,
val upcomming_task_total: Int = 0)

data class TodaysTask(
val created_at: String = "",
val description: String = "",
val due_date: String= "",
val is_completed: String= "",
val is_pinned_task: String= "",
val remind_me: String= "",
val task_id: String= "",
var title: String= "",
val updated_at: String= "",
val user_id: String= ""
)

适配器:-

package com.coronation.jackpotplus.adapter

import android.annotation.SuppressLint
import android.app.DatePickerDialog
import android.content.Context
import android.graphics.Typeface
import android.os.Build
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.*
import androidx.annotation.RequiresApi
import com.coronation.jackpotplus.R
import com.coronation.jackpotplus.model.CommonResponse
import com.coronation.jackpotplus.model.ToDoListResponse
import com.coronation.jackpotplus.network.ApiClient
import com.coronation.jackpotplus.network.ApiService
import com.coronation.jackpotplus.view.ToDoListActivity
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.android.material.textfield.TextInputEditText
import org.jetbrains.anko.layoutInflater
import retrofit2.Call
import retrofit2.Response
import java.text.SimpleDateFormat
import java.time.LocalDate
import java.time.ZoneId
import java.time.format.DateTimeFormatter
import java.util.*


@Suppress("NAME_SHADOWING", "DEPRECATED_IDENTITY_EQUALS")
class CustomExpandableListAdapter(
        context: Context,
        expandableListTitle: ArrayList<String>,
        expandableListDetail: HashMap<String,
                MutableList<ToDoListResponse.TodaysTask>>)
    : BaseExpandableListAdapter()

    private val context: Context
    private val expandableListTitle: ArrayList<String>
    private val expandableListDetail: HashMap<String, MutableList<ToDoListResponse.TodaysTask>>
    private lateinit var edtTitle: TextInputEditText
    private lateinit var edtDes: TextInputEditText
    private lateinit var dueDate: TextView
    private lateinit var txtreminddate: TextView
    private lateinit var createAt: String
    private lateinit var taskId: String
    private var ChildCount: String? = null
    private lateinit var dialog: BottomSheetDialog

    override fun getChild(listPosition: Int, expandedListPosition: Int): Any
    
        return expandableListDetail[expandableListTitle[listPosition]]?.get(expandedListPosition)!!
    

    override fun getChildId(listPosition: Int, expandedListPosition: Int): Long
    
        return expandedListPosition.toLong()
    

    @RequiresApi(Build.VERSION_CODES.O)
    @SuppressLint("InflateParams", "SimpleDateFormat")
    override fun getChildView(listPosition: Int, expandedListPosition: Int, isLastChild: Boolean, convertView: View?, parent: ViewGroup?): View
    
        var convertView = convertView
        if (convertView == null)
        
            val layoutInflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
            convertView = layoutInflater.inflate(R.layout.list_item, null)
        
        val expandedListTextView = convertView?.findViewById(R.id.expandedListItem) as TextView
        val expandedItem = convertView.findViewById(R.id.expandedItem) as LinearLayout
        val txtDelete = convertView.findViewById(R.id.delete) as FrameLayout
        val unpin = convertView.findViewById(R.id.unpin) as FrameLayout
        val pin = convertView.findViewById(R.id.pin) as FrameLayout
        val complete = convertView.findViewById(R.id.complete) as FrameLayout
        val mainPin = convertView.findViewById(R.id.mainPin) as ImageView

        val getset = getChild(listPosition, expandedListPosition) as ToDoListResponse.TodaysTask
        expandedListTextView.text = getset.title
        createAt = getset.created_at
        unpin.visibility = View.GONE
        if (getset.is_pinned_task == "1")
        
            mainPin.visibility = View.VISIBLE
            unpin.visibility = View.VISIBLE
            pin.visibility = View.GONE
        
        else
        
            mainPin.visibility = View.GONE
            pin.visibility = View.VISIBLE
        

        unpin.setOnClickListener 
            pinnedtask(getset.task_id)
        

        pin.setOnClickListener 
            pinnedtask(getset.task_id)
        

        complete.setOnClickListener 
            markascomplete(getset.task_id)
        

        txtDelete.setOnClickListener 
            deleteTask(getset.task_id)
        

        expandedItem.setOnClickListener 
            openTaskDetails()
            taskId = getset.task_id
            edtTitle.setText(getset.title)
            edtDes.setText(getset.description)
            dueDate.visibility = View.VISIBLE
            txtreminddate.visibility = View.VISIBLE
            val dueDate1 = getset.due_date
            val sdf = SimpleDateFormat("yyyy-MM-dd")
            val date = Date(dueDate1.toLong() * 1000)
            dueDate.text = sdf.format(date)
            val remindDate = getset.remind_me
            val sdf1 = SimpleDateFormat("yyyy-MM-dd")
            val date1 = Date(remindDate.toLong() * 1000)
            txtreminddate.text = sdf1.format(date1)
        
        return convertView
    

    private fun pinnedtask(taskId: String)
    
        val retIn = ApiClient.client!!.create(ApiService::class.java)
        retIn.pintask(taskId).enqueue(object : retrofit2.Callback<CommonResponse> 
            override fun onResponse(call: Call<CommonResponse>, response: Response<CommonResponse>) 
                showToast(response.body()?.message)
                notifyDataSetChanged()
                if (context is ToDoListActivity) 
                    context.tasklistAPI("1")
                
            

            override fun onFailure(call: Call<CommonResponse>, t: Throwable) 
                showToast("Shomwthing wents wrong")
            
        )
    

    private fun markascomplete(taskId: String)
    
        val retIn = ApiClient.client!!.create(ApiService::class.java)
        retIn.markcomplete(taskId).enqueue(object : retrofit2.Callback<CommonResponse> 
            override fun onResponse(call: Call<CommonResponse>, response: Response<CommonResponse>) 
                showToast(response.body()?.message)
                notifyDataSetChanged()
                if (context is ToDoListActivity) 
                    context.tasklistAPI("1")
                
            

            override fun onFailure(call: Call<CommonResponse>, t: Throwable) 
                showToast("Shomwthing wents wrong")
            
        )
    

    private fun deleteTask(taskId: String)
    
        val retIn = ApiClient.client!!.create(ApiService::class.java)
        retIn.deteletask(taskId).enqueue(object : retrofit2.Callback<CommonResponse> 
            override fun onResponse(call: Call<CommonResponse>, response: Response<CommonResponse>) 
                showToast(response.body()?.message)
                notifyDataSetChanged()
                if (context is ToDoListActivity) 
                    context.tasklistAPI("1")
                
            

            override fun onFailure(call: Call<CommonResponse>, t: Throwable) 
                showToast("Shomwthing wents wrong")
            

        )
    

    @RequiresApi(Build.VERSION_CODES.O)
    @SuppressLint("InflateParams")
    private fun openTaskDetails()
    
        try
        
            val modalbottomsheet = context.layoutInflater.inflate(R.layout.custom_view_todo, null)
            dialog = BottomSheetDialog(context, R.style.DialogStyle)
            dialog.setContentView(modalbottomsheet)
            edtTitle = dialog.findViewById(R.id.edtTitle)!!
            edtDes = dialog.findViewById(R.id.edtDes)!!
            dueDate = dialog.findViewById(R.id.dueDate)!!
            txtreminddate = dialog.findViewById(R.id.txtreminddate)!!
            val imgDatePicker = dialog.findViewById<ImageView>(R.id.imgDatePicker)
            val imgDatePickerReminder = dialog.findViewById<ImageView>(R.id.imgDatePickerReminder)
            val button = dialog.findViewById<Button>(R.id.Button)

            imgDatePicker?.setOnClickListener 
                showDatePicker(context)
            
            imgDatePickerReminder?.setOnClickListener 
                showDatePickerForRemind(context)
            
            button?.setOnClickListener 
                updateTaskAPI()
            
            dialog.show()
        
        catch (e: Exception)
        
            e.printStackTrace()
        
    

    @RequiresApi(Build.VERSION_CODES.O)
    private fun updateTaskAPI()
    
        val l = LocalDate.parse(dueDate.text, DateTimeFormatter.ofPattern("yyyy-MM-dd"))
        val dueDateTimestamp = l.atStartOfDay(ZoneId.systemDefault()).toInstant().epochSecond
        Toast.makeText(context, dueDateTimestamp.toString(), Toast.LENGTH_SHORT).show()

        val l1 = LocalDate.parse(txtreminddate.text, DateTimeFormatter.ofPattern("yyyy-MM-dd"))
        val remindMeTimestamp = l1.atStartOfDay(ZoneId.systemDefault()).toInstant().epochSecond
        Toast.makeText(context, remindMeTimestamp.toString(), Toast.LENGTH_SHORT).show()

        val retIn = ApiClient.client!!.create(ApiService::class.java)
        retIn.taskupdate(
                createAt,
                edtDes.text?.trim().toString(),
                dueDateTimestamp.toString(),
                remindMeTimestamp.toString(),
                taskId, edtTitle.text?.trim().toString(),
                "1").enqueue(object : retrofit2.Callback<CommonResponse>
        
            override fun onResponse(call: Call<CommonResponse>, response: Response<CommonResponse>)
            
                if (response.body()!!.success == 1)
                
                    dialog.dismiss()
                    showToast(response.body()?.message)
                
            

            override fun onFailure(call: Call<CommonResponse>, t: Throwable)
            
                showToast("Something not right, Please try again.")
            
        
        )
    

    @SuppressLint("InflateParams")
    fun showToast(msg: String?)
    
        try
        
            val inflater = context.layoutInflater
            val layout = inflater.inflate(R.layout.custom_toast, null)
            val text = layout.findViewById<View>(R.id.text) as TextView
            text.text = msg
            val toast = Toast(context)
            toast.duration = Toast.LENGTH_SHORT
            toast.view = layout
            if (toast.view.isShown)
            
                toast.cancel()
            
            else
            
                toast.show()
            
        
        catch (e: Exception)
        
            e.printStackTrace()
        
    

    private fun showDatePickerForRemind(context: Context)
    
        val cal = Calendar.getInstance()
        val dateSetListener =
                DatePickerDialog.OnDateSetListener  _, year, monthOfYear, dayOfMonth ->
                    cal.set(Calendar.YEAR, year)
                    cal.set(Calendar.MONTH, monthOfYear)
                    cal.set(Calendar.DAY_OF_MONTH, dayOfMonth)
                    val myFormat = "yyyy-MM-dd" // mention the format you need
                    val sdf = SimpleDateFormat(myFormat, Locale.US)
                    txtreminddate.visibility = View.VISIBLE
                    txtreminddate.text = sdf.format(cal.time)
                

        var datepicker: DatePickerDialog? = null
        if (txtreminddate.text.isNotBlank())
        
            try
            
                val date: String = txtreminddate.text.trim().toString()
                val datearr = date.split("-").toTypedArray()
                val yearint = datearr[2].toInt()
                val monthint = datearr[1].toInt()
                val dateint = datearr[0].toInt()
                datepicker = DatePickerDialog(
                        context,
                        dateSetListener,
                        dateint,
                        monthint - 1,
                        yearint
                )
            
            catch (e: Exception)
            
                e.printStackTrace()
            
        
        else
        
            try
            
                val calendar = Calendar.getInstance()
                val dd = calendar[Calendar.DAY_OF_MONTH]
                val mm = calendar[Calendar.MONTH]
                val yy = calendar[Calendar.YEAR]
                datepicker = DatePickerDialog(context, dateSetListener, dd, mm, yy)
            
            catch (e: Exception)
            
                e.printStackTrace()
            
        
        datepicker!!.show()
    

    private fun showDatePicker(context: Context)
    
        val cal = Calendar.getInstance()
        val dateSetListener =
                DatePickerDialog.OnDateSetListener  _, year, monthOfYear, dayOfMonth ->
                    cal.set(Calendar.YEAR, year)
                    cal.set(Calendar.MONTH, monthOfYear)
                    cal.set(Calendar.DAY_OF_MONTH, dayOfMonth)
                    val myFormat = "yyyy-MM-dd" // mention the format you need
                    val sdf = SimpleDateFormat(myFormat, Locale.US)
                    dueDate.visibility = View.VISIBLE
                    dueDate.text = sdf.format(cal.time)
                

        var datepicker: DatePickerDialog? = null
        if (dueDate.text.isNotBlank())
        
            try
            
                val date: String = dueDate.text.toString()
                val datearr = date.split("-").toTypedArray()
                val dateint = datearr[0].toInt()
                val monthint = datearr[1].toInt()
                val yearint = datearr[2].toInt()
                datepicker = DatePickerDialog(
                        context,
                        dateSetListener,
                        yearint,
                        monthint - 1,
                        dateint
                )
            
            catch (e: java.lang.Exception)
            
                e.printStackTrace()
            
        
        else
        
            try
            
                val calendar = Calendar.getInstance()
                val yy = calendar[Calendar.YEAR]
                val mm = calendar[Calendar.MONTH]
                val dd = calendar[Calendar.DAY_OF_MONTH]
                datepicker = DatePickerDialog(context, dateSetListener, yy, mm, dd)
            
            catch (e: java.lang.Exception)
            
                e.printStackTrace()
            
        
        datepicker!!.show()
    

    override fun getChildrenCount(listPosition: Int): Int
    
        ChildCount = expandableListDetail[expandableListTitle[listPosition]]?.size.toString()
        Log.e("TAG",ChildCount)
        return expandableListDetail[expandableListTitle[listPosition]]?.size!!
    

    override fun getGroup(listPosition: Int): Any
    
        return expandableListTitle[listPosition]
    

    override fun getGroupCount(): Int
    
        return expandableListTitle.size
    

    override fun getGroupId(listPosition: Int): Long
    
        return listPosition.toLong()
    

    @SuppressLint("InflateParams")
    override fun getGroupView(listPosition: Int, isExpanded: Boolean, convertView: View?, parent: ViewGroup?): View
    
        var convertView: View? = convertView
        val listTitle = getGroup(listPosition) as String

        if (convertView == null)
        
            val layoutInflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
            convertView = layoutInflater.inflate(R.layout.list_group, null)
        
        val listTitleTextView = convertView?.findViewById(R.id.listTitle) as TextView
        val listCount = convertView.findViewById(R.id.listCount) as TextView
        val arrowicon = convertView.findViewById(R.id.arrowicon) as ImageView
        listTitleTextView.setTypeface(null, Typeface.BOLD)
        listTitleTextView.text = listTitle
        listCount.text = "($ChildCount)"

        if (getChildrenCount(listPosition) === 0)
        
            arrowicon.visibility = View.INVISIBLE
        
        else
        
            arrowicon.visibility = View.VISIBLE
            arrowicon.setImageResource(if (isExpanded) R.drawable.ic_arrow_up else R.drawable.ic_arrow_down)
        
        return convertView
    

    override fun hasStableIds(): Boolean
    
        return false
    

    override fun isChildSelectable(listPosition: Int, expandedListPosition: Int): Boolean
    
        return true
    

    init
    
        this.context = context
        this.expandableListTitle = expandableListTitle
        this.expandableListDetail = expandableListDetail
    

活动:-

  fun tasklistAPI(userId: String)
    
        if (isOnline())
        
            llNoInternet.gone()
            llLoading.visible()
            apiService.todotasklist(userId).enqueue(object :
                    Callback<ToDoListResponse>
            
                override fun onFailure(call: Call<ToDoListResponse>, t: Throwable)
                
                    llLoading.gone()
                

                override fun onResponse(call: Call<ToDoListResponse>, response: Response<ToDoListResponse>)
                
                    if (response.isSuccessful)
                    
                        if (response.body()!!.success == 1)
                        
                            try
                            

                                llLoading.gone()
                                expandableListDetail = HashMap()

                                val todaytask = response.body()!!.todays_task_list

                                expandableListTitle = ArrayList()
                                todaystitle = ArrayList()
                                todayslist = ArrayList()
                                Log.e("<>list", todaystitle.toString())

                                for (i in todaytask.indices)
                                
                                    todaystitle.add(todaytask[i])
                                

                                val tommrowtask = response.body()!!.tomorows_task_list
                                val tommorowtitle: MutableList<ToDoListResponse.TodaysTask> = ArrayList()

                                for (i in tommrowtask.indices)
                                
                                    tommorowtitle.add(tommrowtask[i])
                                

                                val upcomingtask = response.body()!!.upcomming_task_list
                                val upcomingtitle: MutableList<ToDoListResponse.TodaysTask> = ArrayList()

                                for (i in upcomingtask.indices)
                                
                                    upcomingtitle.add(upcomingtask[i])
                                

                                expandableListTitle.add("Today's Task")
                                expandableListTitle.add("Tommorow's Task")
                                expandableListTitle.add("Upcoming Task")
                                expandableListDetail.put(expandableListTitle[0], todaystitle)
                                expandableListDetail.put(expandableListTitle[1], tommrowtask)
                                expandableListDetail.put(expandableListTitle[2], upcomingtask)
                                Log.e("task", expandableListTitle.get(0) + " = " + expandableListDetail.put(expandableListTitle.get(0), todaystitle))
                                Log.e("task", expandableListTitle.get(1) + " = " + expandableListDetail.put(expandableListTitle.get(1), tommrowtask))
                                Log.e("task", expandableListTitle.get(2) + " = " + expandableListDetail.put(expandableListTitle.get(2), upcomingtask))
                                expandableListAdapter = CustomExpandableListAdapter(activity, expandableListTitle, expandableListDetail)
                                expandableListView!!.setAdapter(expandableListAdapter)
                            
                            catch (e: Exception)
                            
                                e.printStackTrace()
                            
                        
                    
                    else
                    
                        llLoading.gone()
                    
                
            )
        
        else
        
            llNoInternet.visible()
        
    

这是显示如何将添加数据添加到 hashmap 和可扩展列表视图的代码。 如您所见,有一个可扩展列表视图的哈希图,并且在adaoter中,我将标题从api respose放入,但是listview父级的标题是静态的,而子级中的数据是动态的,因此您可以看到差异

【问题讨论】:

你不能简单地在 recyclerview 中获取列表的大小吗? 它是一个可扩展的列表视图,所以我必须使用哈希映射设置数据,并且标题是静态的,子来自 api 响应 表示您正在从 api 响应中获取列表? 是正确的来自api响应的child中的数据 那么您能否简单地从 api 响应中获取列表的大小并将其设置为可扩展的列表视图标题文本 【参考方案1】:

您添加了很多代码,但我认为这是唯一对您的问题很重要的代码:-

expandableListTitle.add("Today's Task")
expandableListTitle.add("Tommorow's Task")
expandableListTitle.add("Upcoming Task")
expandableListDetail.put(expandableListTitle[0], todaystitle)
expandableListDetail.put(expandableListTitle[1], tommrowtask)
expandableListDetail.put(expandableListTitle[2], upcomingtask)
Log.e("task", expandableListTitle.get(0) + " = " + expandableListDetail.put(expandableListTitle.get(0), todaystitle))
Log.e("task", expandableListTitle.get(1) + " = " + expandableListDetail.put(expandableListTitle.get(1), tommrowtask))
Log.e("task", expandableListTitle.get(2) + " = " + expandableListDetail.put(expandableListTitle.get(2), upcomingtask))
expandableListAdapter = CustomExpandableListAdapter(activity, expandableListTitle, expandableListDetail)

expandableListView!!.setAdapter(expandableListAdapter)

据我从您在链接中添加的图片了解到,您需要在标题右侧显示子项中存在的元素数量。

您可以做的就是简单地添加列表中存在的元素总数,如下所示:-

expandableListTitle.add("Today's Task ($todaystitle.count())") //.count() gives the total number of elements present in list 

它将添加标题为Today's Task (10)\\ here 10 would be the number of elements present in your list。现在你可以简单地以任何你想要的方式格式化

【讨论】:

很高兴能帮助到兄弟,如果对你有帮助,请投票,方便其他人找到。

以上是关于如何在可扩展列表视图 Kotlin 中获取标题中的子项计数的主要内容,如果未能解决你的问题,请参考以下文章

如何在可展开的列表视图中设置不同的组指示器图像?

在可扩展的 QML 应用程序中访问列表视图索引

在可扩展列表视图android中折叠除选定组之外的所有组

如何在可扩展的表格视图单元中制作动态集合视图

使用键盘时如何在可编辑视图中获取光标的位置?

如何将可扩展列表视图的选定子视图数据从片段发送到父活动?