FileDocCategorySizeDatePackage
AbsSpinner.javaAPI DocAndroid 1.5 API15199Wed May 06 22:41:56 BST 2009android.widget

AbsSpinner

public abstract class AbsSpinner extends AdapterView
An abstract base class for spinner widgets. SDK users will probably not need to use this class.
attr
ref android.R.styleable#AbsSpinner_entries

Fields Summary
SpinnerAdapter
mAdapter
int
mHeightMeasureSpec
int
mWidthMeasureSpec
boolean
mBlockLayoutRequests
int
mSelectionLeftPadding
int
mSelectionTopPadding
int
mSelectionRightPadding
int
mSelectionBottomPadding
android.graphics.Rect
mSpinnerPadding
android.view.View
mSelectedView
android.view.animation.Interpolator
mInterpolator
RecycleBin
mRecycler
private android.database.DataSetObserver
mDataSetObserver
private android.graphics.Rect
mTouchFrame
Temporary frame to hold a child View's frame rectangle
Constructors Summary
public AbsSpinner(android.content.Context context)


       
        super(context);
        initAbsSpinner();
    
public AbsSpinner(android.content.Context context, android.util.AttributeSet attrs)

        this(context, attrs, 0);
    
public AbsSpinner(android.content.Context context, android.util.AttributeSet attrs, int defStyle)

        super(context, attrs, defStyle);
        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();
    
Methods Summary
protected ViewGroup.LayoutParamsgenerateDefaultLayoutParams()

        return new ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.FILL_PARENT,
                ViewGroup.LayoutParams.WRAP_CONTENT);
    
public SpinnerAdaptergetAdapter()

        return mAdapter;
    
intgetChildHeight(android.view.View child)

        return child.getMeasuredHeight();
    
intgetChildWidth(android.view.View child)

        return child.getMeasuredWidth();
    
public intgetCount()

        return mItemCount;
    
public android.view.ViewgetSelectedView()

        if (mItemCount > 0 && mSelectedPosition >= 0) {
            return getChildAt(mSelectedPosition - mFirstPosition);
        } else {
            return null;
        }
    
voidhandleDataChanged()

        // FIXME -- this is called from both measure and layout.
        // This is harmless right now, but we don't want to do redundant work if
        // this gets more complicated
       super.handleDataChanged();
    
private voidinitAbsSpinner()
Common code for different constructor flavors

        setFocusable(true);
        setWillNotDraw(false);
    
abstract voidlayout(int delta, boolean animate)

protected voidonMeasure(int widthMeasureSpec, int heightMeasureSpec)

see
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.

        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSize;
        int heightSize;

        mSpinnerPadding.left = mPaddingLeft > mSelectionLeftPadding ? mPaddingLeft
                : mSelectionLeftPadding;
        mSpinnerPadding.top = mPaddingTop > mSelectionTopPadding ? mPaddingTop
                : mSelectionTopPadding;
        mSpinnerPadding.right = mPaddingRight > mSelectionRightPadding ? mPaddingRight
                : mSelectionRightPadding;
        mSpinnerPadding.bottom = mPaddingBottom > mSelectionBottomPadding ? mPaddingBottom
                : mSelectionBottomPadding;

        if (mDataChanged) {
            handleDataChanged();
        }
        
        int preferredHeight = 0;
        int preferredWidth = 0;
        boolean needsMeasuring = true;
        
        int selectedPosition = getSelectedItemPosition();
        if (selectedPosition >= 0 && mAdapter != null) {
            // Try looking in the recycler. (Maybe we were measured once already)
            View view = mRecycler.get(selectedPosition);
            if (view == null) {
                // Make a new one
                view = mAdapter.getView(selectedPosition, null, this);
            }

            if (view != null) {
                // Put in recycler for re-measuring and/or layout
                mRecycler.put(selectedPosition, view);
            }

            if (view != null) {
                if (view.getLayoutParams() == null) {
                    mBlockLayoutRequests = true;
                    view.setLayoutParams(generateDefaultLayoutParams());
                    mBlockLayoutRequests = false;
                }
                measureChild(view, widthMeasureSpec, heightMeasureSpec);
                
                preferredHeight = getChildHeight(view) + mSpinnerPadding.top + mSpinnerPadding.bottom;
                preferredWidth = getChildWidth(view) + mSpinnerPadding.left + mSpinnerPadding.right;
                
                needsMeasuring = false;
            }
        }
        
        if (needsMeasuring) {
            // No views -- just use padding
            preferredHeight = mSpinnerPadding.top + mSpinnerPadding.bottom;
            if (widthMode == MeasureSpec.UNSPECIFIED) {
                preferredWidth = mSpinnerPadding.left + mSpinnerPadding.right;
            }
        }

        preferredHeight = Math.max(preferredHeight, getSuggestedMinimumHeight());
        preferredWidth = Math.max(preferredWidth, getSuggestedMinimumWidth());

        heightSize = resolveSize(preferredHeight, heightMeasureSpec);
        widthSize = resolveSize(preferredWidth, widthMeasureSpec);

        setMeasuredDimension(widthSize, heightSize);
        mHeightMeasureSpec = heightMeasureSpec;
        mWidthMeasureSpec = widthMeasureSpec;
    
