Android AutoCompleteTextView Bind dropdown to complex datasource is showing the wrong text for selected item

Viewed 11

Basically all examples of using this control as a replacement for a dropdown list show the datasource as a string array. My datasource is a list of objects. I successfully have the control behaving as expected, except that when you choose an item I end up with text in the text field which seems to be the name of the object. I do have a workaround which involves capturing onitemclick and setting the text manually, but it seems to me this is a hack. Can anyone tell me why this is malfunctioning? Adapter code:

package com.dispatchcrude.mobiledriverapp.adapter;

import android.annotation.SuppressLint;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.dispatchcrude.mobiledriverapp.R;
import com.dispatchcrude.mobiledriverapp.dao.OriginTankDao;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import static com.dispatchcrude.mobiledriverapp.dao.OriginTankDao.ORIGIN_TANK_ZERO_CAPTION;

public class OriginTankDropdownAdapter extends 
BaseMaterialDropdownAdapter<OriginTankDao> {

/**
 * Constructor that uses the default zero caption of "(Select Tank)"
 *
 * @param context  Context.
 * @param orderId  Current Order ID.
 * @param originId Current Origin ID.
 */
public OriginTankDropdownAdapter(@NonNull Context context, int orderId, int originId) {
    super(context, new OriginTankDao(), ORIGIN_TANK_ZERO_CAPTION, 0);
    mContext = context;
    mList = new OriginTankDao().getOriginTanksUi(originId, ORIGIN_TANK_ZERO_CAPTION, orderId);
}

/**
 * Constructor that uses the passed in "option label" instead of the default "(Select Tank)"
 *
 * @param context     Context.
 * @param orderId     Current Order ID.
 * @param originId    Current Origin ID.
 * @param optionLabel Text to display instead of "(Select Tank)"
 */
public OriginTankDropdownAdapter(@NonNull Context context, int orderId, int originId, String optionLabel) {
    super(context, new OriginTankDao(), optionLabel, 0);
    mContext = context;
    mList = new OriginTankDao().getOriginTanksUi(originId, optionLabel, orderId);
}

@SuppressLint({"SetTextI18n", "InflateParams"})
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
    OriginTankDao record = mList.get(position);
    OriginTankDropdownAdapter.ViewHolder holder;

    if (convertView == null) {
        convertView = LayoutInflater.from(mContext).inflate(R.layout.list_item_material_dropdown_single_line, null);
        holder = new OriginTankDropdownAdapter.ViewHolder();
        holder.tvKey = convertView.findViewById(R.id.tvItemIndexValue);
        holder.tvValue = convertView.findViewById(R.id.tvItemDisplayValue);
        convertView.setTag(holder);
    } else {
        holder = (OriginTankDropdownAdapter.ViewHolder) convertView.getTag();
    }

    holder.tvKey.setText(Integer.toString(record.getId()));
    holder.tvValue.setText(record.getName());

    return convertView;
}

public String getTextOfFirstItem() {
    return mList.get(0).getName();
}

/**
 * Finds a tank with the passed name value (if it exists in the list) and returns that tank's ID.
 * @param tankName The name name to look for.
 * @return Returns the ID of the passed tank name, or -1 if the tank is not found.
 */
public int getTankId(String tankName) {
    for (OriginTankDao tank : mList) {
        if (tank.getName().equals(tankName)) {
            return tank.getId();
        }
    }

    return -1;
}

/**
 * Finds a tank with the passed ID (if it exists in the list) and returns the number and description of that tank.
 *
 * @param tankId The ID of the tank to look for.
 * @return Returns the number and description of a tank if it exists in the list.
 */
public String getTankName(int tankId) {
    for (OriginTankDao tank : mList) {
        if (tank.getId() == tankId) {
            return tank.getName();
        }
    }

    return "";
}

public static class ViewHolder {
    TextView tvKey;
    TextView tvValue;
  }

}

control usage in class:

int originId = new OrderDao(orderId).getOriginId();
acOriginTank.setAdapter(new OriginTankDropdownAdapter(this, orderId, originId));

acOriginTank.setOnItemClickListener((parent, view, position, id) -> {
            String selectedItemText = ((TextView) view.findViewById(R.id.tvItemDisplayValue)).getText().toString();
        });

And finally control:

        <com.google.android.material.textfield.TextInputLayout
        android:id="@+id/tilTankNum"
        style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/cts_material_general_margin_minimum"
        android:layout_weight="7">

        <com.google.android.material.textfield.MaterialAutoCompleteTextView
            android:id="@+id/acTankNum"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:editable="false"
            android:hint="@string/caption_tank_num"
            android:inputType="none"
            android:minHeight="@dimen/cts_material_general_minimum_touch_target_height_or_width"
            tools:hint="@string/caption_tank_num"
            tools:ignore="Deprecated,LabelFor" />

    </com.google.android.material.textfield.TextInputLayout>

To be clear, this is working but I want to be able to eliminate the item click event.

0 Answers
Related