I want to dynamically create input views, which each contain an AutoCompleteTextView. Each AutoCompleteTextView shows a Dropdown list.
I have defined an item view (item_new_product.xml), which gets inflated and added to the viewContainer (activity_main.xml).
Each AutoCompleteTextView has defined a dropDownAnchor in xml, which is the view ID of its parent TextInputLayout. This is where the dropdown list should show up.
For the first item the Dropdown appears in the right place (see Screenshot 1). But each additional Dropdown is associated to the first AutoCompleteTextView's TextInputLayout, because they all have the same dropDownAnchor id(see Screenshot 2).
Is there a clean way to show the Dropdown lists at the right place having multiple dynamically created AutoCompleteTextViews? I have not found anything related to this specific issue.
activity_main.xml
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.google.android.material.card.MaterialCardView
android:id="@+id/cardView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:backgroundTint="@android:color/holo_blue_dark"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.button.MaterialButton
android:id="@+id/addButton"
android:layout_width="52dp"
android:layout_height="52dp"
android:layout_gravity="start"
android:background="@color/holo_blue_bright"
android:elevation="5dp"
android:text="+" />
<com.google.android.material.button.MaterialButton
android:id="@+id/removeButton"
android:layout_width="52dp"
android:layout_height="52dp"
android:layout_gravity="end"
android:background="@color/holo_blue_bright"
android:elevation="5dp"
android:text="-" />
</com.google.android.material.card.MaterialCardView>
<LinearLayout
android:id="@+id/viewContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_margin="16dp"
android:animateLayoutChanges="true"
android:background="@color/holo_blue_dark"
android:orientation="vertical"
android:padding="8dp"
app:layout_constraintTop_toBottomOf="@id/cardView"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
item_new_product.xml
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="vertical"
app:layout_constraintGuide_percent=".5" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/productText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:hint="Product"
app:hintTextColor="@color/holo_blue_dark"
app:helperText=" "
app:boxBackgroundColor="@color/holo_blue_bright"
app:boxStrokeColor="@color/holo_blue_dark"
app:layout_constraintEnd_toStartOf="@+id/guideline"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/productEditText"
android:layout_width="match_parent"
android:layout_height="52dp"
android:textSize="12sp"
android:imeOptions="actionNext"
android:inputType="textPersonName"
android:textCursorDrawable="@null" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/productTypeLayout"
style="@style/DropdownLayoutStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:hint="Type"
app:helperText=" "
android:inputType="none"
app:boxBackgroundColor="@color/holo_blue_bright"
app:boxStrokeColor="@color/holo_blue_dark"
app:endIconTint="@color/holo_blue_dark"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toEndOf="@id/guideline"
app:layout_constraintEnd_toEndOf="parent">
<AutoCompleteTextView
android:id="@+id/productTypeAutoCompleteTv"
android:layout_width="match_parent"
android:layout_height="52dp"
android:dropDownAnchor="@id/productTypeLayout"
android:dropDownHeight="120dp"
android:inputType="none"
android:maxLines="1"
android:textSize="12sp"
android:singleLine="true"
android:paddingStart="16dp"
android:paddingEnd="16dp"/>
</com.google.android.material.textfield.TextInputLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.kt
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private var IDs = mutableListOf<Int>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
binding.addButton.setOnClickListener {
Timber.d("add clicked")
addView()
}
binding.removeButton.setOnClickListener {
Timber.d("remove clicked")
removeView()
}
setContentView(binding.root)
}
private fun addView() {
Timber.d("addView")
val rootView = binding.viewContainer
val inflater = LayoutInflater.from(this)
val child: View = inflater.inflate(R.layout.item_new_product, rootView, false)
// generate new view id and remember it for later removal
val childId = View.generateViewId()
child.id = childId
IDs.add(childId)
val items: List<String> = listOf("Beverages", "Cocktails", "Pasta", "Pizza", "Salads")
val adapter = ArrayAdapter(this, R.layout.item_product_dropdown, items)
val productAutoComplete =
child.findViewById(R.id.productTypeAutoCompleteTv) as AutoCompleteTextView
productAutoComplete.setAdapter(adapter)
rootView.addView(child)
}
private fun removeView() {
if (IDs.size == 0) {
return
}
val view: View? = findViewById<View>(IDs.last())
IDs.removeLast()
if (view != null) {
(view.parent as ViewGroup).removeView(view)
}
}
styles.xml
<resources>
<style name="DropdownLayoutStyle" parent="Widget.MaterialComponents.TextInputLayout.FilledBox.ExposedDropdownMenu">
<item name="endIconTint">@color/holo_blue_dark</item>
<item name="hintTextColor">@color/holo_blue_dark</item>
</style>
</resources>
item_product_dropdown.xml
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="52dp"
android:background="@color/holo_blue_bright"
android:maxLines="1"
android:padding="16dp"
android:textColor="@color/white" />