public voidonRestoreInstanceState(android.os.Parcelable state)

        SavedState ss = (SavedState) state;
  
        super.onRestoreInstanceState(ss.getSuperState());

        if (ss.selectedId >= 0) {
            mDataChanged = true;
            mNeedSync = true;
            mSyncRowId = ss.selectedId;
            mSyncPosition = ss.position;
            mSyncMode = SYNC_SELECTED_POSITION;
            requestLayout();
        }
    
public android.os.ParcelableonSaveInstanceState()

    

    
       
        Parcelable superState = super.onSaveInstanceState();
        SavedState ss = new SavedState(superState);
        ss.selectedId = getSelectedItemId();
        if (ss.selectedId >= 0) {
            ss.position = getSelectedItemPosition();
        } else {
            ss.position = INVALID_POSITION;
        }
        return ss;
    
public intpointToPosition(int x, int y)
Maps a point to a position in the list.

param
x X in local coordinate
param
y Y in local coordinate
return
The position of the item which contains the specified point, or {@link #INVALID_POSITION} if the point does not intersect an item.

        Rect frame = mTouchFrame;
        if (frame == null) {
            mTouchFrame = new Rect();
            frame = mTouchFrame;
        }

        final int count = getChildCount();
        for (int i = count - 1; i >= 0; i--) {
            View child = getChildAt(i);
            if (child.getVisibility() == View.VISIBLE) {
                child.getHitRect(frame);
                if (frame.contains(x, y)) {
                    return mFirstPosition + i;
                }
            }
        } 
        return INVALID_POSITION;
    
voidrecycleAllViews()

        int childCount = getChildCount();
        final AbsSpinner.RecycleBin recycleBin = mRecycler;

        // All views go in recycler
        for (int i=0; i<childCount; i++) {
            View v = getChildAt(i);
            int index = mFirstPosition + i;
            recycleBin.put(index, v);
        }  
    
public voidrequestLayout()
Override to prevent spamming ourselves with layout requests as we place views

see
android.view.View#requestLayout()

        if (!mBlockLayoutRequests) {
            super.requestLayout();
        }
    
voidresetList()
Clear out all children from the list

        mDataChanged = false;
        mNeedSync = false;
        
        removeAllViewsInLayout();
        mOldSelectedPosition = INVALID_POSITION;
        mOldSelectedRowId = INVALID_ROW_ID;
        
        setSelectedPositionInt(INVALID_POSITION);
        setNextSelectedPositionInt(INVALID_POSITION);
        invalidate();
    
public voidsetAdapter(SpinnerAdapter adapter)
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.

param
adapter The SpinnerAdapter to use for this Spinner

        if (null != mAdapter) {
            mAdapter.unregisterDataSetObserver(mDataSetObserver);
            resetList();
        }
        
        mAdapter = adapter;
        
        mOldSelectedPosition = INVALID_POSITION;
        mOldSelectedRowId = INVALID_ROW_ID;
        
        if (mAdapter != null) {
            mOldItemCount = mItemCount;
            mItemCount = mAdapter.getCount();
            checkFocus();

            mDataSetObserver = new AdapterDataSetObserver();
            mAdapter.registerDataSetObserver(mDataSetObserver);

            int position = mItemCount > 0 ? 0 : INVALID_POSITION;

            setSelectedPositionInt(position);
            setNextSelectedPositionInt(position);
            
            if (mItemCount == 0) {
                // Nothing selected
                checkSelectionChanged();
            }
            
        } else {
            checkFocus();            
            resetList();
            // Nothing selected
            checkSelectionChanged();
        }

        requestLayout();
    
public voidsetSelection(int position, boolean animate)
Jump directly to a specific item in the adapter data.

        // Animate only if requested position is already on screen somewhere
        boolean shouldAnimate = animate && mFirstPosition <= position &&
                position <= mFirstPosition + getChildCount() - 1;
        setSelectionInt(position, shouldAnimate);
    
public voidsetSelection(int position)

        setNextSelectedPositionInt(position);
        requestLayout();
        invalidate();
    
voidsetSelectionInt(int position, boolean animate)
Makes the item at the supplied position selected.

param
position Position to select
param
animate Should the transition be animated

        if (position != mOldSelectedPosition) {
            mBlockLayoutRequests = true;
            int delta  = position - mSelectedPosition;
            setNextSelectedPositionInt(position);
            layout(delta, animate);
            mBlockLayoutRequests = false;
        }