Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * Copyright (C) 2006 The Android Open Source Project
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 package com.actionbarsherlock.internal.widget;
 
An abstract base class for spinner widgets. SDK users will probably not need to use this class.

Attr:
ref android.R.styleable#AbsSpinner_entries
 
 public abstract class IcsAbsSpinner extends IcsAdapterView<SpinnerAdapter> {
     private static final boolean IS_HONEYCOMB = .. >= ..;
 
 
     int mHeightMeasureSpec;
     int mWidthMeasureSpec;
     boolean mBlockLayoutRequests;
 
     int mSelectionLeftPadding = 0;
     int mSelectionTopPadding = 0;
     int mSelectionRightPadding = 0;
     int mSelectionBottomPadding = 0;
     final Rect mSpinnerPadding = new Rect();
 
     final RecycleBin mRecycler = new RecycleBin();
     private DataSetObserver mDataSetObserver;

    
Temporary frame to hold a child View's frame rectangle
 
     private Rect mTouchFrame;
 
     public IcsAbsSpinner(Context context) {
         super(context);
         initAbsSpinner();
     }
 
     public IcsAbsSpinner(Context contextAttributeSet attrs) {
         this(contextattrs, 0);
     }
 
     public IcsAbsSpinner(Context contextAttributeSet attrsint defStyle) {
         super(contextattrsdefStyle);
         initAbsSpinner();
 
         /*
         TypedArray a = context.obtainStyledAttributes(attrs,
                 com.android.internal.R.styleable.AbsSpinner, defStyle, 0);
 
         CharSequence[] entries = a.getTextArray(R.styleable.AbsSpinner_entries);
         if (entries != null) {
             ArrayAdapter<CharSequence> adapter =
                     new ArrayAdapter<CharSequence>(context,
                             R.layout.simple_spinner_item, entries);
             adapter.setDropDownViewResource(R.layout.simple_spinner_dropdown_item);
             setAdapter(adapter);
         }
 
         a.recycle();
         */
     }

    
Common code for different constructor flavors
 
     private void initAbsSpinner() {
         setFocusable(true);
         setWillNotDraw(false);
     }

    
The Adapter is used to provide the data which backs this Spinner. It also provides methods to transform spinner items based on their position relative to the selected item.

Parameters:
adapter The SpinnerAdapter to use for this Spinner
    @Override
    public void setAdapter(SpinnerAdapter adapter) {
        if (null != ) {
            resetList();
        }
         = adapter;
        if ( != null) {
             = ;
             = .getCount();
            checkFocus();
             = new AdapterDataSetObserver();
            int position =  > 0 ? 0 : ;
            setSelectedPositionInt(position);
            setNextSelectedPositionInt(position);
            if ( == 0) {
                // Nothing selected
                checkSelectionChanged();
            }
        } else {
            checkFocus();
            resetList();
            // Nothing selected
            checkSelectionChanged();
        }
        requestLayout();
    }

    
Clear out all children from the list
    void resetList() {
         = false;
         = false;
        removeAllViewsInLayout();
        invalidate();
    }

    

See also:
android.view.View.measure(int,int) Figure out the dimensions of this Spinner. The width comes from the widthMeasureSpec as Spinnners can't have their width set to UNSPECIFIED. The height is based on the height of the selected item plus padding.
    @Override
    protected void onMeasure(int widthMeasureSpecint heightMeasureSpec) {
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSize;
        int heightSize;
        final int mPaddingLeft = getPaddingLeft();
        final int mPaddingTop = getPaddingTop();
        final int mPaddingRight = getPaddingRight();
        final int mPaddingBottom = getPaddingBottom();
        . = mPaddingLeft >  ? mPaddingLeft
                : ;
        . = mPaddingTop >  ? mPaddingTop
                : ;
        . = mPaddingRight >  ? mPaddingRight
                : ;
        . = mPaddingBottom >  ? mPaddingBottom
                : ;
        if () {
            handleDataChanged();
        }
        int preferredHeight = 0;
        int preferredWidth = 0;
        boolean needsMeasuring = true;
        int selectedPosition = getSelectedItemPosition();
        if (selectedPosition >= 0 &&  != null && selectedPosition < .getCount()) {
            // Try looking in the recycler. (Maybe we were measured once already)
            View view = .get(selectedPosition);
            if (view == null) {
                // Make a new one
                view = .getView(selectedPositionnullthis);
            }
            if (view != null) {
                // Put in recycler for re-measuring and/or layout
                .put(selectedPositionview);
            }
            if (view != null) {
                if (view.getLayoutParams() == null) {
                     = true;
                    view.setLayoutParams(generateDefaultLayoutParams());
                     = false;
                }
                measureChild(viewwidthMeasureSpecheightMeasureSpec);
                preferredHeight = getChildHeight(view) + . + .;
                preferredWidth = getChildWidth(view) + . + .;
                needsMeasuring = false;
            }
        }
        if (needsMeasuring) {
            // No views -- just use padding
            preferredHeight = . + .;
            if (widthMode == .) {
                preferredWidth = . + .;
            }
        }
        preferredHeight = Math.max(preferredHeightgetSuggestedMinimumHeight());
        preferredWidth = Math.max(preferredWidthgetSuggestedMinimumWidth());
        if () {
            heightSize = resolveSizeAndState(preferredHeightheightMeasureSpec, 0);
            widthSize = resolveSizeAndState(preferredWidthwidthMeasureSpec, 0);
        } else {
            heightSize = resolveSize(preferredHeightheightMeasureSpec);
            widthSize = resolveSize(preferredWidthwidthMeasureSpec);
        }
        setMeasuredDimension(widthSizeheightSize);
         = heightMeasureSpec;
         = widthMeasureSpec;
    }
    int getChildHeight(View child) {
        return child.getMeasuredHeight();
    }
    int getChildWidth(View child) {
        return child.getMeasuredWidth();
    }
    @Override
        return new ViewGroup.LayoutParams(
                ..,
                ..);
    }
    void recycleAllViews() {
        final int childCount = getChildCount();
        final IcsAbsSpinner.RecycleBin recycleBin = ;
        final int position = ;
        // All views go in recycler
        for (int i = 0; i < childCounti++) {
            View v = getChildAt(i);
            int index = position + i;
            recycleBin.put(indexv);
        }
    }

    
