【问题标题】:How to implement search with Spinner in Android?如何在 Android 中使用 Spinner 实现搜索?
【发布时间】:2016-09-14 05:48:16
【问题描述】:

Spinner 的代码如下:

String[] countryNames = {"Select Country", "India", "China", "Australia",   "Portugle", "America", "New Zealand"};

Spinner spinner = (Spinner) findViewById(R.id.simpleSpinner);
hintAdapter = new CustomArrayAdapter(getApplicationContext(), R.layout.simple_row,countriesList,getApplicationContext());
spinner.setAdapter(hintAdapter);

我想在Spinner中实现搜索。

我怎样才能做到这一点?

【问题讨论】:

  • 实现AutocompleteEditText
  • 使用android.widget.AutoCompleteTextView
  • 如果您不想要AutoCompleteTextView,请说明您想如何“搜索”您的Spinner
  • 我的列表最初显示在微调器中。我想在微调器顶部搜索

标签: android


【解决方案1】:

使用 SearchableSpinner Lib,有可用的 SearchableSpinner 库列表,只需选择一个更好的 https://github.com/search?utf8=%E2%9C%93&q=searchable+spinner

【讨论】:

  • 如何在这个小部件中执行类似搜索?...目前它的搜索类似于 .equals 内容。
【解决方案2】:

去 AutocompleteTextview this example will help you

【讨论】:

  • Preetika AutoComplete 是不同的场景。在 Spinner 列表中首先出现
  • 他的要求不是 AutocompleteTextview
  • 这只是一个建议,提出这个问题的人可以选择这个选项,你不能说这不是他的要求,他可能不知道这件事。 @brahmyadigopula
  • @PreetikaKaur 是的,你是对的,但他没有问其他可能的方法。所以必须根据问题给出答案......建议应该在 cmets 中提及。
【解决方案3】:

我找到了以下解决方案here

/**
* A modified Spinner that doesn't automatically select the first entry in the list.
*
* Shows the prompt if nothing is selected.
*
* Limitations: does not display prompt if the entry list is empty.
*/
public class NoDefaultSpinner extends Spinner {

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

public NoDefaultSpinner(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
}

@Override
public void setAdapter(SpinnerAdapter orig ) {
    final SpinnerAdapter adapter = newProxy(orig);

    super.setAdapter(adapter);

    try {
        final Method m = AdapterView.class.getDeclaredMethod(
                           "setNextSelectedPositionInt",int.class);
        m.setAccessible(true);
        m.invoke(this,-1);

        final Method n = AdapterView.class.getDeclaredMethod(
                           "setSelectedPositionInt",int.class);
        n.setAccessible(true);
        n.invoke(this,-1);
    } 
    catch( Exception e ) {
        throw new RuntimeException(e);
    }
}

protected SpinnerAdapter newProxy(SpinnerAdapter obj) {
    return (SpinnerAdapter) java.lang.reflect.Proxy.newProxyInstance(
            obj.getClass().getClassLoader(),
            new Class[]{SpinnerAdapter.class},
            new SpinnerAdapterProxy(obj));
}



/**
 * Intercepts getView() to display the prompt if position < 0
 */
protected class SpinnerAdapterProxy implements InvocationHandler {

    protected SpinnerAdapter obj;
    protected Method getView;


    protected SpinnerAdapterProxy(SpinnerAdapter obj) {
        this.obj = obj;
        try {
            this.getView = SpinnerAdapter.class.getMethod(
                             "getView",int.class,View.class,ViewGroup.class);
        } 
        catch( Exception e ) {
            throw new RuntimeException(e);
        }
    }

    public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
        try {
            return m.equals(getView) && 
                   (Integer)(args[0])<0 ? 
                     getView((Integer)args[0],(View)args[1],(ViewGroup)args[2]) : 
                     m.invoke(obj, args);
        } 
        catch (InvocationTargetException e) {
            throw e.getTargetException();
        } 
        catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    protected View getView(int position, View convertView, ViewGroup parent) 
      throws IllegalAccessException {

        if( position<0 ) {
            final TextView v = 
              (TextView) ((LayoutInflater)getContext().getSystemService(
                Context.LAYOUT_INFLATER_SERVICE)).inflate(
                  android.R.layout.simple_spinner_item,parent,false);
            v.setText(getPrompt());
            return v;
        }
        return obj.getView(position,convertView,parent);
    }
}
}

【讨论】:

    【解决方案4】:

    在尝试了很多库和方法之后,我终于创建了我的自定义可搜索微调器。我附加的代码处于非常初级的级别,我将像在我的项目中那样更新它。我也在写完整的使用方法。

    所有布局 searchable_spinner.xml

    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">
        <EditText
            android:id="@+id/spinner_search_bar"
            android:layout_width="match_parent"
            android:layout_height="35dp"
            android:hint="Select A Company"
            android:cursorVisible="false"
            android:background="@drawable/white_rect_fillet_border"
            android:paddingHorizontal="10dp"/>
        
        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/ledger_list"
            android:layout_width="match_parent"
            android:layout_height="300dp"
            android:visibility="gone"
            android:layout_marginHorizontal="10dp"/>
    </LinearLayout>
    </FrameLayout>
    

    actity_or_frag_layout.xml记得把它放在最后,并根据你的父布局对齐。

    <FrameLayout
        android:id="@+id/spinner_frame"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginHorizontal="10dp"
        android:layout_marginTop="10dp"
        android:background="@drawable/white_rect_fillet_border"
        app:layout_constraintTop_toTopOf="parent">
    
        <include layout="@layout/searchable_spinner" />
    </FrameLayout>
    

    list_adapter_element.xml

    <?xml version="1.0" encoding="utf-8"?>
    <TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    <TableRow>
        <TextView
            android:id="@+id/txt"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingVertical=5dp"
            android:gravity="center_vertical"/>
    </TableRow>
    </TableLayout>
    

    所有可绘制对象 white_rect_fillet_border.xml

    <?xml version="1.0" encoding="utf-8"?>
    <shape android:shape="rectangle"
        xmlns:android="http://schemas.android.com/apk/res/android">
        <solid android:color="@android:color/white"/>
        <corners android:radius="5dp" />
        <stroke android:color="@android:color/darker_gray"
            android:width="1dp" />
    </shape>
    

    CustomListAdapter.java

    public class CustomListAdapter extends 
    RecyclerView.Adapter<CustomListAdapter.ViewHolder> {
    private final Activity context;
    private Fragment fragment;
    private ArrayList<LedgerListObject> ledgerlist; //replace LedgerListObject with your object or simply String everywhere in this code.
    
    public CustomListAdapter(Activity context, Fragment fragment, 
    ArrayList<LedgerListObject> ledgerlist) {
        this.context = context;
        this.fragment = fragment;
        this.ledgerlist = ledgerlist;
    }
    
    
    public void updateList(ArrayList<LedgerListObject> newList){
        ledgerlist = newList;
        notifyDataSetChanged();
    }
    
    @NonNull
    @Override
    public CustomListAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        LayoutInflater inflater = context.getLayoutInflater();
        View rowView= inflater.inflate(R.layout.list_adapter_element, null, true);
        return new ViewHolder(rowView);
    }
    
    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, final int position) {
        holder.txtTitle.setText(ledgerlist.get(position).LedgerName);
        holder.txtTitle.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                MyFragment.LedgerID = ledgerlist.get(position).LedgerID;  //MyFragment can be replaced with the name of your activity or fragment 
                MyFragment.ledgerListView.setVisibility(View.GONE);
                MyFragment.spinnerSearch.setText(ledgerlist.get(position).LedgerName);
                MyFragment.spinnerSearch.setCursorVisible(false);
            }
        });
    }
    
    
    @Override
    public int getItemCount() {
        return ledgerlist.size();
    }
    
    class ViewHolder extends RecyclerView.ViewHolder {
    
        TextView txtTitle;
        ViewHolder(@NonNull View itemView) {
            super(itemView);
            txtTitle = (TextView) itemView.findViewById(R.id.txt);
        }
    }
    }
    

    MyFragment.java

    public class MyFragment extends Fragment{
    ArrayList<LedgerListObject> ledgerlist = new ArrayList<LedgerListObject>();
    public static int LedgerID = 0;
    CustomListAdapter ledgerAdapter;
    
    FrameLayout spinnerFrame;
    public static EditText spinnerSearch;
    public static RecyclerView ledgerListView;
    
     @SuppressLint("ClickableViewAccessibility")
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState){
        View root = inflater.inflate(R.layout.fragment_ledger, container, false);
        super.onCreate(savedInstanceState);
        spinnerFrame = root.findViewById(R.id.spinner_frame);
        spinnerSearch = root.findViewById(R.id.spinner_search_bar);
        ledgerListView = root.findViewById(R.id.ledger_list);
        spinnerSearch.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                ledgerListView.setVisibility(View.VISIBLE);
                spinnerSearch.setCursorVisible(true);
                return false;
            }
        });
    
        spinnerSearch.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) 
    {
    
            }
    
            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
    
            }
    
            @Override
            public void afterTextChanged(Editable s) {
                try{
                    filter(s.toString());
                }catch (Exception e){e.printStackTrace();}
            }
        });
    
        GridLayoutManager listgridLayoutManager = new GridLayoutManager(getContext(), 1, 
        RecyclerView.VERTICAL, false);
        ledgerListView.setLayoutManager(listgridLayoutManager);
    
        //todo: your method of adding objects to your ledgerlist
    
        ledgerAdapter = new CustomListAdapter(getActivity(), LedgerFragment.this, ledgerlist);
                ledgerListView.setAdapter(ledgerAdapter);
        return root;
    }
    }
    

    尝试一下,如果有任何问题,请随时询问,我会解决它

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-07-28
      • 1970-01-01
      • 1970-01-01
      • 2017-01-19
      • 1970-01-01
      • 1970-01-01
      • 2012-08-08
      • 1970-01-01
      相关资源
      最近更新 更多