Loading api/current.xml +103 −0 Original line number Diff line number Diff line Loading @@ -4189,6 +4189,17 @@ visibility="public" > </field> <field name="fastScrollAlwaysVisible" type="int" transient="false" volatile="false" value="16843588" static="true" final="true" deprecated="not deprecated" visibility="public" > </field> <field name="fastScrollEnabled" type="int" transient="false" Loading Loading @@ -10371,6 +10382,17 @@ visibility="public" > </field> <field name="verticalScrollbarPosition" type="int" transient="false" volatile="false" value="16843587" static="true" final="true" deprecated="not deprecated" visibility="public" > </field> <field name="verticalSpacing" type="int" transient="false" Loading Loading @@ -206780,6 +206802,17 @@ visibility="public" > </method> <method name="getVerticalScrollbarPosition" return="int" abstract="false" native="false" synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > </method> <method name="getVerticalScrollbarWidth" return="int" abstract="false" Loading Loading @@ -209227,6 +209260,19 @@ <parameter name="verticalScrollBarEnabled" type="boolean"> </parameter> </method> <method name="setVerticalScrollbarPosition" return="void" abstract="false" native="false" synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > <parameter name="position" type="int"> </parameter> </method> <method name="setVisibility" return="void" abstract="false" Loading Loading @@ -210016,6 +210062,39 @@ visibility="public" > </field> <field name="SCROLLBAR_POSITION_DEFAULT" type="int" transient="false" volatile="false" value="0" static="true" final="true" deprecated="not deprecated" visibility="public" > </field> <field name="SCROLLBAR_POSITION_LEFT" type="int" transient="false" volatile="false" value="1" static="true" final="true" deprecated="not deprecated" visibility="public" > </field> <field name="SCROLLBAR_POSITION_RIGHT" type="int" transient="false" volatile="false" value="2" static="true" final="true" deprecated="not deprecated" visibility="public" > </field> <field name="SELECTED_STATE_SET" type="int[]" transient="false" Loading Loading @@ -228926,6 +229005,17 @@ visibility="public" > </method> <method name="isFastScrollAlwaysVisible" return="boolean" abstract="false" native="false" synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > </method> <method name="isFastScrollEnabled" return="boolean" abstract="false" Loading Loading @@ -229213,6 +229303,19 @@ <parameter name="onTop" type="boolean"> </parameter> </method> <method name="setFastScrollAlwaysVisible" return="void" abstract="false" native="false" synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > <parameter name="alwaysShow" type="boolean"> </parameter> </method> <method name="setFastScrollEnabled" return="void" abstract="false" core/java/android/view/View.java +84 −8 Original line number Diff line number Diff line Loading @@ -1966,6 +1966,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility @ViewDebug.ExportedProperty(category = "padding") int mUserPaddingBottom; /** * Cache the paddingLeft set by the user to append to the scrollbar's size. */ @ViewDebug.ExportedProperty(category = "padding") int mUserPaddingLeft; /** * @hide */ Loading Loading @@ -2116,6 +2122,26 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility */ boolean mCanAcceptDrop; /** * Position of the vertical scroll bar. */ private int mVerticalScrollbarPosition; /** * Position the scroll bar at the default position as determined by the system. */ public static final int SCROLLBAR_POSITION_DEFAULT = 0; /** * Position the scroll bar along the left edge. */ public static final int SCROLLBAR_POSITION_LEFT = 1; /** * Position the scroll bar along the right edge. */ public static final int SCROLLBAR_POSITION_RIGHT = 2; /** * Simple constructor to use when creating a view from code. * Loading Loading @@ -2448,6 +2474,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility case R.styleable.View_overScrollMode: overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS); break; case R.styleable.View_verticalScrollbarPosition: mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT); break; } } Loading Loading @@ -2707,6 +2736,29 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility } } /** * Set the position of the vertical scroll bar. Should be one of * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or * {@link #SCROLLBAR_POSITION_RIGHT}. * * @param position Where the vertical scroll bar should be positioned. */ public void setVerticalScrollbarPosition(int position) { if (mVerticalScrollbarPosition != position) { mVerticalScrollbarPosition = position; computeOpaqueFlags(); recomputePadding(); } } /** * @return The position where the vertical scroll bar will show, if applicable. * @see #setVerticalScrollbarPosition(int) */ public int getVerticalScrollbarPosition() { return mVerticalScrollbarPosition; } /** * Register a callback to be invoked when focus of this view changed. * Loading Loading @@ -6542,7 +6594,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility (mAlpha >= 1.0f - ViewConfiguration.ALPHA_THRESHOLD); } private void computeOpaqueFlags() { /** * @hide */ protected void computeOpaqueFlags() { // Opaque if: // - Has a background // - Background is opaque Loading Loading @@ -6929,8 +6984,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility } } private void recomputePadding() { setPadding(mPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom); /** * @hide */ protected void recomputePadding() { setPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom); } /** Loading Loading @@ -7213,8 +7271,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility scrollBar.setParameters(computeVerticalScrollRange(), computeVerticalScrollOffset(), computeVerticalScrollExtent(), true); // TODO: Deal with RTL languages to position scrollbar on left switch (mVerticalScrollbarPosition) { default: case SCROLLBAR_POSITION_DEFAULT: case SCROLLBAR_POSITION_RIGHT: left = scrollX + width - size - (mUserPaddingRight & inside); break; case SCROLLBAR_POSITION_LEFT: left = scrollX + (mUserPaddingLeft & inside); break; } top = scrollY + (mPaddingTop & inside); right = left + size; bottom = scrollY + height - (mUserPaddingBottom & inside); Loading Loading @@ -9003,6 +9069,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility public void setPadding(int left, int top, int right, int bottom) { boolean changed = false; mUserPaddingLeft = left; mUserPaddingRight = right; mUserPaddingBottom = bottom; Loading @@ -9010,12 +9077,21 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility // Common case is there are no scroll bars. if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) { // TODO: Deal with RTL languages to adjust left padding instead of right. if ((viewFlags & SCROLLBARS_VERTICAL) != 0) { right += (viewFlags & SCROLLBARS_INSET_MASK) == 0 // TODO Determine what to do with SCROLLBAR_POSITION_DEFAULT based on RTL settings. final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0 ? 0 : getVerticalScrollbarWidth(); switch (mVerticalScrollbarPosition) { case SCROLLBAR_POSITION_DEFAULT: case SCROLLBAR_POSITION_RIGHT: right += offset; break; case SCROLLBAR_POSITION_LEFT: left += offset; break; } } if ((viewFlags & SCROLLBARS_HORIZONTAL) == 0) { if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) { bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0 ? 0 : getHorizontalScrollbarHeight(); } Loading core/java/android/widget/AbsListView.java +78 −0 Original line number Diff line number Diff line Loading @@ -744,6 +744,8 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } setChoiceMode(a.getInt(R.styleable.AbsListView_choiceMode, CHOICE_MODE_NONE)); setFastScrollAlwaysVisible( a.getBoolean(R.styleable.AbsListView_fastScrollAlwaysVisible, false)); a.recycle(); } Loading Loading @@ -1128,6 +1130,49 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } } /** * Set whether or not the fast scroller should always be shown in place of the * standard scrollbars. Fast scrollers shown in this way will not fade out and will * be a permanent fixture within the list. Best combined with an inset scroll bar style * that will ensure enough padding. This will enable fast scrolling if it is not * already enabled. * * @param alwaysShow true if the fast scroller should always be displayed. * @see #setScrollBarStyle(int) * @see #setFastScrollEnabled(boolean) */ public void setFastScrollAlwaysVisible(boolean alwaysShow) { if (alwaysShow && !mFastScrollEnabled) { setFastScrollEnabled(true); } if (mFastScroller != null) { mFastScroller.setAlwaysShow(alwaysShow); } computeOpaqueFlags(); recomputePadding(); } /** * Returns true if the fast scroller is set to always show on this view rather than * fade out when not in use. * * @return true if the fast scroller will always show. * @see #setFastScrollAlwaysVisible(boolean) */ public boolean isFastScrollAlwaysVisible() { return mFastScrollEnabled && mFastScroller.isAlwaysShowEnabled(); } @Override public int getVerticalScrollbarWidth() { if (isEnabled()) { return Math.max(super.getVerticalScrollbarWidth(), mFastScroller.getWidth()); } return super.getVerticalScrollbarWidth(); } /** * Returns the current state of the fast scroll feature. * @see #setFastScrollEnabled(boolean) Loading @@ -1138,6 +1183,14 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te return mFastScrollEnabled; } @Override public void setVerticalScrollbarPosition(int position) { super.setVerticalScrollbarPosition(position); if (mFastScroller != null) { mFastScroller.setScrollbarPosition(position); } } /** * If fast scroll is visible, then don't draw the vertical scrollbar. * @hide Loading Loading @@ -1968,6 +2021,31 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } } @Override protected boolean isPaddingOffsetRequired() { return (mGroupFlags & CLIP_TO_PADDING_MASK) != CLIP_TO_PADDING_MASK; } @Override protected int getLeftPaddingOffset() { return (mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK ? 0 : -mPaddingLeft; } @Override protected int getTopPaddingOffset() { return (mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK ? 0 : -mPaddingTop; } @Override protected int getRightPaddingOffset() { return (mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK ? 0 : mPaddingRight; } @Override protected int getBottomPaddingOffset() { return (mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK ? 0 : mPaddingBottom; } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { if (getChildCount() > 0) { Loading core/java/android/widget/FastScroller.java +213 −29 Original line number Diff line number Diff line Loading @@ -22,12 +22,14 @@ import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.drawable.Drawable; import android.graphics.drawable.NinePatchDrawable; import android.os.Handler; import android.os.SystemClock; import android.util.TypedValue; import android.view.MotionEvent; import android.view.View; import android.widget.AbsListView.OnScrollListener; /** Loading @@ -48,8 +50,37 @@ class FastScroller { // Scroll thumb fading out due to inactivity timeout private static final int STATE_EXIT = 4; private static final int[] PRESSED_STATES = new int[] { android.R.attr.state_pressed }; private static final int[] DEFAULT_STATES = new int[0]; private static final int[] ATTRS = new int[] { android.R.attr.textColorPrimary, com.android.internal.R.attr.fastScrollThumbDrawable, com.android.internal.R.attr.fastScrollTrackDrawable, com.android.internal.R.attr.fastScrollPreviewBackgroundLeft, com.android.internal.R.attr.fastScrollPreviewBackgroundRight, com.android.internal.R.attr.fastScrollOverlayPosition }; private static final int PRIMARY_TEXT_COLOR = 0; private static final int THUMB_DRAWABLE = 1; private static final int TRACK_DRAWABLE = 2; private static final int PREVIEW_BACKGROUND_LEFT = 3; private static final int PREVIEW_BACKGROUND_RIGHT = 4; private static final int OVERLAY_POSITION = 5; private static final int OVERLAY_FLOATING = 0; private static final int OVERLAY_AT_THUMB = 1; private Drawable mThumbDrawable; private Drawable mOverlayDrawable; private Drawable mTrackDrawable; private Drawable mOverlayDrawableLeft; private Drawable mOverlayDrawableRight; private int mThumbH; private int mThumbW; Loading Loading @@ -80,11 +111,64 @@ class FastScroller { private boolean mChangedBounds; private int mPosition; private boolean mAlwaysShow; private int mOverlayPosition; private static final int FADE_TIMEOUT = 1500; private final Rect mTmpRect = new Rect(); public FastScroller(Context context, AbsListView listView) { mList = listView; init(context); } public void setAlwaysShow(boolean alwaysShow) { mAlwaysShow = alwaysShow; if (alwaysShow) { mHandler.removeCallbacks(mScrollFade); setState(STATE_VISIBLE); } else if (mState == STATE_VISIBLE) { mHandler.postDelayed(mScrollFade, FADE_TIMEOUT); } } public boolean isAlwaysShowEnabled() { return mAlwaysShow; } private void refreshDrawableState() { int[] state = mState == STATE_DRAGGING ? PRESSED_STATES : DEFAULT_STATES; if (mThumbDrawable != null && mThumbDrawable.isStateful()) { mThumbDrawable.setState(state); } if (mTrackDrawable != null && mTrackDrawable.isStateful()) { mTrackDrawable.setState(state); } } public void setScrollbarPosition(int position) { mPosition = position; switch (position) { default: case View.SCROLLBAR_POSITION_DEFAULT: case View.SCROLLBAR_POSITION_RIGHT: mOverlayDrawable = mOverlayDrawableRight; break; case View.SCROLLBAR_POSITION_LEFT: mOverlayDrawable = mOverlayDrawableLeft; break; } } public int getWidth() { return mThumbW; } public void setState(int state) { switch (state) { case STATE_NONE: Loading @@ -105,6 +189,7 @@ class FastScroller { break; } mState = state; refreshDrawableState(); } public int getState() { Loading @@ -114,27 +199,42 @@ class FastScroller { private void resetThumbPos() { final int viewWidth = mList.getWidth(); // Bounds are always top right. Y coordinate get's translated during draw switch (mPosition) { case View.SCROLLBAR_POSITION_DEFAULT: case View.SCROLLBAR_POSITION_RIGHT: mThumbDrawable.setBounds(viewWidth - mThumbW, 0, viewWidth, mThumbH); break; case View.SCROLLBAR_POSITION_LEFT: mThumbDrawable.setBounds(0, 0, mThumbW, mThumbH); break; } mThumbDrawable.setAlpha(ScrollFade.ALPHA_MAX); } private void useThumbDrawable(Context context, Drawable drawable) { mThumbDrawable = drawable; if (drawable instanceof NinePatchDrawable) { mThumbW = context.getResources().getDimensionPixelSize( com.android.internal.R.dimen.fastscroll_thumb_width); mThumbH = context.getResources().getDimensionPixelSize( com.android.internal.R.dimen.fastscroll_thumb_height); } else { mThumbW = drawable.getIntrinsicWidth(); mThumbH = drawable.getIntrinsicHeight(); } mChangedBounds = true; } private void init(Context context) { // Get both the scrollbar states drawables final Resources res = context.getResources(); useThumbDrawable(context, res.getDrawable( com.android.internal.R.drawable.scrollbar_handle_accelerated_anim2)); TypedArray ta = context.getTheme().obtainStyledAttributes(ATTRS); useThumbDrawable(context, ta.getDrawable(ta.getIndex(THUMB_DRAWABLE))); mTrackDrawable = ta.getDrawable(ta.getIndex(TRACK_DRAWABLE)); mOverlayDrawable = res.getDrawable( com.android.internal.R.drawable.menu_submenu_background); mOverlayDrawableLeft = ta.getDrawable(ta.getIndex(PREVIEW_BACKGROUND_LEFT)); mOverlayDrawableRight = ta.getDrawable(ta.getIndex(PREVIEW_BACKGROUND_RIGHT)); mOverlayPosition = ta.getInt(ta.getIndex(OVERLAY_POSITION), OVERLAY_FLOATING); mScrollCompleted = true; Loading @@ -148,9 +248,8 @@ class FastScroller { mPaint.setAntiAlias(true); mPaint.setTextAlign(Paint.Align.CENTER); mPaint.setTextSize(mOverlaySize / 2); TypedArray ta = context.getTheme().obtainStyledAttributes(new int[] { android.R.attr.textColorPrimary }); ColorStateList textColor = ta.getColorStateList(ta.getIndex(0)); ColorStateList textColor = ta.getColorStateList(ta.getIndex(PRIMARY_TEXT_COLOR)); int textColorNormal = textColor.getDefaultColor(); mPaint.setColor(textColorNormal); mPaint.setStyle(Paint.Style.FILL_AND_STROKE); Loading @@ -161,6 +260,11 @@ class FastScroller { } mState = STATE_NONE; refreshDrawableState(); ta.recycle(); setScrollbarPosition(mList.getVerticalScrollbarPosition()); } void stop() { Loading Loading @@ -188,23 +292,73 @@ class FastScroller { if (alpha < ScrollFade.ALPHA_MAX / 2) { mThumbDrawable.setAlpha(alpha * 2); } int left = viewWidth - (mThumbW * alpha) / ScrollFade.ALPHA_MAX; mThumbDrawable.setBounds(left, 0, viewWidth, mThumbH); int left = 0; switch (mPosition) { case View.SCROLLBAR_POSITION_DEFAULT: case View.SCROLLBAR_POSITION_RIGHT: left = viewWidth - (mThumbW * alpha) / ScrollFade.ALPHA_MAX; break; case View.SCROLLBAR_POSITION_LEFT: left = -mThumbW + (mThumbW * alpha) / ScrollFade.ALPHA_MAX; break; } mThumbDrawable.setBounds(left, 0, left + mThumbW, mThumbH); mChangedBounds = true; } if (mTrackDrawable != null) { final int left = mThumbDrawable.getBounds().left; final int trackWidth = mTrackDrawable.getIntrinsicWidth(); final int trackLeft = (left + mThumbW) / 2 - trackWidth / 2; mTrackDrawable.setBounds(trackLeft, 0, trackLeft + trackWidth, mList.getHeight()); mTrackDrawable.draw(canvas); } canvas.translate(0, y); mThumbDrawable.draw(canvas); canvas.translate(0, -y); // If user is dragging the scroll bar, draw the alphabet overlay if (mState == STATE_DRAGGING && mDrawOverlay) { if (mOverlayPosition == OVERLAY_AT_THUMB) { int left = 0; switch (mPosition) { default: case View.SCROLLBAR_POSITION_DEFAULT: case View.SCROLLBAR_POSITION_RIGHT: left = Math.max(0, mThumbDrawable.getBounds().left - mThumbW - mOverlaySize); break; case View.SCROLLBAR_POSITION_LEFT: left = Math.min(mThumbDrawable.getBounds().right + mThumbW, mList.getWidth() - mOverlaySize); break; } int top = Math.max(0, Math.min(y + (mThumbH - mOverlaySize) / 2, mList.getHeight() - mOverlaySize)); final RectF pos = mOverlayPos; pos.left = left; pos.right = pos.left + mOverlaySize; pos.top = top; pos.bottom = pos.top + mOverlaySize; if (mOverlayDrawable != null) { mOverlayDrawable.setBounds((int) pos.left, (int) pos.top, (int) pos.right, (int) pos.bottom); } } mOverlayDrawable.draw(canvas); final Paint paint = mPaint; float descent = paint.descent(); final RectF rectF = mOverlayPos; canvas.drawText(mSectionText, (int) (rectF.left + rectF.right) / 2, (int) (rectF.bottom + rectF.top) / 2 + mOverlaySize / 4 - descent, paint); final Rect tmpRect = mTmpRect; mOverlayDrawable.getPadding(tmpRect); final int hOff = (tmpRect.right - tmpRect.left) / 2; final int vOff = (tmpRect.bottom - tmpRect.top) / 2; canvas.drawText(mSectionText, (int) (rectF.left + rectF.right) / 2 - hOff, (int) (rectF.bottom + rectF.top) / 2 + mOverlaySize / 4 - descent - vOff, paint); } else if (mState == STATE_EXIT) { if (alpha == 0) { // Done with exit setState(STATE_NONE); Loading @@ -216,8 +370,18 @@ class FastScroller { void onSizeChanged(int w, int h, int oldw, int oldh) { if (mThumbDrawable != null) { switch (mPosition) { default: case View.SCROLLBAR_POSITION_DEFAULT: case View.SCROLLBAR_POSITION_RIGHT: mThumbDrawable.setBounds(w - mThumbW, 0, w, mThumbH); break; case View.SCROLLBAR_POSITION_LEFT: mThumbDrawable.setBounds(0, 0, mThumbW, mThumbH); break; } } if (mOverlayPosition == OVERLAY_FLOATING) { final RectF pos = mOverlayPos; pos.left = (w - mOverlaySize) / 2; pos.right = pos.left + mOverlaySize; Loading @@ -228,6 +392,7 @@ class FastScroller { (int) pos.right, (int) pos.bottom); } } } void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { Loading Loading @@ -257,7 +422,9 @@ class FastScroller { mVisibleItem = firstVisibleItem; if (mState != STATE_DRAGGING) { setState(STATE_VISIBLE); mHandler.postDelayed(mScrollFade, 1500); if (!mAlwaysShow) { mHandler.postDelayed(mScrollFade, FADE_TIMEOUT); } } } Loading Loading @@ -454,7 +621,11 @@ class FastScroller { setState(STATE_VISIBLE); final Handler handler = mHandler; handler.removeCallbacks(mScrollFade); if (!mAlwaysShow) { handler.postDelayed(mScrollFade, 1000); } mList.invalidate(); return true; } } else if (action == MotionEvent.ACTION_MOVE) { Loading Loading @@ -482,7 +653,20 @@ class FastScroller { } boolean isPointInside(float x, float y) { return x > mList.getWidth() - mThumbW && y >= mThumbY && y <= mThumbY + mThumbH; boolean inTrack = false; switch (mPosition) { default: case View.SCROLLBAR_POSITION_DEFAULT: case View.SCROLLBAR_POSITION_RIGHT: inTrack = x > mList.getWidth() - mThumbW; break; case View.SCROLLBAR_POSITION_LEFT: inTrack = x < mThumbW; break; } // Allow taps in the track to start moving. return inTrack && (mTrackDrawable != null || y >= mThumbY && y <= mThumbY + mThumbH); } public class ScrollFade implements Runnable { Loading core/res/res/drawable-hdpi/btn_cab_done_default_holo.9.png −221 B (2.19 KiB) Loading image diff... Loading
api/current.xml +103 −0 Original line number Diff line number Diff line Loading @@ -4189,6 +4189,17 @@ visibility="public" > </field> <field name="fastScrollAlwaysVisible" type="int" transient="false" volatile="false" value="16843588" static="true" final="true" deprecated="not deprecated" visibility="public" > </field> <field name="fastScrollEnabled" type="int" transient="false" Loading Loading @@ -10371,6 +10382,17 @@ visibility="public" > </field> <field name="verticalScrollbarPosition" type="int" transient="false" volatile="false" value="16843587" static="true" final="true" deprecated="not deprecated" visibility="public" > </field> <field name="verticalSpacing" type="int" transient="false" Loading Loading @@ -206780,6 +206802,17 @@ visibility="public" > </method> <method name="getVerticalScrollbarPosition" return="int" abstract="false" native="false" synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > </method> <method name="getVerticalScrollbarWidth" return="int" abstract="false" Loading Loading @@ -209227,6 +209260,19 @@ <parameter name="verticalScrollBarEnabled" type="boolean"> </parameter> </method> <method name="setVerticalScrollbarPosition" return="void" abstract="false" native="false" synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > <parameter name="position" type="int"> </parameter> </method> <method name="setVisibility" return="void" abstract="false" Loading Loading @@ -210016,6 +210062,39 @@ visibility="public" > </field> <field name="SCROLLBAR_POSITION_DEFAULT" type="int" transient="false" volatile="false" value="0" static="true" final="true" deprecated="not deprecated" visibility="public" > </field> <field name="SCROLLBAR_POSITION_LEFT" type="int" transient="false" volatile="false" value="1" static="true" final="true" deprecated="not deprecated" visibility="public" > </field> <field name="SCROLLBAR_POSITION_RIGHT" type="int" transient="false" volatile="false" value="2" static="true" final="true" deprecated="not deprecated" visibility="public" > </field> <field name="SELECTED_STATE_SET" type="int[]" transient="false" Loading Loading @@ -228926,6 +229005,17 @@ visibility="public" > </method> <method name="isFastScrollAlwaysVisible" return="boolean" abstract="false" native="false" synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > </method> <method name="isFastScrollEnabled" return="boolean" abstract="false" Loading Loading @@ -229213,6 +229303,19 @@ <parameter name="onTop" type="boolean"> </parameter> </method> <method name="setFastScrollAlwaysVisible" return="void" abstract="false" native="false" synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > <parameter name="alwaysShow" type="boolean"> </parameter> </method> <method name="setFastScrollEnabled" return="void" abstract="false"
core/java/android/view/View.java +84 −8 Original line number Diff line number Diff line Loading @@ -1966,6 +1966,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility @ViewDebug.ExportedProperty(category = "padding") int mUserPaddingBottom; /** * Cache the paddingLeft set by the user to append to the scrollbar's size. */ @ViewDebug.ExportedProperty(category = "padding") int mUserPaddingLeft; /** * @hide */ Loading Loading @@ -2116,6 +2122,26 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility */ boolean mCanAcceptDrop; /** * Position of the vertical scroll bar. */ private int mVerticalScrollbarPosition; /** * Position the scroll bar at the default position as determined by the system. */ public static final int SCROLLBAR_POSITION_DEFAULT = 0; /** * Position the scroll bar along the left edge. */ public static final int SCROLLBAR_POSITION_LEFT = 1; /** * Position the scroll bar along the right edge. */ public static final int SCROLLBAR_POSITION_RIGHT = 2; /** * Simple constructor to use when creating a view from code. * Loading Loading @@ -2448,6 +2474,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility case R.styleable.View_overScrollMode: overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS); break; case R.styleable.View_verticalScrollbarPosition: mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT); break; } } Loading Loading @@ -2707,6 +2736,29 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility } } /** * Set the position of the vertical scroll bar. Should be one of * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or * {@link #SCROLLBAR_POSITION_RIGHT}. * * @param position Where the vertical scroll bar should be positioned. */ public void setVerticalScrollbarPosition(int position) { if (mVerticalScrollbarPosition != position) { mVerticalScrollbarPosition = position; computeOpaqueFlags(); recomputePadding(); } } /** * @return The position where the vertical scroll bar will show, if applicable. * @see #setVerticalScrollbarPosition(int) */ public int getVerticalScrollbarPosition() { return mVerticalScrollbarPosition; } /** * Register a callback to be invoked when focus of this view changed. * Loading Loading @@ -6542,7 +6594,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility (mAlpha >= 1.0f - ViewConfiguration.ALPHA_THRESHOLD); } private void computeOpaqueFlags() { /** * @hide */ protected void computeOpaqueFlags() { // Opaque if: // - Has a background // - Background is opaque Loading Loading @@ -6929,8 +6984,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility } } private void recomputePadding() { setPadding(mPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom); /** * @hide */ protected void recomputePadding() { setPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom); } /** Loading Loading @@ -7213,8 +7271,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility scrollBar.setParameters(computeVerticalScrollRange(), computeVerticalScrollOffset(), computeVerticalScrollExtent(), true); // TODO: Deal with RTL languages to position scrollbar on left switch (mVerticalScrollbarPosition) { default: case SCROLLBAR_POSITION_DEFAULT: case SCROLLBAR_POSITION_RIGHT: left = scrollX + width - size - (mUserPaddingRight & inside); break; case SCROLLBAR_POSITION_LEFT: left = scrollX + (mUserPaddingLeft & inside); break; } top = scrollY + (mPaddingTop & inside); right = left + size; bottom = scrollY + height - (mUserPaddingBottom & inside); Loading Loading @@ -9003,6 +9069,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility public void setPadding(int left, int top, int right, int bottom) { boolean changed = false; mUserPaddingLeft = left; mUserPaddingRight = right; mUserPaddingBottom = bottom; Loading @@ -9010,12 +9077,21 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility // Common case is there are no scroll bars. if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) { // TODO: Deal with RTL languages to adjust left padding instead of right. if ((viewFlags & SCROLLBARS_VERTICAL) != 0) { right += (viewFlags & SCROLLBARS_INSET_MASK) == 0 // TODO Determine what to do with SCROLLBAR_POSITION_DEFAULT based on RTL settings. final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0 ? 0 : getVerticalScrollbarWidth(); switch (mVerticalScrollbarPosition) { case SCROLLBAR_POSITION_DEFAULT: case SCROLLBAR_POSITION_RIGHT: right += offset; break; case SCROLLBAR_POSITION_LEFT: left += offset; break; } } if ((viewFlags & SCROLLBARS_HORIZONTAL) == 0) { if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) { bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0 ? 0 : getHorizontalScrollbarHeight(); } Loading
core/java/android/widget/AbsListView.java +78 −0 Original line number Diff line number Diff line Loading @@ -744,6 +744,8 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } setChoiceMode(a.getInt(R.styleable.AbsListView_choiceMode, CHOICE_MODE_NONE)); setFastScrollAlwaysVisible( a.getBoolean(R.styleable.AbsListView_fastScrollAlwaysVisible, false)); a.recycle(); } Loading Loading @@ -1128,6 +1130,49 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } } /** * Set whether or not the fast scroller should always be shown in place of the * standard scrollbars. Fast scrollers shown in this way will not fade out and will * be a permanent fixture within the list. Best combined with an inset scroll bar style * that will ensure enough padding. This will enable fast scrolling if it is not * already enabled. * * @param alwaysShow true if the fast scroller should always be displayed. * @see #setScrollBarStyle(int) * @see #setFastScrollEnabled(boolean) */ public void setFastScrollAlwaysVisible(boolean alwaysShow) { if (alwaysShow && !mFastScrollEnabled) { setFastScrollEnabled(true); } if (mFastScroller != null) { mFastScroller.setAlwaysShow(alwaysShow); } computeOpaqueFlags(); recomputePadding(); } /** * Returns true if the fast scroller is set to always show on this view rather than * fade out when not in use. * * @return true if the fast scroller will always show. * @see #setFastScrollAlwaysVisible(boolean) */ public boolean isFastScrollAlwaysVisible() { return mFastScrollEnabled && mFastScroller.isAlwaysShowEnabled(); } @Override public int getVerticalScrollbarWidth() { if (isEnabled()) { return Math.max(super.getVerticalScrollbarWidth(), mFastScroller.getWidth()); } return super.getVerticalScrollbarWidth(); } /** * Returns the current state of the fast scroll feature. * @see #setFastScrollEnabled(boolean) Loading @@ -1138,6 +1183,14 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te return mFastScrollEnabled; } @Override public void setVerticalScrollbarPosition(int position) { super.setVerticalScrollbarPosition(position); if (mFastScroller != null) { mFastScroller.setScrollbarPosition(position); } } /** * If fast scroll is visible, then don't draw the vertical scrollbar. * @hide Loading Loading @@ -1968,6 +2021,31 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } } @Override protected boolean isPaddingOffsetRequired() { return (mGroupFlags & CLIP_TO_PADDING_MASK) != CLIP_TO_PADDING_MASK; } @Override protected int getLeftPaddingOffset() { return (mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK ? 0 : -mPaddingLeft; } @Override protected int getTopPaddingOffset() { return (mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK ? 0 : -mPaddingTop; } @Override protected int getRightPaddingOffset() { return (mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK ? 0 : mPaddingRight; } @Override protected int getBottomPaddingOffset() { return (mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK ? 0 : mPaddingBottom; } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { if (getChildCount() > 0) { Loading
core/java/android/widget/FastScroller.java +213 −29 Original line number Diff line number Diff line Loading @@ -22,12 +22,14 @@ import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.drawable.Drawable; import android.graphics.drawable.NinePatchDrawable; import android.os.Handler; import android.os.SystemClock; import android.util.TypedValue; import android.view.MotionEvent; import android.view.View; import android.widget.AbsListView.OnScrollListener; /** Loading @@ -48,8 +50,37 @@ class FastScroller { // Scroll thumb fading out due to inactivity timeout private static final int STATE_EXIT = 4; private static final int[] PRESSED_STATES = new int[] { android.R.attr.state_pressed }; private static final int[] DEFAULT_STATES = new int[0]; private static final int[] ATTRS = new int[] { android.R.attr.textColorPrimary, com.android.internal.R.attr.fastScrollThumbDrawable, com.android.internal.R.attr.fastScrollTrackDrawable, com.android.internal.R.attr.fastScrollPreviewBackgroundLeft, com.android.internal.R.attr.fastScrollPreviewBackgroundRight, com.android.internal.R.attr.fastScrollOverlayPosition }; private static final int PRIMARY_TEXT_COLOR = 0; private static final int THUMB_DRAWABLE = 1; private static final int TRACK_DRAWABLE = 2; private static final int PREVIEW_BACKGROUND_LEFT = 3; private static final int PREVIEW_BACKGROUND_RIGHT = 4; private static final int OVERLAY_POSITION = 5; private static final int OVERLAY_FLOATING = 0; private static final int OVERLAY_AT_THUMB = 1; private Drawable mThumbDrawable; private Drawable mOverlayDrawable; private Drawable mTrackDrawable; private Drawable mOverlayDrawableLeft; private Drawable mOverlayDrawableRight; private int mThumbH; private int mThumbW; Loading Loading @@ -80,11 +111,64 @@ class FastScroller { private boolean mChangedBounds; private int mPosition; private boolean mAlwaysShow; private int mOverlayPosition; private static final int FADE_TIMEOUT = 1500; private final Rect mTmpRect = new Rect(); public FastScroller(Context context, AbsListView listView) { mList = listView; init(context); } public void setAlwaysShow(boolean alwaysShow) { mAlwaysShow = alwaysShow; if (alwaysShow) { mHandler.removeCallbacks(mScrollFade); setState(STATE_VISIBLE); } else if (mState == STATE_VISIBLE) { mHandler.postDelayed(mScrollFade, FADE_TIMEOUT); } } public boolean isAlwaysShowEnabled() { return mAlwaysShow; } private void refreshDrawableState() { int[] state = mState == STATE_DRAGGING ? PRESSED_STATES : DEFAULT_STATES; if (mThumbDrawable != null && mThumbDrawable.isStateful()) { mThumbDrawable.setState(state); } if (mTrackDrawable != null && mTrackDrawable.isStateful()) { mTrackDrawable.setState(state); } } public void setScrollbarPosition(int position) { mPosition = position; switch (position) { default: case View.SCROLLBAR_POSITION_DEFAULT: case View.SCROLLBAR_POSITION_RIGHT: mOverlayDrawable = mOverlayDrawableRight; break; case View.SCROLLBAR_POSITION_LEFT: mOverlayDrawable = mOverlayDrawableLeft; break; } } public int getWidth() { return mThumbW; } public void setState(int state) { switch (state) { case STATE_NONE: Loading @@ -105,6 +189,7 @@ class FastScroller { break; } mState = state; refreshDrawableState(); } public int getState() { Loading @@ -114,27 +199,42 @@ class FastScroller { private void resetThumbPos() { final int viewWidth = mList.getWidth(); // Bounds are always top right. Y coordinate get's translated during draw switch (mPosition) { case View.SCROLLBAR_POSITION_DEFAULT: case View.SCROLLBAR_POSITION_RIGHT: mThumbDrawable.setBounds(viewWidth - mThumbW, 0, viewWidth, mThumbH); break; case View.SCROLLBAR_POSITION_LEFT: mThumbDrawable.setBounds(0, 0, mThumbW, mThumbH); break; } mThumbDrawable.setAlpha(ScrollFade.ALPHA_MAX); } private void useThumbDrawable(Context context, Drawable drawable) { mThumbDrawable = drawable; if (drawable instanceof NinePatchDrawable) { mThumbW = context.getResources().getDimensionPixelSize( com.android.internal.R.dimen.fastscroll_thumb_width); mThumbH = context.getResources().getDimensionPixelSize( com.android.internal.R.dimen.fastscroll_thumb_height); } else { mThumbW = drawable.getIntrinsicWidth(); mThumbH = drawable.getIntrinsicHeight(); } mChangedBounds = true; } private void init(Context context) { // Get both the scrollbar states drawables final Resources res = context.getResources(); useThumbDrawable(context, res.getDrawable( com.android.internal.R.drawable.scrollbar_handle_accelerated_anim2)); TypedArray ta = context.getTheme().obtainStyledAttributes(ATTRS); useThumbDrawable(context, ta.getDrawable(ta.getIndex(THUMB_DRAWABLE))); mTrackDrawable = ta.getDrawable(ta.getIndex(TRACK_DRAWABLE)); mOverlayDrawable = res.getDrawable( com.android.internal.R.drawable.menu_submenu_background); mOverlayDrawableLeft = ta.getDrawable(ta.getIndex(PREVIEW_BACKGROUND_LEFT)); mOverlayDrawableRight = ta.getDrawable(ta.getIndex(PREVIEW_BACKGROUND_RIGHT)); mOverlayPosition = ta.getInt(ta.getIndex(OVERLAY_POSITION), OVERLAY_FLOATING); mScrollCompleted = true; Loading @@ -148,9 +248,8 @@ class FastScroller { mPaint.setAntiAlias(true); mPaint.setTextAlign(Paint.Align.CENTER); mPaint.setTextSize(mOverlaySize / 2); TypedArray ta = context.getTheme().obtainStyledAttributes(new int[] { android.R.attr.textColorPrimary }); ColorStateList textColor = ta.getColorStateList(ta.getIndex(0)); ColorStateList textColor = ta.getColorStateList(ta.getIndex(PRIMARY_TEXT_COLOR)); int textColorNormal = textColor.getDefaultColor(); mPaint.setColor(textColorNormal); mPaint.setStyle(Paint.Style.FILL_AND_STROKE); Loading @@ -161,6 +260,11 @@ class FastScroller { } mState = STATE_NONE; refreshDrawableState(); ta.recycle(); setScrollbarPosition(mList.getVerticalScrollbarPosition()); } void stop() { Loading Loading @@ -188,23 +292,73 @@ class FastScroller { if (alpha < ScrollFade.ALPHA_MAX / 2) { mThumbDrawable.setAlpha(alpha * 2); } int left = viewWidth - (mThumbW * alpha) / ScrollFade.ALPHA_MAX; mThumbDrawable.setBounds(left, 0, viewWidth, mThumbH); int left = 0; switch (mPosition) { case View.SCROLLBAR_POSITION_DEFAULT: case View.SCROLLBAR_POSITION_RIGHT: left = viewWidth - (mThumbW * alpha) / ScrollFade.ALPHA_MAX; break; case View.SCROLLBAR_POSITION_LEFT: left = -mThumbW + (mThumbW * alpha) / ScrollFade.ALPHA_MAX; break; } mThumbDrawable.setBounds(left, 0, left + mThumbW, mThumbH); mChangedBounds = true; } if (mTrackDrawable != null) { final int left = mThumbDrawable.getBounds().left; final int trackWidth = mTrackDrawable.getIntrinsicWidth(); final int trackLeft = (left + mThumbW) / 2 - trackWidth / 2; mTrackDrawable.setBounds(trackLeft, 0, trackLeft + trackWidth, mList.getHeight()); mTrackDrawable.draw(canvas); } canvas.translate(0, y); mThumbDrawable.draw(canvas); canvas.translate(0, -y); // If user is dragging the scroll bar, draw the alphabet overlay if (mState == STATE_DRAGGING && mDrawOverlay) { if (mOverlayPosition == OVERLAY_AT_THUMB) { int left = 0; switch (mPosition) { default: case View.SCROLLBAR_POSITION_DEFAULT: case View.SCROLLBAR_POSITION_RIGHT: left = Math.max(0, mThumbDrawable.getBounds().left - mThumbW - mOverlaySize); break; case View.SCROLLBAR_POSITION_LEFT: left = Math.min(mThumbDrawable.getBounds().right + mThumbW, mList.getWidth() - mOverlaySize); break; } int top = Math.max(0, Math.min(y + (mThumbH - mOverlaySize) / 2, mList.getHeight() - mOverlaySize)); final RectF pos = mOverlayPos; pos.left = left; pos.right = pos.left + mOverlaySize; pos.top = top; pos.bottom = pos.top + mOverlaySize; if (mOverlayDrawable != null) { mOverlayDrawable.setBounds((int) pos.left, (int) pos.top, (int) pos.right, (int) pos.bottom); } } mOverlayDrawable.draw(canvas); final Paint paint = mPaint; float descent = paint.descent(); final RectF rectF = mOverlayPos; canvas.drawText(mSectionText, (int) (rectF.left + rectF.right) / 2, (int) (rectF.bottom + rectF.top) / 2 + mOverlaySize / 4 - descent, paint); final Rect tmpRect = mTmpRect; mOverlayDrawable.getPadding(tmpRect); final int hOff = (tmpRect.right - tmpRect.left) / 2; final int vOff = (tmpRect.bottom - tmpRect.top) / 2; canvas.drawText(mSectionText, (int) (rectF.left + rectF.right) / 2 - hOff, (int) (rectF.bottom + rectF.top) / 2 + mOverlaySize / 4 - descent - vOff, paint); } else if (mState == STATE_EXIT) { if (alpha == 0) { // Done with exit setState(STATE_NONE); Loading @@ -216,8 +370,18 @@ class FastScroller { void onSizeChanged(int w, int h, int oldw, int oldh) { if (mThumbDrawable != null) { switch (mPosition) { default: case View.SCROLLBAR_POSITION_DEFAULT: case View.SCROLLBAR_POSITION_RIGHT: mThumbDrawable.setBounds(w - mThumbW, 0, w, mThumbH); break; case View.SCROLLBAR_POSITION_LEFT: mThumbDrawable.setBounds(0, 0, mThumbW, mThumbH); break; } } if (mOverlayPosition == OVERLAY_FLOATING) { final RectF pos = mOverlayPos; pos.left = (w - mOverlaySize) / 2; pos.right = pos.left + mOverlaySize; Loading @@ -228,6 +392,7 @@ class FastScroller { (int) pos.right, (int) pos.bottom); } } } void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { Loading Loading @@ -257,7 +422,9 @@ class FastScroller { mVisibleItem = firstVisibleItem; if (mState != STATE_DRAGGING) { setState(STATE_VISIBLE); mHandler.postDelayed(mScrollFade, 1500); if (!mAlwaysShow) { mHandler.postDelayed(mScrollFade, FADE_TIMEOUT); } } } Loading Loading @@ -454,7 +621,11 @@ class FastScroller { setState(STATE_VISIBLE); final Handler handler = mHandler; handler.removeCallbacks(mScrollFade); if (!mAlwaysShow) { handler.postDelayed(mScrollFade, 1000); } mList.invalidate(); return true; } } else if (action == MotionEvent.ACTION_MOVE) { Loading Loading @@ -482,7 +653,20 @@ class FastScroller { } boolean isPointInside(float x, float y) { return x > mList.getWidth() - mThumbW && y >= mThumbY && y <= mThumbY + mThumbH; boolean inTrack = false; switch (mPosition) { default: case View.SCROLLBAR_POSITION_DEFAULT: case View.SCROLLBAR_POSITION_RIGHT: inTrack = x > mList.getWidth() - mThumbW; break; case View.SCROLLBAR_POSITION_LEFT: inTrack = x < mThumbW; break; } // Allow taps in the track to start moving. return inTrack && (mTrackDrawable != null || y >= mThumbY && y <= mThumbY + mThumbH); } public class ScrollFade implements Runnable { Loading