【问题标题】:AutoCompleteTextView - How to remove margin from top and bottom?AutoCompleteTextView - 如何从顶部和底部删除边距?
【发布时间】:2022-01-05 10:11:04
【问题描述】:

我正在使用AutoCompleteTextView 创建一个下拉菜单。如何删除列表顶部和底部的默认边距?

重新创建:

<com.google.android.material.textfield.TextInputLayout
        style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="parent"
        app:boxBackgroundColor="@color/white"
        android:focusable="false"
        app:boxStrokeWidth="1.5dp"
        app:layout_constraintTop_toBottomOf="@+id/spinner_network">

        <AutoCompleteTextView
            android:id="@+id/autoCompleteTextView"
            android:layout_width="250dp"
            android:layout_height="match_parent"
            android:inputType="none"
            android:dropDownHeight="200dp"
            android:text="Select age" />

    </com.google.android.material.textfield.TextInputLayout>
        List<String> dropdownItems = new ArrayList<>();
        for(int i = 1; i <= 100; i++){
            dropdownItems.add(String.valueOf(i));
        }

        ArrayAdapter<String> spinnerAdapter = new ArrayAdapter<>(
                this, R.layout.dropdown_item, dropdownItems
        );

        AutoCompleteTextView autoCompleteTextView = findViewById(R.id.autoCompleteTextView);
        autoCompleteTextView.setAdapter(spinnerAdapter);

R.layout.dropdown_item

<TextView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/textView"
    android:layout_width="match_parent"
    android:textColor="@color/black"
    android:padding="14dp"
    android:layout_height="wrap_content"
    android:text="TextView" />

【问题讨论】:

  • 好的,是的,我最初并没有意识到你在做什么;您并没有真正将其用作AutoCompleteTextView。好吧,在这里忽略我以前的 cmets,因为我认为这只是针对常规的 AutoCompleteTextView 设置。如果我想到别的,我会告诉你的。顺便说一句,您的 XML 或代码确实没有问题。 ACTV 正在按预期工作。 TIL 只是添加了一些花里胡哨,其中之一就是可点击的下拉箭头。 ACTV 自己没有。
  • 我发现在 ACTV 上设置 OnClickListener 确实有效,因为它不接受文本输入。这意味着我们基本上可以在没有 TIL 的情况下复制 TIL 的行为:drive.google.com/file/d/10fpJswrcJ7MiDnRJH7Ycv49p3J37f2nO/…。我无法在这台机器 atm 上获得流畅的视频,但它可以工作:i.stack.imgur.com/T2QrH.png。不确定你是否真的想要边框,但你可以看到填充消失了(所以它一定来自某个地方的 TIL,但我还没有找到它)。仅供参考,如果对你有帮助的话。
  • @MikeM。绝对的传奇。它修复了边距问题,在没有 TIL 的情况下工作(我不喜欢闪烁的下拉动画),现在我可以使用这个解决方案而不是微调器来实现简单的 dropDownHeight。谢谢一堆。发表你的答案并声称你的赏金老板是你应得的 Lol
  • 没问题。不过,我不再在这里发布答案,所以请随意完成这个,但你喜欢。我仍然想追踪填充的来源,如果我想出某种方法从 XML 中关闭它,我会告诉你的。不过谢谢。我很感激这个提议。很高兴我们发现了一些有用的东西。干杯!
  • 我找到了它的来源,并在下面对 Zain 的回答添加了一些注释,因为他们首先确认父母的填充导致了这些差距。

标签: android material-design autocompletetextview material-components-android android-textinputlayout


【解决方案1】:

更新

cmets 对@MikeM. 的所有功劳和努力。非常感谢他的努力。

原因 填充来自TextInputLayout 本身,它的DropdownMenuEndIconDelegate sets some MaterialShapeDrawables as the dropdown's background。垂直填充的值为 8dp,取自this resource dimen

解决方案 1:

将此资源维度覆盖为 0dp:

<dimen name="mtrl_exposed_dropdown_menu_popup_vertical_padding" tools:override="true">0dp</dimen>

解决方案 2:

前面的解决方案将应用于所有AutoCompleteTextView,但如果你想对某些执行此操作:更改默认的dropDown背景drawable,例如:

