Android动态创建多个AutoCompleteTextView的问题

And*_*fix 6 android autocompletetextview kotlin

我想动态创建输入视图,每个视图都包含一个 AutoCompleteTextView。每个 AutoCompleteTextView 都会显示一个下拉列表。

我定义了一个项目视图 (item_new_product.xml),它会膨胀并添加到 viewContainer (activity_main.xml)。

每个AutoCompleteTextView在xml中定义了一个dropDownAnchor,它是其父TextInputLayout的视图ID。这是下拉列表应该显示的位置。

对于第一项,下拉菜单出现在正确的位置(参见屏幕截图 1)。但每个额外的 Dropdown 都与第一个 AutoCompleteTextView 的 TextInputLayout 相关联,因为它们都具有相同的 dropDownAnchor id(参见屏幕截图 2)。

有没有一种干净的方法可以在正确的位置显示具有多个动态创建的 AutoCompleteTextView 的下拉列表?我还没有找到与这个特定问题相关的任何内容。

活动主文件

<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>
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

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)
        }
    }
Run Code Online (Sandbox Code Playgroud)

样式.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>
Run Code Online (Sandbox Code Playgroud)

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" />
Run Code Online (Sandbox Code Playgroud)