Jump directly to a specific item in the adapter data.
    public void setSelection(int positionboolean animate) {
        // Animate only if requested position is already on screen somewhere
        boolean shouldAnimate = animate &&  <= position &&
                position <=  + getChildCount() - 1;
        setSelectionInt(positionshouldAnimate);
    }
    @Override
    public void setSelection(int position) {
        setNextSelectedPositionInt(position);
        requestLayout();
        invalidate();
    }


    
Makes the item at the supplied position selected.

Parameters:
position Position to select
animate Should the transition be animated
    void setSelectionInt(int positionboolean animate) {
        if (position != ) {
             = true;
            int delta  = position - ;
            setNextSelectedPositionInt(position);
            layout(deltaanimate);
             = false;
        }
    }
    abstract void layout(int deltaboolean animate);
    @Override
    public View getSelectedView() {
        if ( > 0 &&  >= 0) {
            return getChildAt( - );
        } else {
            return null;
        }
    }

    
Override to prevent spamming ourselves with layout requests as we place views

    @Override
    public void requestLayout() {
        if (!) {
            super.requestLayout();
        }
    }
    @Override
    public SpinnerAdapter getAdapter() {
        return ;
    }
    @Override
    public int getCount() {
        return ;
    }

    
Maps a point to a position in the list.

Parameters:
x X in local coordinate
y Y in local coordinate
Returns:
The position of the item which contains the specified point, or IcsAdapterView.INVALID_POSITION if the point does not intersect an item.
    public int pointToPosition(int xint y) {
        Rect frame = ;
        if (frame == null) {
             = new Rect();
            frame = ;
        }
        final int count = getChildCount();
        for (int i = count - 1; i >= 0; i--) {
            View child = getChildAt(i);
            if (child.getVisibility() == .) {
                child.getHitRect(frame);
                if (frame.contains(xy)) {
                    return  + i;
                }
            }
        }
        return ;
    }
    static class SavedState extends BaseSavedState {
        long selectedId;
        int position;

        
Constructor called from AbsSpinner#onSaveInstanceState()
        SavedState(Parcelable superState) {
            super(superState);
        }

        
Constructor called from CREATOR
        private SavedState(Parcel in) {
            super(in);
             = in.readLong();
             = in.readInt();
        }
        @Override
        public void writeToParcel(Parcel outint flags) {
            super.writeToParcel(outflags);
            out.writeLong();
            out.writeInt();
        }
        @Override
        public String toString() {
            return "AbsSpinner.SavedState{"
                    + Integer.toHexString(System.identityHashCode(this))
                    + " selectedId=" + 
                    + " position=" +  + "}";
        }
        public static final Parcelable.Creator<SavedStateCREATOR
                = new Parcelable.Creator<SavedState>() {
            public SavedState createFromParcel(Parcel in) {
                return new SavedState(in);
            }
            public SavedState[] newArray(int size) {
                return new SavedState[size];
            }
        };
    }
    @Override
    public Parcelable onSaveInstanceState() {
        Parcelable superState = super.onSaveInstanceState();
        SavedState ss = new SavedState(superState);
        ss.selectedId = getSelectedItemId();
        if (ss.selectedId >= 0) {
            ss.position = getSelectedItemPosition();
        } else {
            ss.position = ;
        }
        return ss;
    }
    @Override
    public void onRestoreInstanceState(Parcelable state) {
        SavedState ss = (SavedStatestate;
        super.onRestoreInstanceState(ss.getSuperState());
        if (ss.selectedId >= 0) {
             = true;
             = true;
             = ss.selectedId;
             = ss.position;
             = ;
            requestLayout();
        }
    }
    class RecycleBin {
        private final SparseArray<ViewmScrapHeap = new SparseArray<View>();
        public void put(int positionView v) {
            .put(positionv);
        }
        View get(int position) {
            // System.out.print("Looking for " + position);
            View result = .get(position);
            if (result != null) {
                // System.out.println(" HIT");
                .delete(position);
            } else {
                // System.out.println(" MISS");
            }
            return result;
        }
        void clear() {
            final SparseArray<ViewscrapHeap = ;
            final int count = scrapHeap.size();
            for (int i = 0; i < counti++) {
                final View view = scrapHeap.valueAt(i);
                if (view != null) {
                    removeDetachedView(viewtrue);
                }
            }
            scrapHeap.clear();
        }
    }