kotlin.Unit cannot be cast to java.util.List. for Custom Adapter on getFilter - android

I am using a custom adapter to display a list of contacts on AutoTextComplete but when I try to run it I get the error "kotlin.Unit cannot be cast to java.util.List" for
mContact = filterResults.values **as List<Contact>**
Contact is a Serializable object and is how i am retrieving contact names as objects in the List - code is below... I have tried looking for a solution elsewhere, but have not been able to resolve... if you can redirect or solution or guide will be amazing thanks
private var invoice: Invoice? = null
private lateinit var contact: Contact
private var invoiceItems: List<InvoiceItems>? = null
private lateinit var contactSelect: ArrayList<Contact>
private lateinit var dueDate: Calendar
private val calendar = Calendar.getInstance()
private var total = 0
private var subTotal = 0
private var taxrate = 0
private var invoiceType: String = ""
private var invoiceUpdt: InvoiceItems? = null
private var j: String? = null
private var clientLkey: String? = ""
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_edit_invoice)
val toolbar: Toolbar = findViewById(R.id.toolbar_editinv)
setSupportActionBar(toolbar)
supportActionBar?.setDisplayShowHomeEnabled(true)
val invoiceClient = findViewById<AutoCompleteTextView>(R.id.invoiceClient)
val invoiceDueDt = findViewById<TextView>(R.id.invoiceDueDt)
dueDate = Calendar.getInstance()
//getting values from intent
invoice = intent.getSerializableExtra("invoice") as? Invoice
invoiceItems = intent.getSerializableExtra("invoiceItem") as? List<InvoiceItems>
invoiceUpdt = intent.getSerializableExtra("invoiceItemUpdt") as? InvoiceItems
j = intent.getStringExtra("i")
if (invoice == null){
invoiceType = "new"
supportActionBar?.title = "Add Invoice"
addinvoiceItem()
} else {
editInvoice()
}
//Setup Due date for the invoice
invoiceDueDt.setOnClickListener {
showCalendar()
}
//Auto complete based on database for selecting the client
val clientContact: List<Contact> = ArrayList<Contact>()
val adapter = ClientSelectAdapter(this, R.layout.userlatomcontacts, clientContact)
invoiceClient.setAdapter(adapter)
invoiceClient.threshold = 2
invoiceClient.setOnItemClickListener { parent, _, position, id ->
val selectedClient = parent.adapter.getItem(position) as Contact?
invoiceClient.setText(selectedClient?.name)
clientLkey = selectedClient?.lookupKey
}
}
inner class ClientSelectAdapter(
context: Context,
#LayoutRes private val layoutResource: Int,
private var allContacts: List<Contact>
):
ArrayAdapter<Contact>(context, layoutResource, allContacts),
Filterable {private var mContact: List<Contact> = allContacts
override fun getCount(): Int {
return mContact.size
}
override fun getItem(p0: Int): Contact {
return mContact[p0]
}
override fun getItemId(p0: Int): Long {
// Or just return p0
return mContact[p0].id.toLong()
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
var view = convertView
if (view == null) {
view = LayoutInflater.from(parent.context)
.inflate(layoutResource, parent, false)
}
val invoiceClient = view!!.findViewById<View>(R.id.invoiceClient) as TextView
invoiceClient.text = mContact[position].name
val clientProfile = view.findViewById<View>(R.id.profile_image) as ShapeableImageView
Picasso.get().load(mContact[position].photoUri)
.placeholder(R.drawable.ic_baseline_whatshot_24).fit().centerCrop()
.into(clientProfile)
return view
}
override fun getFilter(): Filter {
return object : Filter() {
override fun publishResults(
charSequence: CharSequence?,
filterResults: FilterResults
) {
**mContact = filterResults.values as List<Contact>**
notifyDataSetChanged()
}
override fun performFiltering(charSequence: CharSequence?): FilterResults {
val queryString = charSequence?.toString()?.toLowerCase(Locale.ROOT)
val results = FilterResults()
results.values = if (queryString == null || queryString.isEmpty())
allContacts
else {
val db = AppDatabase.getDatabase(context)
allContacts = db.contactsDao().getBySearch(queryString)
}
return results
}
}
}
}

According to kotlin documentations Branches of if branches can be blocks. In this case, the last expression is the value of a block
So, in your case, when code enters the else block, the last expression is assignment, and assignments return Unit in kotlin. You may check this situation with this simple example:
var temp = 0
var result: Int = if (temp > 0) {
5
} else {
temp = 5
}
You would see the ide error at temp = 5 since it returns Unit whereas result expects Int.
To sum up, you just need to change your else block as follows:
else {
val db = AppDatabase.getDatabase(context)
allContacts = db.contactsDao().getBySearch(queryString)
allContacts
}

Related

How to get Folder size and number of Files avaliable from Folder path in Kotlin

