Searchable Spinner没有在android工作

时间:2017-10-27 07:48:46

标签: android android-fragments android-arrayadapter android-spinner searchable

我有一个简单的旋转器,我工作完美。现在我想改变它,用户可以搜索其中的项目。按照以下代码我做了更改。

示例代码

//Gradle

 compile 'com.toptoche.searchablespinner:searchablespinnerlibrary:1.3.1'

//activity_main.xml

 <com.toptoche.searchablespinnerlibrary.SearchableSpinner
    android:id="@+id/searchable_spinner"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />
// In main activity 

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

    SearchableSpinner searchableSpinner = (SearchableSpinner) findViewById(R.id.searchable_spinner);
    String[] names = new String[]{"India","CHINA","UK","US","MALYSIA"};
    ArrayAdapter arrayAdapter = new ArrayAdapter(MainActivity.this,android.R.layout.simple_spinner_dropdown_item,names);
    searchableSpinner.setAdapter(arrayAdapter);

    searchableSpinner.setTitle("Select Item");
    searchableSpinner.setPositiveButton("OK");

}

输出

点击dropdown

enter image description here

我做了什么?

//added the library in gradle 
compile 'com.toptoche.searchablespinner:searchablespinnerlibrary:1.3.1'

//new_form_layout (i have created this)
<com.toptoche.searchablespinnerlibrary.SearchableSpinner
                android:id="@+id/smart_msn_spinner"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:layout_gravity="right|center_vertical"
                android:gravity="right" />

**In My Fragment**
@BindView(R.id.smart_msn_spinner)
SearchableSpinner smartMsnSpinner;

现在我创建了一个bindListners()函数,我在其中绑定了所有值,我在onCreateView函数中调用它

 public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    if (view == null) {
        view = inflater.inflate(R.layout.new_form_layout, container, false);
        ButterKnife.bind(this, view);
        bindListners(); // here i am calling it
        imsiNo.setVisibility(View.GONE);
        setupUI(mScrollView);
    }
    Bundle arguments = getArguments();
    if (arguments != null && arguments.containsKey("install_id")) {
        isNewInstall = false;
        editInstallId = arguments.getString("install_id");
        getActivity().setTitle(getString(R.string.title_fragment_edit_form));
        setEditData();
        imsiNo.setVisibility(View.GONE);
        resetFormButton.setVisibility(View.GONE);
    } else {
        getActivity().setTitle(getString(R.string.title_fragment_new_form));
    }

    /*mCoordinatesReceiver = new CoordinatesReceiver();
    IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction(Common.GetCoordinatesAction());
    getActivity().registerReceiver(mCoordinatesReceiver, intentFilter);*/
    return view;
}
bindListeners(){
.......

    //Searchable smartMsnSpinner spinner and adapter
    meterSrArrayList = new ArrayList<String>();

    meterSrNumAdapter = new ArrayAdapter<String>(getActivity(), R.layout.custom_spinner_layout, meterSrArrayList);
    smartMsnSpinner.setAdapter(meterSrNumAdapter);
    smartMsnSpinner.setTitle("Select Item");
    smartMsnSpinner.setPositiveButton("Ok");
    smartMsnSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            selectedMeterNo = meterSrArrayList.get(position);
        }

        @Override
        public void onNothingSelected(AdapterView<?> parent) {

        }

    });
 }

在运行我的应用程序时,我只是像以前一样获得简单的下拉列表。

enter image description here

我不知道问题是什么以及因为我已经完成了样本中的所有操作而遗漏了什么。

我已在设备中运行示例代码并且工作正常。我不知道为什么它不能在我的应用程序上运行

更新

看了logcat我看到的错误是

Parcelable encountered IOException writing serializable object (name = com.toptoche.searchablespinnerlibrary.SearchableSpinner)

任何帮助都将受到高度赞赏。

1 个答案:

答案 0 :(得分:0)

我使用的是同一个库,但是我没有这个问题。 无论如何,我在此库的可视化,宗地化和重新初始化同一视图(向下滚动视图)方面都遇到了其他问题。

我个人扩展了“ SearchableSpinner”并进行了以下更改:

