I am trying to use a android Spinner in a Custom dialog, but when I tap on the Spinner the list with items opens and you can tap on them and the view closes, but none of the items gets selected. When I use the exact same code in a normal Fragment it works fine.
And since I found nothing helpful anywhere, is there something I need to know when using the spinner in a Dialog ?
CustomDialog Class:
public SelectionDialog(Activity context, ArrayAdapter<T> arrayAdapter, List<T> objects) {
super(context);
this.activity = context;
this.arrayAdapter = arrayAdapter;
this.objects = objects;
}
@SuppressLint("ResourceAsColor")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().requestFeature(Window.FEATURE_NO_TITLE);
getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));
View view = LayoutInflater.from(getContext()).inflate(R.layout.dialog_selection,null);
setContentView(view);
BodyMenuCard parentCard = view.findViewById(R.id.parentCard);
parentCard.setHeader(header);
TextView textView = parentCard.getCardBody().findViewById(R.id.bodyText);
textView.setText(description);
yesBtn = parentCard.getCardBody().findViewById(R.id.btn_yes);
//spinner = parentCard.getCardBody().findViewById(R.id.employeeSpinner);
spinner = view.findViewById(R.id.employeeSpinner);
spinnerHandler = new EmployeeSpinnerHandler(getContext(), spinner, (List<Employee>)
toggleYesBtn(false);
if (iconRessoruce != -1) parentCard.setIcon(iconRessoruce);
if (backgroundColor != -1) parentCard.setCircleColor(backgroundColor);
if (successfullCallback != null) yesBtn.setOnClickListener((v -> successfullCallback.onClick(this)));
if (abbortCalllback != null) {
parentCard.getCardBody().findViewById(R.id.btn_no).setOnClickListener((v -> abbortCalllback.onClick(this)));
} else {
parentCard.getCardBody().findViewById(R.id.btn_no).setOnClickListener(v -> this.dismiss());
}
}
EmployeeSpinnerAdapter
public class EmployeeSpinnerAdapter extends ArrayAdapter<Employee> {
private Map<String, ColorStateList> employeeColors;
private List<Employee> employees;
private RandomMaterialColor randomColor;
public EmployeeSpinnerAdapter(Context context, List<Employee> employees) {
super(context, R.layout.employee_spinner, employees);
setDropDownViewResource(R.layout.employee_spinner);
this.employees = employees;
this.employeeColors = new HashMap<>();
}
private class ViewHolder {
private GradientDrawable background;
private TextView header;
private TablePart idField;
private ViewHolder(View view) {
if (randomColor == null) randomColor = new RandomMaterialColor(view.getResources(), view.getContext());
ImageView iv = view.findViewById(R.id.icon_view);
background = (GradientDrawable) iv.getBackground().mutate();
header = view.findViewById(R.id.header);
idField = view.findViewById(R.id.description);
}
private void populate(Employee employee) {
header.setText(employee.getName());
idField.update(employee.getId());
ColorStateList color = employeeColors.getOrDefault(employee.getId(), ColorStateList.valueOf(randomColor.getMatColor("A700")));
background.setColor(color);
}
}
@Override
public int getCount() {
return employees.size();
}
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
return obtainView(position, convertView, parent);
}
@Override
public View getDropDownView(int position, View convertView, ViewGroup parent)
{
return obtainView(position, convertView, parent);
}
private View obtainView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater mInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = mInflater.inflate(R.layout.employee_spinner, parent, false);
convertView.setTag(new ViewHolder(convertView));
}
ViewHolder vh = (ViewHolder) convertView.getTag();
vh.populate(employees.get(position));
return convertView;
}
}
EmployeeSpinnerHandler The purpose of the class is to have exacly the same code handling the Spinner inside a dialog and outside, to find the mistake.
public class EmployeeSpinnerHandler {
private Context context;
private Spinner spinner;
private EmployeeSpinnerAdapter adapter;
private List<Employee> employees;
public EmployeeSpinnerHandler(Context context, Spinner spinner, List<Employee> employees) {
this.context = context;
this.spinner = spinner;
this.employees = employees;
setUp();
}
private void setUp() {
adapter = new EmployeeSpinnerAdapter(getContext(), employees);
spinner.setAdapter(adapter);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
FancyToast.makeText(getContext(), "selected: " + employees.get(position).getName(), Toast.LENGTH_LONG, FancyToast.SUCCESS, true).show();
//toggleYesBtn(true);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
//toggleYesBtn(false);
FancyToast.makeText(getContext(), "selected: none", Toast.LENGTH_LONG, FancyToast.SUCCESS, true).show();
}
});
}
public void updateObjects(List<Employee> employees) {
this.employees.clear();
this.employees.addAll(employees);
adapter.notifyDataSetChanged();
}
}
The Spinner inside the normal Fragment
spinner = view.findViewById(R.id.employeeSpinner);
EmployeeSpinnerHandler spinnerHandler = new EmployeeSpinnerHandler(getContext(), spinner, objects);
Notice: In boath cases the date gets fetched from a REST-Api, but it still only works in the normal Fragment.
And now the problem is, if I use the EmployeeSpinnerHandler on a Spinner located in a normal Fragment it works, but if I am using the Spinner in the selection dialog, you can click the spinner and the items show up, but they arent selectable (see in the images).
Images:
Adapter allow single focus view make android:focusable="false"
for all other itemsandroid:focusable="true"
for your TextView which holds the title it will work.