i am trying to create a video player app using kotlin , First of all I got the videos files by using MediaStore , than store this in ArrayList so far it's been perfect but When I made a folder list of videos, I tried to find out the size of those folders and how many video files there are in those folders, but I failed. like this (Image)
Check this image for more clear
This is my data class code (VideoItem.Kt)
import android.net.Uri
data class VideoItem(
val id: String,
val title: String,
val duration: Long = 0,
val folderName: String,
val size: String,
val path: String,
val dateAdded: String,
val artUri: Uri
)
data class FolderItem(
val id: String,
val folderName: String,
val folderSize: Long
)
This is my MainActivity Code To get Allvideos Using MediaStore
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
companion object {
lateinit var videoList: ArrayList<VideoItem>
lateinit var folderList: ArrayList<FolderItem>
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
folderList = ArrayList()
videoList = getAllVideos()
setFragment(VideoviewFragment())
}
private fun setFragment(fragment: Fragment) {
val transaction = supportFragmentManager.beginTransaction()
transaction.replace(R.id.FrameLayout, fragment)
transaction.disallowAddToBackStack()
transaction.commit()
}
#SuppressLint("Recycle", "Range")
private fun getAllVideos(): ArrayList<VideoItem> {
val tempList = ArrayList<VideoItem>()
val tempFolderList = ArrayList<String>()
val projection = arrayOf(
MediaStore.Video.Media.TITLE,
MediaStore.Video.Media.SIZE,
MediaStore.Video.Media._ID,
MediaStore.Video.Media.BUCKET_DISPLAY_NAME,
MediaStore.Video.Media.DATA,
MediaStore.Video.Media.DATE_ADDED,
MediaStore.Video.Media.DURATION,
MediaStore.Video.Media.BUCKET_ID
)
val cursor = this.contentResolver.query(
MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
projection,
null,
null,
MediaStore.Video.Media.DATE_ADDED + " DESC"
)
if (cursor != null)
if (cursor.moveToNext())
do {
val titleC =
cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.TITLE))
val idC = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media._ID))
val folderNameC =
cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.BUCKET_DISPLAY_NAME))
val folderIdC =
cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.BUCKET_ID))
val sizeC = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.SIZE))
val pathC = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.DATA))
val dateAddedC =
cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.DATE_ADDED))
val durationC =
cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.DURATION))
.toLong()
try {
val file = File(pathC)
val artUriC = Uri.fromFile(file)
val video = VideoItem(
title = titleC,
id = idC,
folderName = folderNameC,
size = sizeC,
path = pathC,
duration = durationC,
dateAdded = dateAddedC,
artUri = artUriC
)
if (file.exists()) tempList.add(video)
//for adding Folders
if (!tempFolderList.contains(folderNameC)) {
tempFolderList.add(folderNameC)
val folderSizeC = getFileLength(pathC)
folderList.add(
FolderItem(
id = folderIdC,
folderName = folderNameC,
folderSize = folderSizeC
)
)
}
} catch (_: Exception) {
}
} while (cursor.moveToNext())
cursor?.close()
return tempList
}
private fun getFileLength(path: String?): Long {
return if (!isExistFile(path)) 0 else File(path.toString()).length()
}
private fun isExistFile(path: String?): Boolean {
val file = File(path.toString())
return file.exists()
}
}
This is my RecyclerviwAdapter Code(FolderAdapter.kt)
class FoldersAdapter(private val context: Context, private var foldersList: ArrayList<FolderItem>) :
RecyclerView.Adapter<FoldersAdapter.MyHolder>() {
class MyHolder(binding: FolderItemBinding) : RecyclerView.ViewHolder(binding.root) {
val folderName = binding.folderName
val noofFiles = binding.nooffiles
val folderSize = binding.foldersize
val root = binding.root
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyHolder {
return MyHolder(FolderItemBinding.inflate(LayoutInflater.from(context), parent, false))
}
override fun onBindViewHolder(holder: MyHolder, position: Int) {
holder.folderName.text = foldersList[position].folderName
val size: Long = foldersList[position].folderSize
holder.folderSize.text = android.text.format.Formatter.formatFileSize(context, (size))
holder.root.setOnClickListener {
val intent = Intent(context, FolderVideosActivity::class.java)
intent.putExtra("position", position)
ContextCompat.startActivity(context, intent, null)
}
}
override fun getItemCount(): Int {
return foldersList.size
}
}
This is my all codes now please check out all code and suggest the best.
Thank you
Use this function for size
private fun getFolderSize(f: File): Long {
var size: Long = 0
if (f.isDirectory) {
for (file in f.listFiles()!!) {
size += getFolderSize(file)
}
} else {
size = f.length()
}
return size
}
And Count number of files Use this
val length = File("/path/to/folder").listFiles()?.size

Troubles with nested array and JSON

Hello) I'm new in Android dev. And I have a problem with my program.
It's my model:
data class Test (val id: Int,
val numberQuestion: String,
val question: String,
val questionImageSrc: String,
val examination: Boolean,
val typeQuestion: String,
val singleChoiceAnswers: ArrayList<singleChoiceAnswer>,
val multipleChoiceAnswers: ArrayList<multipleChoiceAnswers>,
val inputAnswer: ArrayList<inputAnswer>)
data class multipleChoiceAnswers(val letter: String,
val text: String,
val correctAnswer: Boolean,
val checked: Boolean)
data class singleChoiceAnswer(val letter: String,
val text: String,
val correctAnswer: Boolean,
val checked: Boolean)
data class inputAnswer(val correctAnswer: String,
val userAnswer: String)
It's how i get the data from JSON:
private fun jsonResult(jsonString: String?) {
val jsonArray = JSONArray(jsonString)
val list = ArrayList<Test>()
val slist = ArrayList<singleChoiceAnswer>()
val mlist = ArrayList<multipleChoiceAnswers>()
val ilist = ArrayList<inputAnswer>()
for (i in 0 until jsonArray.length()){
val jsonObject = jsonArray.getJSONObject(i)
val typeQuestion = jsonObject.getString("typeQuestion")
val curentId = jsonObject.optInt("id")
val curentNQ = jsonObject.optString("numberQuestion")
val curentQ = jsonObject.optString("question")
val curentQIS = jsonObject.optString("questionImageSrc")
val curentEx = jsonObject.optBoolean("examination")
if (typeQuestion.contains("multipleChoice")){
val multipleChoiceAnswers = jsonObject.getJSONArray("multipleChoiceAnswers")
for (sc in 0 until multipleChoiceAnswers.length()){
val curentMCA = multipleChoiceAnswers.getJSONObject(sc)
val letter = curentMCA.optString("letter")
val text = curentMCA.optString("text")
val correctAnswer = curentMCA.optBoolean("correctAnswer")
val checked = curentMCA.optBoolean("checked")
mlist.add(multipleChoiceAnswers(letter, text, correctAnswer, checked))
}
}
if (typeQuestion.contains("singleChoice")){
val singleChoiceAnswer = jsonObject.getJSONArray("singleChoiceAnswers")
for (sc in 0 until singleChoiceAnswer.length()){
val curentSCA = singleChoiceAnswer.getJSONObject(sc)
val letter = curentSCA.optString("letter")
val text = curentSCA.optString("text")
val correctAnswer = curentSCA.optBoolean("correctAnswer")
val checked = curentSCA.optBoolean("checked")
slist.add(singleChoiceAnswer(letter, text, correctAnswer, checked))
}
}
if (typeQuestion.contains("input")){
val inputAnswer = jsonObject.getJSONArray("inputAnswer")
for (sc in 0 until inputAnswer.length()){
val curentIA = inputAnswer.getJSONObject(sc)
val correctAnswer = curentIA.optString("correctAnswer")
val userAnswer = curentIA.optString("userAnswer")
ilist.add(inputAnswer(correctAnswer,userAnswer))
}
}
list.add(Test(curentId, curentNQ, curentQ, curentQIS, curentEx, typeQuestion, slist, mlist, ilist))
}
val adapter = TestAdapter(list) { item ->
testAdapterItemClick(item)
}
val recView = findViewById<RecyclerView>(R.id.testRecyclerView)
recView.adapter = adapter
}
Here is link to my JSON. If you need it)
Then i am doing something like that:
private fun testAdapterItemClick(item: Test) {
val fT: FragmentTransaction = supportFragmentManager.beginTransaction()
val frag1: Fragment1 = Fragment1()
val frag2: Fragment2 = Fragment2()
if (item.typeQuestion == "input") {
val bundle = Bundle()
bundle.putString("NUMBER_KEY", item.numberQuestion)
bundle.putString("QUESTION_KEY", item.question)
if(!item.questionImageSrc.isNullOrEmpty())
bundle.putString("IMAGE_KEY", item.questionImageSrc)
frag1.setArguments(bundle)
fT.add(R.id.frameLayout, frag1)
}
if (item.typeQuestion == "singleChoice") {
val bundle = Bundle()
bundle.putString("NUMBER_KEY", item.numberQuestion)
bundle.putString("QUESTION_KEY", item.question)
val count = item.singleChoiceAnswers.size
Toast.makeText(this, count.toString(), Toast.LENGTH_LONG).show()
// bundle.putInt("COUNT_KEY", count)
for (i in 0 until count)
{
val curentSCA = item.singleChoiceAnswers[i]
bundle.putString("letterSCA$i", curentSCA.letter)
bundle.putString("textSCA$i", curentSCA.text)
}
frag2.setArguments(bundle)
fT.add(R.id.frameLayout, frag2)
I need to get ArrayList of the definite item and put it data in fragment using bundle.
But I have a problem in fragment:
public override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?): View? {
val rootView = inflater.inflate(R.layout.fragment2, container, false)
val questionNumber = rootView.findViewById(R.id.questionNumber) as TextView
val questionText = rootView.findViewById(R.id.Question) as TextView
val questionImage = rootView.findViewById(R.id.questionImage) as ImageView
val qN : String = getArguments()?.getString("NUMBER_KEY").toString()
val quest: String = getArguments()?.getString("QUESTION_KEY").toString()
val qI: String = getArguments()?.getString("IMAGE_KEY").toString()
questionNumber.text=qN
questionText.text=quest
Picasso.get().load(qI).into(questionImage)
val radioGroup = rootView.findViewById(R.id.radioGroupSetectTest) as RadioGroup
val count : Int = getArguments()!!.getInt("COUNT_KEY")
val context = getContext()
for (i in 0 until count)
{
val curentRB = RadioButton(context)
val curLetter = getArguments()?.getString("letterSCA$i")
val curText = getArguments()?.getString("textSCA$i")
curentRB.setText(curLetter+" "+curText)
radioGroup.addView(curentRB)
}
It put the all values of singleChoiseAnswer from all items like this screen. Please, help me) I know that it is a simple problem but i realy dont understand)
Thanks in advance)
P.S. SOrry for my English)
First of all, you need to convert your Json into Kotlin classes, you can use GSON
to convert your json to kotlin data classes like this
import android.os.Parcel
import android.os.Parcelable
import com.google.gson.annotations.SerializedName
data class QuestionResponse(
#field:SerializedName("multipleChoiceAnswers")
val multipleChoiceAnswers: List<MultipleChoiceAnswersItem?>? = null,
#field:SerializedName("inputAnswer")
val inputAnswer: List<InputAnswer?>? = null,
#field:SerializedName("numberQuestion")
val numberQuestion: String? = null,
#field:SerializedName("question")
val question: String? = null,
#field:SerializedName("typeQuestion")
val typeQuestion: String? = null,
#field:SerializedName("examination")
val examination: Boolean? = null,
#field:SerializedName("id")
val id: Int? = null,
#field:SerializedName("singleChoiceAnswers")
val singleChoiceAnswers: List<MultipleChoiceAnswersItem?>? = null,
#field:SerializedName("questionImageSrc")
val questionImageSrc: String? = null
) : Parcelable {
constructor(parcel: Parcel) : this(
parcel.createTypedArrayList(MultipleChoiceAnswersItem),
parcel.createTypedArrayList(InputAnswer),
parcel.readString(),
parcel.readString(),
parcel.readString(),
parcel.readValue(Boolean::class.java.classLoader) as? Boolean,
parcel.readValue(Int::class.java.classLoader) as? Int,
parcel.createTypedArrayList(MultipleChoiceAnswersItem),
parcel.readString()
) {
}
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeTypedList(multipleChoiceAnswers)
parcel.writeTypedList(inputAnswer)
parcel.writeString(numberQuestion)
parcel.writeString(question)
parcel.writeString(typeQuestion)
parcel.writeValue(examination)
parcel.writeValue(id)
parcel.writeTypedList(singleChoiceAnswers)
parcel.writeString(questionImageSrc)
}
override fun describeContents(): Int {
return 0
}
companion object CREATOR : Parcelable.Creator<QuestionResponse> {
override fun createFromParcel(parcel: Parcel): QuestionResponse {
return QuestionResponse(parcel)
}
override fun newArray(size: Int): Array<QuestionResponse?> {
return arrayOfNulls(size)
}
}
}
import android.os.Parcel
import android.os.Parcelable
import com.google.gson.annotations.SerializedName
data class MultipleChoiceAnswersItem(
#field:SerializedName("letter")
val letter: String? = null,
#field:SerializedName("checked")
val checked: Boolean? = null,
#field:SerializedName("text")
val text: String? = null,
#field:SerializedName("correctAnswer")
val correctAnswer: Boolean? = null
) : Parcelable {
constructor(parcel: Parcel) : this(
parcel.readString(),
parcel.readValue(Boolean::class.java.classLoader) as? Boolean,
parcel.readString(),
parcel.readValue(Boolean::class.java.classLoader) as? Boolean
) {
}
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeString(letter)
parcel.writeValue(checked)
parcel.writeString(text)
parcel.writeValue(correctAnswer)
}
override fun describeContents(): Int {
return 0
}
companion object CREATOR : Parcelable.Creator<MultipleChoiceAnswersItem> {
override fun createFromParcel(parcel: Parcel): MultipleChoiceAnswersItem {
return MultipleChoiceAnswersItem(parcel)
}
override fun newArray(size: Int): Array<MultipleChoiceAnswersItem?> {
return arrayOfNulls(size)
}
}
}
import android.os.Parcel
import android.os.Parcelable
import com.google.gson.annotations.SerializedName
data class InputAnswer(
#field:SerializedName("correctAnswer")
val correctAnswer: String? = null,
#field:SerializedName("userAnswer")
val userAnswer: String? = null) : Parcelable {
constructor(parcel: Parcel) : this(
parcel.readString(),
parcel.readString()
) {
}
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeString(correctAnswer)
parcel.writeString(userAnswer)
}
override fun describeContents(): Int {
return 0
}
companion object CREATOR : Parcelable.Creator<InputAnswer> {
override fun createFromParcel(parcel: Parcel): InputAnswer {
return InputAnswer(parcel)
}
override fun newArray(size: Int): Array<InputAnswer?> {
return arrayOfNulls(size)
}
}
}
To know about Parcelable go to this link
Then when this is complete, parse the JSON like this
private fun jsonResult(jsonString: String?) {
val jsonArray = JSONArray(jsonString)
val list = ArrayList<QuestionResponse>()
val slist = ArrayList<MultipleChoiceAnswersItem>()
val mlist = ArrayList<MultipleChoiceAnswersItem>()
val ilist = ArrayList<InputAnswer>()
for (i in 0 until jsonArray.length()){
val jsonObject = jsonArray.getJSONObject(i)
val typeQuestion = jsonObject.getString("typeQuestion")
val curentId = jsonObject.optInt("id")
val curentNQ = jsonObject.optString("numberQuestion")
val curentQ = jsonObject.optString("question")
val curentQIS = jsonObject.optString("questionImageSrc")
val curentEx = jsonObject.optBoolean("examination")
if (typeQuestion.contains("multipleChoice")){
val multipleChoiceAnswers = jsonObject.getJSONArray("multipleChoiceAnswers")
for (sc in 0 until multipleChoiceAnswers.length()){
val curentMCA = multipleChoiceAnswers.getJSONObject(sc)
val letter = curentMCA.optString("letter")
val text = curentMCA.optString("text")
val correctAnswer = curentMCA.optBoolean("correctAnswer")
val checked = curentMCA.optBoolean("checked")
mlist.add(MultipleChoiceAnswersItem(letter,checked, text, correctAnswer))
}
}
if (typeQuestion.contains("singleChoice")){
val singleChoiceAnswer = jsonObject.getJSONArray("singleChoiceAnswers")
for (sc in 0 until singleChoiceAnswer.length()){
val curentSCA = singleChoiceAnswer.getJSONObject(sc)
val letter = curentSCA.optString("letter")
val text = curentSCA.optString("text")
val correctAnswer = curentSCA.optBoolean("correctAnswer")
val checked = curentSCA.optBoolean("checked")
slist.add(MultipleChoiceAnswersItem(letter, checked,text, correctAnswer))
}
}
if (typeQuestion.contains("input")){
val inputAnswer = jsonObject.getJSONArray("inputAnswer")
for (sc in 0 until inputAnswer.length()){
val curentIA = inputAnswer.getJSONObject(sc)
val correctAnswer = curentIA.optString("correctAnswer")
val userAnswer = curentIA.optString("userAnswer")
ilist.add(InputAnswer(correctAnswer,userAnswer))
}
}
val questionResponse = QuestionResponse(mlist,ilist,curentNQ,curentQ,typeQuestion,curentEx,curentId,slist,curentQIS)
//pass this questionResponse to your adapter
}
}
Then in Adapter Item click
private fun testAdapterItemClick(item: Test) {
val fT: FragmentTransaction = supportFragmentManager.beginTransaction()
val frag1: Fragment1 = Fragment1()
val frag2: Fragment2 = Fragment2()
if (item.typeQuestion == "input") {
val bundle = Bundle()
bundle.putParcelable("input", item)
frag1.setArguments(bundle)
fT.add(R.id.frameLayout, frag1)
}
// do the same for the rest
}
Then in the Fragment
public override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?): View? {
val rootView = inflater.inflate(R.layout.fragment2, container, false)
val questionNumber = rootView.findViewById(R.id.questionNumber) as TextView
val questionText = rootView.findViewById(R.id.Question) as TextView
val questionImage = rootView.findViewById(R.id.questionImage) as ImageView
val item = arguments.getParcelable("input")
// val arraylist = arguments.getParcelableArrayList<YOUR_CLASS_TYPE>("key") //for arrays you can do it like this
//then set it in the radiobutton like this item.getCurrentText and so on
}

