Spinner의 개폐 타이밍 제어

소개



최근, 안건으로 AndroidSpinner 클래스에 대해서 고리고리와 실장을 하고, 어느 정도 지견이 모였으므로 메모 쓰기도 포함해 하고 싶은 것과 그 실장예를 화상+텍스트 베이스로 설명을 해 보고 싶습니다.
(2019/02/25 시점에서는 개폐 타이밍만)

TL;DR


  • Spinner의 개폐 타이밍은 Spinner 클래스를 랩 할 필요가 있다. 표준에서는 불가능합니다
  • Spinner는 생각하는 것처럼 제어하기 어려우므로 사용할 때는 UI 등 세세한 사양이되지 않도록 조정해야합니다.

    Spinner의 개폐 타이밍 처리



    개폐 타이밍을 제어하려면 표준 Spinner에서는 실현할 수 없습니다. Spinner 클래스를 랩(엄밀하게는 AppCompatSpinner 클래스) 해, 다음의 소스 코드로 오리지날의 Spinner 클래스를 생성할 필요가 있습니다.

    사용 타이밍으로서는, 닫았을 때만(열 때만) 문자의 사이즈를 변경하고 싶은지 View의 화상 부분등을 비표시로 하고 싶은 등에 대응할 수 있습니다.

    소스 코드
    public class CustomSpinner extends android.support.v7.widget.AppCompatSpinner {
        public CustomSpinner(Context context) {
            super(context);
        }
    
        public CustomSpinner(Context context, int mode) {
            super(context, mode);
        }
    
        public CustomSpinner(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public CustomSpinner(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
        public CustomSpinner(Context context, AttributeSet attrs, int defStyleAttr, int mode) {
            super(context, attrs, defStyleAttr, mode);
        }
    
        public CustomSpinner(Context context, AttributeSet attrs, int defStyleAttr, int mode, Resources.Theme popupTheme) {
            super(context, attrs, defStyleAttr, mode, popupTheme);
        }
    
        /**
         * An interface which a client of this Spinner could use to receive
         * open/closed events for this Spinner.
         */
        public interface OnSpinnerEventsListener {
    
            /**
             * Callback triggered when the spinner was opened.
             */
            void onSpinnerOpened(Spinner spinner);
    
            /**
             * Callback triggered when the spinner was closed.
             */
            void onSpinnerClosed(Spinner spinner);
    
        }
    
        private OnSpinnerEventsListener mListener;
        private boolean mOpenInitiated = false;
    
        // implement the Spinner constructors that you need
    
        @Override
        public boolean performClick() {
            // register that the Spinner was opened so we have a status
            // indicator for when the container holding this Spinner may lose focus
            mOpenInitiated = true;
            if (mListener != null) {
                mListener.onSpinnerOpened(this);
            }
            return super.performClick();
        }
    
        @Override
        public void onWindowFocusChanged (boolean hasFocus) {
            if (hasBeenOpened() && hasFocus) {
                performClosedEvent();
            }
        }
    
        /**
         * Register the listener which will listen for events.
         */
        public void setSpinnerEventsListener(OnSpinnerEventsListener onSpinnerEventsListener) {
            mListener = onSpinnerEventsListener;
        }
    
        /**
         * Propagate the closed Spinner event to the listener from outside if needed.
         */
        public void performClosedEvent() {
            mOpenInitiated = false;
            if (mListener != null) {
                mListener.onSpinnerClosed(this);
            }
        }
    
        /**
         * A boolean flag indicating that the Spinner triggered an open event.
         *
         * @return true for opened Spinner
         */
        public boolean hasBeenOpened() {
            return mOpenInitiated;
        }
    }
    


    사용법
    CustomSpinner customSpinner = (CustomSpinner) findViewById(R.id.custom_spinner);
    // adapterの設定は省略しています
    customSpinner.setSpinnerEventsListener(new CustomSpinner.OnSpinnerEventsListener() {
        @Override
        public void onSpinnerOpened(Spinner spinner) {
            Log.v("opened!!");
        }
    
        @Override
        public void onSpinnerClosed(Spinner spinner) {
            Log.v("closed!!");
        }
    });
    


    주의점으로서는, AppCompatSpinner 클래스를 랩 하고 있으므로 표준의 Spinner 클래스와 같은 UI는 되지 않습니다. 레이아웃에 android:dropDownVerticalOffset="30dp" 를 추가하거나 customSpinner.setDropDownVerticalOffset(30) 를 설정하여 드롭다운 위치를 조정해야 합니다.

  • 좋은 웹페이지 즐겨찾기