Java 暴露下拉菜单只有一项

Java Exposed DropDown Menu only one item

我尝试创建一个 Android 带有公开下拉菜单的应用程序,如下所示:
https://material.io/components/menus/android#exposed-dropdown-menus

左图出现在第一次打开菜单时。选择一项,变化到合适的情况。再次重新选择相同的项目,又变回左边的情况。

这是我的适配器的实现:

public class FilterMenuCategoryAdapter extends ArrayAdapter<String> {
    private static final String TAG = "FilterMenuCategoryAdapter";
    List<String> categoryList;
    LvElCategoryBinding binding;
    Context context;

    public FilterMenuCategoryAdapter(Context context) {
        super(context, 0, getCompleteCategoryList());
        this.context = context;
        this.categoryList = getCompleteCategoryList();
    }

    public FilterMenuCategoryAdapter(Context context, List<String> categoryList) {
        super(context, 0, categoryList);
        this.context = context;
        this.categoryList = new ArrayList<>(categoryList);
    }

    @Override
    public int getCount() {
        return categoryList.size();
    }

    @Override
    public String getItem(int position) {
        return categoryList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return 0;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            binding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), R.layout.lv_el_category, parent, false);
        }
        String category = categoryList.get(position);
        binding.tvTitle.setText(category);
        binding.icon.setImageResource(new IconNameMapper().get(category));
        return binding.getRoot();
    }

}

这是用过的 XML:

 <com.google.android.material.textfield.TextInputLayout
    style="@style/dropDownMenuOnWhite"
    android:layout_width="match_parent"
    android:layout_height="50dp">

    <AutoCompleteTextView
        android:id="@+id/filterMenu"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:inputType="none"
        android:paddingTop="5dp"
        android:paddingBottom="5dp"
        android:text="@string/show_all"
        android:textAlignment="textEnd"
        android:textColor="@color/primaryTextColor"
        android:textSize="@dimen/font_size" />
</com.google.android.material.textfield.TextInputLayout>

在我的片段中 Class 我这样称呼它:

FilterMenuCategoryAdapter adapter = new FilterMenuCategoryAdapter(this.getContext());
binding.filterMenu.setAdapter(adapter);

目前,菜单中的每个选择都会中断我的 onClick 事件。所以我很高兴能得到任何帮助!

更新: 我修好了它!在 getView() 中使用 DataBinding 对我来说每次都会杀死它。
以下解决方案有效:

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            convertView = LayoutInflater.from(getContext()).inflate(
                    R.layout.lv_el_category, parent, false
            );
        }
        TextView title = convertView.findViewById(R.id.tv_title);
        ShapeableImageView image = convertView.findViewById(R.id.icon);
        String category = categoryList.get(position);
        title.setText(category);
        image.setImageResource(new IconNameMapper().get(category));
        return convertView;
    }

如果您知道如何在 getView() 中使用 DataBinding,请告诉我!

问题不在 dataBinding 本身;但是它的实现方式。

当您第一次点击菜单时,它会正确显示,因为 converViewnull 并且满足建立绑定对象的条件。

点击项目时菜单项消失的原因;当再次调用 getView() 时,它有一个新的 convertView 对象,该对象具有不同于旧调用 getView() 的新状态;但你忽略了它,并使用旧的 binding 对象及其原始状态来查找视图;这使得dataBinding无法膨胀新状态的视图(可能是指旧回收的视图)。

这就是 convertView 作为方法参数传递的原因;因此每次回收视图时都需要使用全新的 convertView

解决这个问题;您需要通过保存 dataBinding 的视图来做同样的事情; binding.getRoot() 返回。并且您必须使用 convertView 来保存此 dataBinding 视图状态。这通常可以通过 ViewHolder 并使用 setTag():

保存视图及其状态来完成

ViewHolder 与 RecyclerView view holder 的想法相似:

@Override
public View getView(int position, View convertView, ViewGroup parent) {

    ItemViewHolder holder;
    if (convertView == null) {
        LvElCategoryBinding binding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), R.layout.lv_el_category, parent, false);
        holder = new ItemViewHolder(binding);
        holder.view = binding.getRoot();
        holder.view.setTag(holder); 
    } else {
        holder = (ItemViewHolder) convertView.getTag();
    }
    String category = categoryList.get(position);
    holder.binding.tvTitle.setText(category);
    holder.binding.icon.setImageResource(new IconNameMapper().get(category));
    return holder.view;
}

private static class ItemViewHolder {
    private View view;
    private LvElCategoryBinding binding;

    ItemViewHolder(LvElCategoryBinding binding) {
        this.view = binding.getRoot();
        this.binding = binding;
    }
}