ExpandedListView: how to expandGroup or get correct groupPosition with List<Class>

Before this problem i could expand groups.
Group and child collection was:
val header: MutableList<String> = ArrayList()
var productList : MutableList<String> = mutableListOf()
val body: MutableList<MutableList<String>> = mutableListOf()
After that I needed to add more data to my header and childs (productList). So i created two model classes:
data class Cell (var barcode: String = "", var name: String = "")
data class Product(
var barcode: String = "",
var id: String = "",
var name: String = "",
var time: String = "",
var date: String = "",
var weight: Int = 0
)
And changed my collections in Activity to:
var header: MutableList<Cell> = mutableListOf()
var productList : MutableList<Product> = mutableListOf()
val body: MutableList<MutableList<Product>> = mutableListOf()
My adapter is:
class ExpandableListAdapter(var context : Context, var expandableListView: ExpandableListView, var header : MutableList<Cell>, var body: MutableList<MutableList<Product>>) :
BaseExpandableListAdapter() {
override fun getGroup(groupPosition: Int): String {
return header[groupPosition].toString()
}
override fun isChildSelectable(groupPosition: Int, childPosition: Int): Boolean {
return true
}
override fun hasStableIds(): Boolean {
return false
}
override fun getGroupView(
groupPosition: Int,
isExpanded: Boolean,
convertView: View?,
parent: ViewGroup?
): View? {
var convertView = convertView
if(convertView == null){
val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
convertView = inflater.inflate(R.layout.layout_group, null)
}
val title = convertView?.findViewById<TextView>(R.id.textGroupCode)
title?.text = getGroup(groupPosition)
val det = header.get(groupPosition)
title?.setText(det.name.toString())
title?.setOnClickListener {
if (expandableListView.isGroupExpanded(groupPosition))
expandableListView.collapseGroup(groupPosition)
else
expandableListView.expandGroup(groupPosition)
Toast.makeText(context, getGroup(groupPosition).toString(), Toast.LENGTH_SHORT).show()
}
return convertView
}
override fun getChildrenCount(groupPosition: Int): Int {
return body[groupPosition].size
//return header.get(groupPosition).getChildList().size()
}
override fun getChild(groupPosition: Int, childPosition: Int): String {
return body[groupPosition][childPosition].toString()
//return header.get(groupPosition).get(childPosition)
}
override fun getGroupId(groupPosition: Int): Long {
return groupPosition.toLong()
}
override fun getChildView(
groupPosition: Int,
childPosition: Int,
isLastChild: Boolean,
convertView: View?,
parent: ViewGroup?
): View? {
var convertView = convertView
if(convertView == null){
val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
convertView = inflater.inflate(R.layout.layout_child, null)
}
val title = convertView?.findViewById<TextView>(R.id.textChildId)
title?.text = getChild(groupPosition, childPosition)
val name = convertView?.findViewById<TextView>(R.id.textChildName)
val date = convertView?.findViewById<TextView>(R.id.textChildDate)
val time = convertView?.findViewById<TextView>(R.id.textChildTime)
val weight = convertView?.findViewById<TextView>(R.id.textChildWeight)
val det = body.get(groupPosition).get(childPosition)
title?.setText(det.id.toString())
name?.setText(det.name.toString())
date?.setText(det.date.toString())
time?.setText(det.time.toString())
weight?.setText(det.weight.toString())
title?.setOnClickListener {
Toast.makeText(context, getChild(groupPosition, childPosition), Toast.LENGTH_SHORT).show()
}
return convertView
}
override fun getChildId(groupPosition: Int, childPosition: Int): Long {
return childPosition.toLong()
}
override fun getGroupCount(): Int {
return header.size
}
}
Now when i try to expand/click on my group or child, i get class with his all field values. I dont get position of element. How to fix this? How to work with List of class and get correct position???
Please try this one, i have print group position, child position and handle expend event.
class ExpendNewListAdapter(
var mContext: Context,
var mListDataHeader: List<String>?,
var mListDataChild: HashMap<String, List<EventsItem>?>?) : BaseExpandableListAdapter() {
override fun getChild(groupPosition: Int, childPosititon: Int): Any {
return this.mListDataChild?.get(this.mListDataHeader?.get(groupPosition))!!.get(childPosititon)
}
override fun getChildId(groupPosition: Int, childPosition: Int): Long {
return childPosition.toLong()
}
override fun getChildView(groupPosition: Int, childPosition: Int,
isLastChild: Boolean, convertView: View?, parent: ViewGroup): View {
val events = getChild(groupPosition, childPosition) as EventsItem
val infalInflater = this.mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
val childView = infalInflater.inflate(R.layout.list_item_expandable, null)
val txtListEventName = childView
.findViewById<View>(R.id.text_event_name) as TextView
Log.e("child Position",childPosition.toString())
return childView
}
override fun getChildrenCount(groupPosition: Int): Int {
return this.mListDataChild?.get(this.mListDataHeader?.get(groupPosition))?.size ?:0
}
override fun getGroup(groupPosition: Int): String? {
return this.mListDataHeader?.get(groupPosition)
}
override fun getGroupCount(): Int {
return this.mListDataHeader?.size?:0
}
override fun getGroupId(groupPosition: Int): Long {
return groupPosition.toLong()
}
override fun getGroupView(groupPosition: Int, isExpanded: Boolean,
convertView: View?, parent: ViewGroup): View {
val infalInflater = this.mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
val headerView = infalInflater.inflate(R.layout.expend_list_layout, null)
val innerLayout = headerView
.findViewById<View>(R.id.layout_inner) as ConstraintLayout
val viewBottom = headerView
.findViewById<View>(R.id.view_botttom_parent) as View
Log.e("group Position",groupPosition.toString())
if(isExpanded ) {
innerLayout.setBackgroundColor(ContextCompat.getColor(mContext, R.color.button_green))
viewBottom.visibility = View.GONE
}
else
{
innerLayout.setBackgroundColor(ContextCompat.getColor(mContext,R.color.button_blue))
viewBottom.visibility=View.VISIBLE
}
return headerView
}
override fun hasStableIds(): Boolean {
return false
}
override fun isChildSelectable(groupPosition: Int, childPosition: Int): Boolean {
return true
}
}
In my case i have set all events month wise, where group items are month and child items are all events which are getting from my response.you can change as per your requirement.
if (dataList != null && dataList.size > 0) {
text_empty.visibility = View.GONE
mListDataHeader = ArrayList()
mListDataChild = HashMap()
// Adding the header of parent.because month are common for each year then put static data
mListDataHeader?.add(getString(R.string.january))
mListDataHeader?.add(getString(R.string.feburary))
mListDataHeader?.add(getString(R.string.march))
mListDataHeader?.add(getString(R.string.april))
mListDataHeader?.add(getString(R.string.may))
mListDataHeader?.add(getString(R.string.june))
mListDataHeader?.add(getString(R.string.july))
mListDataHeader?.add(getString(R.string.august))
mListDataHeader?.add(getString(R.string.sep))
mListDataHeader?.add(getString(R.string.oct))
mListDataHeader?.add(getString(R.string.nov))
mListDataHeader?.add(getString(R.string.dec))
mIsRequestForAccess?.let {
if (!it) {
mListDataHeader?.add("") /* these blank item to create space in bottom for
scrolling the list up to request for access view*/
mListDataHeader?.add("")
}
}
/* In this List First we are check the list of event item is empty or not
* if it is empty then we add a blank item for "No Event Found".if the list is not blank then
* we check start and end date are common or not if it is comman then we create a new list and add a event in this list
* and if the date are not common then we get all dates between start and end date..and create a different events
* of those dates..(events name and title are common between start and end date so we change only start date of
* all event which are belong from those dates)..we show the child events for base on start dates.so we change only start date*/
for (item in dataList.indices) {
mListDataChild?.let {
if (dataList[item]?.events?.size == 0) {
var list: List<EventsItem>? = null
list = ArrayList()
val events = EventsItem(null, null, null, getString(R.string.not_events_found), null)
list.add(events)
it.put(mListDataHeader!!.get(item), list)
} else {
var newList: List<EventsItem>? = null
newList = ArrayList()
val events = dataList[item]?.events as List<EventsItem>?
val monthDate=dataList[item]?.date
events?.let {
for (i in it.indices) {
val event = it[i]
val startTime = event.startDate
val endTime = event.endDate
val startDate=Utils.getFormatedTimeFromUtc(startTime,getString(R.string.date_format_data))
val endDate=Utils.getFormatedTimeFromUtc(endTime,getString(R.string.date_format_data))
val colors = event.color
val description = event.description
val title = event.title
if (startDate.equals(endDate)) {
newList.add(event)
} else {
/* get all dates between start and end date*/
var startnewDate: String? = null
val mLists = Utils.getDates(startDate, endDate, activity)
val newFormate = SimpleDateFormat(getString(R.string.date_format_data), Locale.getDefault())
val format = SimpleDateFormat(getString(R.string.date_month_formats), Locale.getDefault())
var mDateStart: Date? = null
try {
mDateStart = newFormate.parse(startDate)
startnewDate = format.format(mDateStart)
} catch (e: ParseException) {
e.printStackTrace()
}
mLists.let {
for (data in it.indices) {
val dateFormat = SimpleDateFormat(getString(R.string.date_format_data), Locale.getDefault())
val datenew = format.format(it[data])
if (datenew == monthDate) {
val newData = dateFormat.format(it[data])
val newEvent = EventsItem(endDate, colors, description, title, newData)
newList.add(newEvent)
}
}
}
}
}
}
val sortedList = newList.sortedWith(compareBy({ it.startDate }))
it[mListDataHeader!!.get(item)] = sortedList as List<EventsItem>?
}
}
setData()
}
} else {
text_empty.visibility = View.VISIBLE
}

Data is added in Sqlite but won't showing in recyclerView

I have added text and Image in sqlite it is added , I checked in log screen and also in sqlite browser but when I retrive it to the recyclerVIew only text is displaying , Image is not showing
Here is insert function
fun inserData(user: User) {
db = writableDatabase
var values = ContentValues()
if (user.Category.equals("CLOTHES")) {
values.put("DESCRIPTION", "${user.Description}")
values.put("IMAGE", "${user.Image}")
if (values !== null) {
db.insertOrThrow(Cloth,null,values)
Toast.makeText(ctx,"Inserted in ${Cloth}",Toast.LENGTH_SHORT).show()
Log.d("data","${values}")
}
Get function
fun ClothData(): ArrayList<User> {
val clothData = ArrayList<User>()
db = readableDatabase
cursor = db.rawQuery("SELECT*FROM $Cloth",null)
if (cursor !== null && cursor.moveToFirst()) {
do {
var user = User()
user.Description = cursor.getString(cursor.getColumnIndex("DESCRIPTION"))
user.Image = cursor.getBlob(cursor.getColumnIndex("IMAGE"))
clothData.add(user)
}while (cursor.moveToNext())
}
return clothData
}
RecyclerView Adapter
class ClothesItemAdapter(var ctx:Context,var arrayList : ArrayList<User>) : RecyclerView.Adapter<ClothesItemAdapter.CustomeViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): CustomeViewHolder {
val inflate = LayoutInflater.from(ctx).inflate(R.layout.row_clothesitem,null)
return CustomeViewHolder(inflate)
}
override fun getItemCount(): Int {
return arrayList.size
}
override fun onBindViewHolder(holder: CustomeViewHolder?, position: Int) {
val position = arrayList[position]
holder!!.clothText.text = position.Description
val bitmap = BitmapFactory.decodeByteArray(position.Image,0,position.Image!!.size)
holder.clothImage.setImageBitmap(bitmap)
}
inner class CustomeViewHolder(view:View) : RecyclerView.ViewHolder(view)
{
var clothImage = view.findViewById<ImageView>(R.id.clothImage)
var clothText = view.findViewById<TextView>(R.id.clothText)
}
}
I included the SS of sqlite browser below which shows the image is added in database

Read contacts and display it in a recyclerview in Kotlin

I am trying to read contacts from ContactsContract in Kotin. But it's not showing any of the contact in the recyclerview. The noticeable thing is that the java version of this code is working fine.
So, I here is my Kotlin code for reading the contact:
private var adapter: ContactsAdapter? = null
private var myContacts : MutableList<MyContacts> = ArrayList()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// code for recyclerview and adapter and checkPermission
val itemDecoration = DividerItemDecoration(this, DividerItemDecoration.VERTICAL)
recycler_view.layoutManager = LinearLayoutManager(this)
recycler_view.addItemDecoration(itemDecoration)
adapter = ContactsAdapter(myContacts)
recycler_view.hasFixedSize()
recycler_view.adapter = ContactsAdapter(myContacts)
checkPermission()
}
private fun loadContactFromProvider() {
showProgressBar()
val contentResolver = contentResolver
val cursor = contentResolver.query(CONTENT_URI, null, null, null, DISPLAY_NAME)
if (cursor != null && cursor.count > 0) {
while (cursor.moveToNext()) {
val id = cursor.getString(cursor.getColumnIndex(ID))
val name = cursor.getString(cursor.getColumnIndex(DISPLAY_NAME))
val hasPhoneNumber = cursor.getInt(cursor.getColumnIndex(HAS_PHONE_NUMBER))
val contacts = MyContacts()
if (hasPhoneNumber > 0) {
contacts.contactName = name
val phoneCursor = contentResolver.query(PHONE_URI, arrayOf(NUMBER), "$PHONE_ID = ?", arrayOf(id), null)
val phoneNumbers = ArrayList<String>()
phoneCursor!!.moveToFirst()
while (!phoneCursor.isAfterLast) {
val phoneNumber = phoneCursor.getString(phoneCursor.getColumnIndex(NUMBER)).replace(" ", "")
phoneNumbers.add(phoneNumber)
phoneCursor.moveToNext()
}
contacts.contactNumber = phoneNumbers
phoneCursor.close()
}
val inputStream = ContactsContract.Contacts.openContactPhotoInputStream(contentResolver, ContentUris.withAppendedId(CONTENT_URI, id.toLong()))
if (inputStream != null) {
val bitmap = BitmapFactory.decodeStream(inputStream)
contacts.contactImage = bitmap?.toString()
} else {
contacts.contactImage = vectorDrawableToBitmap(R.drawable.ic_person)?.toString()
}
log(contacts.contactName + " " + contacts.contactNumber.toString() + " " + contacts.contactImage.toString())
myContacts.add(contacts)
}
adapter?.notifyDataSetChanged()
cursor.close()
}
}
The log details are also fine, they are showing the full contact list. But I am unable to see it in the recyclerview. The constant field like ID, DISPLAY_NAME etc. are already defined in the companion object.
Kotlin code for RecyclerViewAdapter is:
class ContactsAdapter(private val contactList: MutableList<MyContacts>): RecyclerView.Adapter<ContactsAdapter.ContactViewHolder>() {
override fun onCreateViewHolder(viewGroup: ViewGroup, position: Int): ContactViewHolder {
val view = LayoutInflater.from(viewGroup.context).inflate(R.layout.contact_item_layout,viewGroup,false)
return ContactViewHolder(view)
}
override fun onBindViewHolder(holder: ContactViewHolder, position: Int) {
val contact = contactList[position]
holder.name!!.text = contact.contactName
holder.mobile!!.text = contact.contactNumber[0]
Glide.with(holder.itemView.context)
.load(contact.contactImage)
.into(holder.image)
}
override fun getItemCount(): Int = contactList.size
class ContactViewHolder(itemView: View): RecyclerView.ViewHolder(itemView){
var image : ImageView = itemView.find(R.id.contact_image) as ImageView
var name : TextView? = itemView.find(R.id.contact_name) as TextView
var mobile : TextView? = itemView.find(R.id.contact_mobile) as TextView
}
}
Any help would be appreciated.
Thankyou

Categories

Resources