public class BaseSearchableSpinner extends SearchableSpinner
    implements  SearchView.OnAttachStateChangeListener {

    private static final String TAG = BaseSearchableSpinner.class.getSimpleName();
    private static final String TAG_DIALOG = TAG.concat(".dialog");
    // Dialogs Tags
    private static final String TAG_DIALOG_SEARCHABLE_LIST = TAG_DIALOG.concat(".searchableList");
    // SearchableSpinner Fields
    private static final String FIELD_SEARCHABLE_LIST_DIALOG = "_searchableListDialog";
    private static final String FIELD_SEARCH_VIEW = "_searchView";
    private static final String FIELD_SEARCHABLE_ITEM = "_searchableItem";
    private static final String FIELD_ARRAY_ADAPTER = "_arrayAdapter";
    private static final String FIELD_ITEMS = "_items";

    private boolean mIsListDialogAdded;
    private boolean mIsListenerAdded;

    public BaseSearchableSpinner(Context context) {
        super(context);
        initListDialog();
    }

    public BaseSearchableSpinner(Context context, AttributeSet attrs) {
        super(context, attrs);
        initListDialog();
    }

    public BaseSearchableSpinner(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initListDialog();
    }

    /** Override SearchableSpinner Methods **/
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        try{
            SearchableListDialog sld = (SearchableListDialog) FieldUtils.readField(this, FIELD_SEARCHABLE_LIST_DIALOG, true);
            ArrayAdapter adapter = (ArrayAdapter) FieldUtils.readField(this, FIELD_ARRAY_ADAPTER, true);
            List items = (List) FieldUtils.readField(this, FIELD_ITEMS, true);
            if (sld != null && adapter != null && items != null && event.getAction() == MotionEvent.ACTION_UP && checkIfListDialogNotAdded()) {
                if(mIsListenerAdded){
                    mIsListDialogAdded = true;
                }
                items.clear();
                for (int i = 0x0; i < adapter.getCount(); i++) {
                    items.add(adapter.getItem(i));
                }
                sld.show(scanForActivity(getContext()).getFragmentManager(), TAG_DIALOG_SEARCHABLE_LIST);
            }
        } catch (IllegalAccessException iaE){
            EMaxLogger.onException(TAG, iaE);
        }
        return true;
    }

    /** Override SearchView.OnAttachStateChangeListener Methods **/
    @Override
    public void onViewAttachedToWindow(View view) {
        mIsListDialogAdded = true;
    }

    @Override
    public void onViewDetachedFromWindow(View view) {
        mIsListDialogAdded = false;
    }

    /** Private Methods **/
    private void initListDialog(){
        try{
            SearchableListDialog oldD = (SearchableListDialog) FieldUtils.readField(this, FIELD_SEARCHABLE_LIST_DIALOG, true);
            if(oldD != null) {
                BaseSearchableListDialog newD = new BaseSearchableListDialog(this);
                newD.setArguments(oldD.getArguments());
                newD.setOnSearchableItemClickListener(this);
                FieldUtils.writeField(this, FIELD_SEARCHABLE_LIST_DIALOG, newD, true);
            }
        } catch (IllegalAccessException iaE){
            EMaxLogger.onException(TAG, iaE);
        }
    }

    private void initListenerOnCloseSearchView(SearchableListDialog instance) {
        try{
            SearchView sv = (SearchView) FieldUtils.readField(instance, FIELD_SEARCH_VIEW, true);
            if(sv != null){
                sv.addOnAttachStateChangeListener(this);
                mIsListenerAdded = true;
            }
        } catch (IllegalAccessException iaE){
            EMaxLogger.onException(TAG, iaE);
        }
    }

    private boolean checkIfListDialogNotAdded(){
        return !mIsListDialogAdded && scanForActivity(getContext()).getFragmentManager().findFragmentByTag(TAG_DIALOG_SEARCHABLE_LIST) == null;
    }

    private Activity scanForActivity(Context cont) {
        if (cont == null)
            return null;
        else if (cont instanceof Activity)
            return (Activity) cont;
        else if (cont instanceof ContextWrapper)
            return scanForActivity(((ContextWrapper) cont).getBaseContext());
        return null;
    }

    /** Private Classes  **/
    @SuppressLint("ValidFragment")
    public static class BaseSearchableListDialog extends SearchableListDialog {

        private BaseSearchableSpinner mOuter;

        private BaseSearchableListDialog(BaseSearchableSpinner bss){
            super();
            mOuter = bss;
        }

        /** Override SearchableListDialog Methods **/
        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            AlertDialog dialog = (AlertDialog) super.onCreateDialog(savedInstanceState);
            mOuter.initListenerOnCloseSearchView(this);
            return dialog;
        }

    }

}

尝试使用它,看看是否可行。

我也将适配器更改为具有自定义文本,并且并不总是显示对象的“ toString”:/我通常仅将toString用于调试目的,因此要显示有关对象的信息,我将使用特定方法。 / p>

这是适配器的类:

public abstract class BaseSearchableSpinnerAdapter<T> extends ArrayAdapter<CharSequence> {

    // Empty Item Label
    protected static final String LABEL_EMPTY_ITEM = "                                                                           ";
    // Label Length
    protected static final int LABEL_LENGTH = 50;
    // Spinner Adapter Positions
    public static final int POS_ITEM_NOT_FOUND = -0x1;
    public static final int POS_EMPTY_ITEM = 0x0;       // Not always true, depends if implemented

    protected List<T> mItems;
    private int mResLayout;

    public BaseSearchableSpinnerAdapter(@NonNull Context context, @LayoutRes int resource) {
        super(context, resource);
        mItems = new ArrayList<>();
        mResLayout = resource;
    }

    /** Abstract Methods **/
    public abstract <T extends CharSequence> T getLabelView(int pos);

    /** Override ArrayAdapter Methods **/
    @NonNull
    @Override
    public View getView(int position, View convertView, @NonNull ViewGroup parent) {
        if (convertView == null) {
            convertView = LayoutInflater.from(getContext()).inflate(mResLayout, parent, false);
            if (convertView == null) {
                convertView = LayoutInflater.from(getContext()).inflate(R.layout.spinner_default, parent, false);
            }
        }
        TextView tv = convertView.findViewById(R.id.text1);
        if(tv != null){
            tv.setText(getLabelView(position));
        }
        return convertView;
    }

    @Override
    public void clear(){
        mItems.clear();
        super.clear();
    }

    /** Public Methods **/
    public void addAll(List<T> objs){
        clear();
        ArrayList<CharSequence> labels = new ArrayList<>();
        if(objs != null && objs.size() > 0x0){
            mItems.addAll(objs);
            for(int i = 0x0; i < objs.size(); i++){
                labels.add(getLabelView(i));
            }
        }
        super.addAll(labels);
    }

    public T getMyItem(int pos){
        if(mItems != null && mItems.size() > pos && pos != -0x1){
            return mItems.get(pos);
        }
        return null;
    }

    public List<T> getMyItems(){
        return mItems;
    }

}

扩展此类并使用所需的对象。 LABEL_EMTPY_ITEM是一长串空格,因为在某些应用中,当文本没有占据列表视图中的所有行时,它将只能在文本上单击,而不能在所有行上单击。因此,当您没有任何项时,可单击部分该行的左侧是一小块(以我为例,我遇到了这个问题)。

扩展此基本Adapter类的示例:

public class MyObjectSearchableSpinnerAdapter extends BaseSearchableSpinnerAdapter<MyObject> {

    private @StringRes int mIdFstr;

    public MyObjectSearchableSpinnerAdapter(@NonNull Context context, @LayoutRes int resource){
        this(context, resource, R.string.fstr_two_fields_dash);
    }

    public MyObjectSearchableSpinnerAdapter(@NonNull Context context, @LayoutRes int resource, int idFstr){
        super(context, resource);
        mIdFstr = idFstr;
    }

    /** Override BaseSearchableSpinnerAdapter Methods **/
    @Override
    public <T extends CharSequence> T getLabelView(int pos) {
        MyObject item = mItems.get(pos);
        if(item != null){
            return (T) (!TextUtils.isEmpty(item.getName2()) ?
                            getContext().getString(mIdFstr, item.getName1(), item.getName2()) :
                            item.getName1());
        }
        return (T) LABEL_EMPTY_ITEM;
    }

    /** Public Methods **/
    public int getItemPosition(int idMyObject){
        return getItemPosition(String.valueOf(idMyObject));
    }

    public int getItemPosition(String idMyObject){
        if(mItems != null && mItems.size() > 0x0){
            for(int i = 0x0; i < mItems.size(); i++){
                MyObject item = mItems.get(i);
                if(item != null && idMyObject.equals(item.getId())){
                    return i;
                }
            }
        }
        return POS_ITEM_NOT_FOUND;
    }

}

示例Init BaseSearchableSpinner:

private void initBaseSearchableSpinnerMyObjects(){
        MyObjectSearchableSpinnerAdapter adapter = new MyObjectSearchableSpinnerAdapter(getContext(), R.layout.spinner_default);
        adapter.setDropDownViewResource(R.layout.spinner_default);
        mBaseSearchableSpinnerMyObjects.setAdapter(adapter);
    }

示例将您的MyObject列表添加到适配器:

((MyObjectSearchableSpinnerAdapter)mBaseSearchableSpinnerMyObjects.getAdapter()).addAll(items);

示例从BaseSearchableSpinner取回一个对象,该对象具有BaseSearchableAdapter的扩展名和MyObject列表:

MyObject obj = ((MyObjectSearchableSpinnerAdapter) mBaseSearchableSpinnerMyObjects.getAdapter()).getMyItem(mBaseSearchableSpinnerMyObjects.getSelectedItemPosition());

祝您编码愉快! bb