AutoCompleteTextView & ArrayAdapter with back to Fragment

34 views Asked by At

(sorry for my english)

I have fragment where I have an AutocompleteTextView and ArrayAdapter for it. ArrayAdapter get values from resource strings.

When fragment creating first time — everything is ok, but when I go to fragment back (with backstack or replace with saved fragment) my AutocompleteTextView show only 1 item but ArrayAdapter size is 6. I really don't know why is that...

I was thinking if I save ArrayAdapter at viewmodel it will work, but no. I want to see my items after I back to fragment

SomeFragment.kt (all names changed):

class SomeFragment : Fragment() {
    private val mSomeViewModel = SomeViewModel()

    private lateinit var mSomeAutoCompleteTextView: AutoCompleteTextView
    private lateinit var mSomeStrings: Array<String>
    private lateinit var mSomeArrayAdapter: ArrayAdapter<String>

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?,
    ): View? {
        mSomeStrings = resources.getStringArray(R.array.strings_array)
        mSomeArrayAdapter = ArrayAdapter(requireContext(), R.layout.dropdown_item, mSomeStrings)

        return inflater.inflate(R.layout.fragment_order_server, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        view.apply {
            mSomeAutoCompleteTextView = findViewById(R.id.someAutoCompleteTextView)
        }

        mSomeAutoCompleteTextView.apply {
            setText(mSomeStrings[mSomeViewModel.positionId])
            /* when breakpoint here and check mSomeArrayAdapter.count there are 6 items, but app show only one */
            setAdapter(mSomeArrayAdapter)
            setOnItemClickListener { _, _, position, _ ->
                mSomeViewModel.someFunction(position)
            }
        }
    }
}

SomeViewModel.kt (all names changed):

class SomeViewModel : ViewModel() {
    val positionId: Int
        get() = mPositionId

    fun someFunction(position: Int) {
        mPositionId = position

        /* some other code */
    }
}
2

There are 2 answers

1
iwakes On BEST ANSWER

Okay, I just found a solution. My mistake was that I use standard ArrayAdapter instead of my own (or it's because ArrayAdapter has something bad). I created custom BaseAdapter with Filterable and it's work.

Code if someone needed:

class OrderArrayAdapter<T : Any>(
    private val context: Context,
    list: Array<T>
) : BaseAdapter(), Filterable {
    private val mObjects = list

    override fun getCount(): Int {
        return mObjects.size
    }

    override fun getItem(position: Int): Any {
        return mObjects[position]
    }

    override fun getItemId(position: Int): Long {
        return position.toLong()
    }

    override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
        val item = getItem(position)
        val view = convertView ?: LayoutInflater.from(context)
            .inflate(R.layout.dropdown_item, parent, false)

        view.apply {
            findViewById<TextView>(R.id.dropdownTextView).text = item.toString()
        }

        return view
    }

    override fun getFilter(): Filter {
        return customFilter
    }

    private val customFilter = object : Filter() {
        override fun performFiltering(constraint: CharSequence?): FilterResults {
            val filterResults = FilterResults()
            filterResults.values = mObjects
            return filterResults
        }

        override fun publishResults(constraint: CharSequence?, results: FilterResults?) {
            notifyDataSetChanged()
        }
    }
}
1
Amanpreet Kaur On

This happens in the autocomplete edit text, when you set the text in the edit text without specifying whether to filter list data or not. By default, it keeps only one matching record and discard others, to correct your code you can replace your autocomplete code with the following

 mSomeAutoCompleteTextView.apply {
            setText(mSomeStrings[mSomeViewModel.positionId], false)
            setAdapter(mSomeArrayAdapter)
            setOnItemClickListener { _, _, position, _ ->
                mSomeViewModel.someFunction(position)
            }
        }