带有子微调器的微调器未按预期工作

Spinner with sub-spinner not working as expected

我有两个 spinners,因此我的第二个微调器会根据第一个微调器中的 selected 项目更改它可以提供的选项。简单?

示例:如果我在主微调器中 select 'a',则子微调器应显示 'a1' 作为选项。如果我在主微调器中 select 'b',则子微调器应显示 'b1'、'b2' 作为选项。如果我在主微调器中 select 'c',则子微调器应显示 'c1'、'c2'、'c3' 作为选项。

我使用了一个名为 SearchableSpinner 的库,但这并不重要,因为它就像 Android 微调器一样工作。

public class PostComplaint extends AppCompatActivity {
    String[] problems_main = {"a","b","c"};
    String[][] problems_sub = {{"a1"},{"b1","b2"},{"c1","c2","c3"}};

    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_post_complaint);

    spinner_main = (SearchableSpinner)findViewById(R.id.spinner_main);
    spinner_sub = (SearchableSpinner) findViewById(R.id.spinner_sub);

    ArrayAdapter<String> spinnerAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, problems_main);
    spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    spinner_main.setAdapter(spinnerAdapter);
    spinnerAdapter.notifyDataSetChanged();

    spinner_main.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            setSubSpinner(position);
        }
        @Override
        public void onNothingSelected(AdapterView<?> parent) {
            Toast.makeText(PostComplaint.this, "Nothing selected", Toast.LENGTH_SHORT).show();
        }
    });
}

void setSubSpinner(int i){
    String[] myArray = problems_sub[i]; //Note: problems_sub is a two dimensional array
    ArrayAdapter<String> spinnerAdapter_sub = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, myArray);
    spinnerAdapter_sub.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    spinner_sub.setAdapter(spinnerAdapter_sub);
    spinnerAdapter_sub.notifyDataSetChanged();
}

问题:无论我第一次点击主微调器上的哪个项目,根据该子微调器是 selected。然后,如果我更改主微调器,子微调器不会改变。

该问题正在征求建议。不明白的地方评论一下。

由于 SearchableSpinner 中的以下函数而出现错误 Class:

@Override
public boolean onTouch(View v, MotionEvent event) {
    if (event.getAction() == MotionEvent.ACTION_DOWN) {
        ArrayAdapter adapter = (ArrayAdapter) getAdapter();

        if (null != adapter) {

            if (_items.size() == 0) {
                for (int i = 0; i < adapter.getCount(); i++) {
                    _items.add(adapter.getItem(i));
                }
            }
            SearchableListDialog searchableListDialog = SearchableListDialog.newInstance
                    (_items);
            searchableListDialog.setOnSearchableItemClickListener(this);
            searchableListDialog.show(((Activity) _context).getFragmentManager(), "TAG");
        }
    }
    return true;
}

条件 if(_items.size() == 0) 只有在您第一次单击子微调器时才会变为真,因此它会正确初始化并且您会看到正确的值。但是,一旦您单击了子微调器,_item.size() 将永远不会为零,因此永远不会呈现更新的子微调器值。

我建议您使用默认的 Android Spinner 或 fork 存储库并修复错误并使用它。

编辑

你可以试试这个class:

import android.app.Activity;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Spinner;

import com.toptoche.searchablespinnerlibrary.SearchableListDialog;

import java.util.ArrayList;
import java.util.List;

public class CustomSearchableSpinner extends Spinner implements View.OnTouchListener,
    SearchableListDialog.SearchableItem {

private Context _context;
private List _items;
private boolean isDataSetChanged;

public CustomSearchableSpinner(Context context) {
    super(context);
    this._context = context;
    this.isDataSetChanged = true;
    init();
}

public CustomSearchableSpinner(Context context, AttributeSet attrs) {
    super(context, attrs);
    this._context = context;
    this.isDataSetChanged = true;
    init();
}

public CustomSearchableSpinner(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    this._context = context;
    this.isDataSetChanged = true;
    init();
}

private void init() {
    _items = new ArrayList();
    setOnTouchListener(this);
}

@Override
public boolean onTouch(View v, MotionEvent event) {
    if (event.getAction() == MotionEvent.ACTION_DOWN) {
        ArrayAdapter adapter = (ArrayAdapter) getAdapter();

        if (null != adapter) {

            if (isDataSetChanged) {
                if(_items.size() != 0) {
                    _items = new ArrayList();
                }
                for (int i = 0; i < adapter.getCount(); i++) {
                    _items.add(adapter.getItem(i));
                }
                isDataSetChanged = false;
            }
            SearchableListDialog searchableListDialog = SearchableListDialog.newInstance
                    (_items);
            searchableListDialog.setOnSearchableItemClickListener(this);
            searchableListDialog.show(((Activity) _context).getFragmentManager(), "TAG");
        }
    }
    return true;
}

@Override
public void onSearchableItemClicked(Object item, int position) {
    setSelection(_items.indexOf(item));
}

public void notifyDataChanged(Boolean hasDataChanged) {
    this.isDataSetChanged = hasDataChanged;
}
}

此外,更新您的布局文件和 PostComplaint Class 以使用 CustomSearchableSpinner 代替 Searchable Spinner。这可能不是最好的方法,但它确实有效。

编辑 2

您需要在调用 spinnerAdapter_sub.notifyDataSetChanged(); 之后调用 spinnerAdapter_sub.notifyDataChanged(true)