autoCompleteTextView.setDropDownBackgroundDrawable(new ColorDrawable(Color.WHITE));

带反射(不推荐,因为它是反模式)

AutoCompleteTextView 的下拉弹出窗口可以通过mPopup field 内部访问。通过反射获得它:

// Java:

public static ListPopupWindow getPopup(AutoCompleteTextView autoCompleteTextView) {
    try {
        Field field = AutoCompleteTextView.class.getDeclaredField("mPopup");
        field.setAccessible(true);
        return (ListPopupWindow) field.get(autoCompleteTextView);
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
    return null;
}


//  Kotlin:

fun AutoCompleteTextView.getPopup(): ListPopupWindow? {
    try {
        val field = AutoCompleteTextView::class.java.getDeclaredField("mPopup")
        field.isAccessible = true
        return field.get(this) as ListPopupWindow
    } catch (e: NoSuchFieldException) {
        e.printStackTrace()
    } catch (e: IllegalAccessException) {
        e.printStackTrace()
    }
    return null
}

然后通过将其设置为内部ListView的父视图来移除填充:

// Java:

autoCompleteTextView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        ListPopupWindow popup = getPopup(autoCompleteTextView);
        if (popup != null) {
            ListView listView = popup.getListView();
            if (listView!= null)
                ((View) listView.getParent()).setPadding(0, 0, 0, 0);
        }
    }
});

// Kotlin

autoCompleteTextView.setOnClickListener {
    val popUp = autoCompleteTextView2.getPopup()?.listView?.parent
    if (popUp != null)
        (popUp as View).setPadding(0, 0, 0, 0)
}

这是在OnClickListener 中完成的,因为当用户点击列表时,可空性检查将不匹配。

【讨论】:

  • 真的没有简单的 XML 解决方案吗?我真的不想为了删除边距而添加所有这些膨胀
  • 在发这个之前确实做了一些研究,从xml属性到样式,在网上搜索也找不到任何线索很遗憾
  • ……那个值;例如,&lt;dimen name="mtrl_exposed_dropdown_menu_popup_vertical_padding" tools:override="true"&gt;0dp&lt;/dimen&gt;。或者,在代码中,这意味着我们可以设置一个可绘制的背景来摆脱该填充,而无需借助反射来获得弹出窗口;例如,autoCompleteTextView.setDropDownBackgroundDrawable(new ColorDrawable(Color.WHITE));。仅供参考,真的,如果其中任何一个对你有用的话。干杯!
  • (请不要觉得你必须这样做,如果你想删除这个,或者其他什么。我只是认为赏金不应该去浪费。)
  • 赏金已按 OP 的预期工作,因此他们物有所值。没有必要让代表消失,如果你愿意努力从所有这些中找出一个正确的答案,我会说这值得一些分数。此外,我是一个懒惰的人,Zain。你也会帮我一个忙。 :-)
【解决方案2】:

尝试从 AutoCompleteTextView 中删除 dropDownHeight 属性

android:dropDownHeight="200dp" --> remove this line

并将您的 AutoCompleteTextView 高度设置为wrap_content

【讨论】:

  • 那行不通
【解决方案3】:

它不会让我编辑答案,而是https://stackoverflow.com/users/2850651/mike-m 的另一个解决方案 删除填充:

autoCompleteTextView 中调用.showDropDown() .setOnClickListener()

<com.google.android.material.textfield.MaterialAutoCompleteTextView
        android:id="@+id/autoCompleteTextView"
        android:layout_width="250dp"
        android:layout_height="50dp"
        android:drawableEnd="@drawable/ic_arrow_drop_down"
        android:dropDownHeight="200dp"
        android:inputType="none"
        android:text="Select age" 
        ...../>

List<String> dropdownItems = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
     dropdownItems.add(String.valueOf(i));
}

ArrayAdapter<String> spinnerAdapter = new ArrayAdapter<>(
    this, R.layout.dropdown_item, dropdownItems
);


MaterialAutoCompleteTextView autoCompleteTextView = findViewById(R.id.autoCompleteTextView);
autoCompleteTextView.setAdapter(spinnerAdapter);

//.showDropDown() removes the padding
autoCompleteTextView.setOnClickListener(v -> autoCompleteTextView.showDropDown());

【讨论】: