프로그래밍 언어/Android

초기 텍스트가 "Select One"인 Android Spinner를 만드는 방법

Rateye 2021. 9. 8. 10:22
728x90
반응형
질문 : 초기 텍스트가 "Select One"인 Android Spinner를 만드는 방법은 무엇입니까?

처음에 (사용자가 아직 선택하지 않은 경우) "하나 선택"이라는 텍스트를 표시하는 Spinner를 사용하고 싶습니다. 사용자가 스피너를 클릭하면 항목 목록이 표시되고 사용자가 옵션 중 하나를 선택합니다. 사용자가 선택하면 선택한 항목이 "하나 선택"대신 Spinner에 표시됩니다.

Spinner를 만들려면 다음 코드가 있습니다.

String[] items = new String[] {"One", "Two", "Three"};
Spinner spinner = (Spinner) findViewById(R.id.mySpinner);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
            android.R.layout.simple_spinner_item, items);
            adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
            spinner.setAdapter(adapter);
            

이 코드를 사용하면 처음에 "One"항목이 표시됩니다. 항목에 "하나 선택"이라는 새 항목을 추가 할 수 있지만 드롭 다운 목록에 "하나 선택"도 첫 번째 항목으로 표시됩니다.

이 문제를 어떻게 해결할 수 있습니까?

답변

Spinner 보기를 재정의하는 일반적인 솔루션은 다음과 같습니다. setAdapter() 를 재정 의하여 초기 위치를 -1로 설정하고 제공된 SpinnerAdapter 를 프록시하여 0보다 작은 위치에 대한 프롬프트 문자열을 표시합니다.

이것은 Android 1.5 ~ 4.2에서 테스트되었지만 구매자는주의하십시오! 이 솔루션은 리플렉션을 사용하여 개인 AdapterView.setNextSelectedPositionInt()AdapterView.setSelectedPositionInt() 를 호출하기 때문에 향후 OS 업데이트에서 작동하지 않을 수도 있습니다. 그렇게 될 것 같지만 결코 보장되지는 않습니다.

일반적으로 나는 이와 같은 것을 용납하지 않을 것이지만,이 질문은 충분한 횟수의 질문을 받았으며 내 솔루션을 게시 할 것이라고 생각할만큼 합당한 요청처럼 보입니다.

/**
 * 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);
        }
    }
}
출처 : https://stackoverflow.com/questions/867518/how-to-make-an-android-spinner-with-initial-text-select-one
728x90
반응형