diff options
Diffstat (limited to 'library/main/src/com/android/setupwizardlib/view/StickyHeaderListView.java')
-rw-r--r-- | library/main/src/com/android/setupwizardlib/view/StickyHeaderListView.java | 215 |
1 files changed, 109 insertions, 106 deletions
diff --git a/library/main/src/com/android/setupwizardlib/view/StickyHeaderListView.java b/library/main/src/com/android/setupwizardlib/view/StickyHeaderListView.java index 58274f6..c226f29 100644 --- a/library/main/src/com/android/setupwizardlib/view/StickyHeaderListView.java +++ b/library/main/src/com/android/setupwizardlib/view/StickyHeaderListView.java @@ -29,7 +29,6 @@ import android.view.View; import android.view.WindowInsets; import android.view.accessibility.AccessibilityEvent; import android.widget.ListView; - import com.android.setupwizardlib.R; /** @@ -39,125 +38,129 @@ import com.android.setupwizardlib.R; * when the sticky element hits the top of the view. * * <p>There are a few things to note: + * * <ol> * <li>The two supported scenarios are StickyHeaderListView -> Header (stickyContainer) -> sticky, - * and StickyHeaderListView -> Header (sticky). The arrow (->) represents parent/child - * relationship and must be immediate child. + * and StickyHeaderListView -> Header (sticky). The arrow (->) represents parent/child + * relationship and must be immediate child. * <li>The view does not work well with padding. b/16190933 * <li>If fitsSystemWindows is true, then this will offset the sticking position by the height of - * the system decorations at the top of the screen. + * the system decorations at the top of the screen. * </ol> * * @see StickyHeaderScrollView */ public class StickyHeaderListView extends ListView { - private View mSticky; - private View mStickyContainer; - private int mStatusBarInset = 0; - private RectF mStickyRect = new RectF(); - - public StickyHeaderListView(Context context) { - super(context); - init(null, android.R.attr.listViewStyle); + private View sticky; + private View stickyContainer; + private int statusBarInset = 0; + private final RectF stickyRect = new RectF(); + + public StickyHeaderListView(Context context) { + super(context); + init(null, android.R.attr.listViewStyle); + } + + public StickyHeaderListView(Context context, AttributeSet attrs) { + super(context, attrs); + init(attrs, android.R.attr.listViewStyle); + } + + public StickyHeaderListView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(attrs, defStyleAttr); + } + + private void init(AttributeSet attrs, int defStyleAttr) { + final TypedArray a = + getContext() + .obtainStyledAttributes(attrs, R.styleable.SuwStickyHeaderListView, defStyleAttr, 0); + int headerResId = a.getResourceId(R.styleable.SuwStickyHeaderListView_suwHeader, 0); + if (headerResId != 0) { + LayoutInflater inflater = LayoutInflater.from(getContext()); + View header = inflater.inflate(headerResId, this, false); + addHeaderView(header, null, false); } - - public StickyHeaderListView(Context context, AttributeSet attrs) { - super(context, attrs); - init(attrs, android.R.attr.listViewStyle); + a.recycle(); + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + super.onLayout(changed, l, t, r, b); + if (sticky == null) { + updateStickyView(); } - - public StickyHeaderListView(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - init(attrs, defStyleAttr); + } + + public void updateStickyView() { + sticky = findViewWithTag("sticky"); + stickyContainer = findViewWithTag("stickyContainer"); + } + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + if (stickyRect.contains(ev.getX(), ev.getY())) { + ev.offsetLocation(-stickyRect.left, -stickyRect.top); + return stickyContainer.dispatchTouchEvent(ev); + } else { + return super.dispatchTouchEvent(ev); } - - private void init(AttributeSet attrs, int defStyleAttr) { - final TypedArray a = getContext().obtainStyledAttributes(attrs, - R.styleable.SuwStickyHeaderListView, defStyleAttr, 0); - int headerResId = a.getResourceId(R.styleable.SuwStickyHeaderListView_suwHeader, 0); - if (headerResId != 0) { - LayoutInflater inflater = LayoutInflater.from(getContext()); - View header = inflater.inflate(headerResId, this, false); - addHeaderView(header, null, false); - } - a.recycle(); - } - - @Override - protected void onLayout(boolean changed, int l, int t, int r, int b) { - super.onLayout(changed, l, t, r, b); - if (mSticky == null) { - updateStickyView(); - } + } + + @Override + public void draw(Canvas canvas) { + super.draw(canvas); + if (sticky != null) { + final int saveCount = canvas.save(); + // The view to draw when sticking to the top + final View drawTarget = stickyContainer != null ? stickyContainer : sticky; + // The offset to draw the view at when sticky + final int drawOffset = stickyContainer != null ? sticky.getTop() : 0; + // Position of the draw target, relative to the outside of the scrollView + final int drawTop = drawTarget.getTop(); + if (drawTop + drawOffset < statusBarInset || !drawTarget.isShown()) { + // ListView does not translate the canvas, so we can simply draw at the top + stickyRect.set( + 0, + -drawOffset + statusBarInset, + drawTarget.getWidth(), + drawTarget.getHeight() - drawOffset + statusBarInset); + canvas.translate(0, stickyRect.top); + canvas.clipRect(0, 0, drawTarget.getWidth(), drawTarget.getHeight()); + drawTarget.draw(canvas); + } else { + stickyRect.setEmpty(); + } + canvas.restoreToCount(saveCount); } - - public void updateStickyView() { - mSticky = findViewWithTag("sticky"); - mStickyContainer = findViewWithTag("stickyContainer"); + } + + @Override + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + public WindowInsets onApplyWindowInsets(WindowInsets insets) { + if (getFitsSystemWindows()) { + statusBarInset = insets.getSystemWindowInsetTop(); + insets.replaceSystemWindowInsets( + insets.getSystemWindowInsetLeft(), + 0, /* top */ + insets.getSystemWindowInsetRight(), + insets.getSystemWindowInsetBottom()); } - - @Override - public boolean dispatchTouchEvent(MotionEvent ev) { - if (mStickyRect.contains(ev.getX(), ev.getY())) { - ev.offsetLocation(-mStickyRect.left, -mStickyRect.top); - return mStickyContainer.dispatchTouchEvent(ev); - } else { - return super.dispatchTouchEvent(ev); - } - } - - @Override - public void draw(Canvas canvas) { - super.draw(canvas); - if (mSticky != null) { - final int saveCount = canvas.save(); - // The view to draw when sticking to the top - final View drawTarget = mStickyContainer != null ? mStickyContainer : mSticky; - // The offset to draw the view at when sticky - final int drawOffset = mStickyContainer != null ? mSticky.getTop() : 0; - // Position of the draw target, relative to the outside of the scrollView - final int drawTop = drawTarget.getTop(); - if (drawTop + drawOffset < mStatusBarInset || !drawTarget.isShown()) { - // ListView does not translate the canvas, so we can simply draw at the top - mStickyRect.set(0, -drawOffset + mStatusBarInset, drawTarget.getWidth(), - drawTarget.getHeight() - drawOffset + mStatusBarInset); - canvas.translate(0, mStickyRect.top); - canvas.clipRect(0, 0, drawTarget.getWidth(), drawTarget.getHeight()); - drawTarget.draw(canvas); - } else { - mStickyRect.setEmpty(); - } - canvas.restoreToCount(saveCount); - } - } - - @Override - @TargetApi(Build.VERSION_CODES.LOLLIPOP) - public WindowInsets onApplyWindowInsets(WindowInsets insets) { - if (getFitsSystemWindows()) { - mStatusBarInset = insets.getSystemWindowInsetTop(); - insets.replaceSystemWindowInsets( - insets.getSystemWindowInsetLeft(), - 0, /* top */ - insets.getSystemWindowInsetRight(), - insets.getSystemWindowInsetBottom() - ); - } - return insets; - } - - @Override - public void onInitializeAccessibilityEvent(AccessibilityEvent event) { - super.onInitializeAccessibilityEvent(event); - - // Decoration-only headers should not count as an item for accessibility, adjust the - // accessibility event to account for that. - final int numberOfHeaders = mSticky != null ? 1 : 0; - event.setItemCount(event.getItemCount() - numberOfHeaders); - event.setFromIndex(Math.max(event.getFromIndex() - numberOfHeaders, 0)); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { - event.setToIndex(Math.max(event.getToIndex() - numberOfHeaders, 0)); - } + return insets; + } + + @Override + public void onInitializeAccessibilityEvent(AccessibilityEvent event) { + super.onInitializeAccessibilityEvent(event); + + // Decoration-only headers should not count as an item for accessibility, adjust the + // accessibility event to account for that. + final int numberOfHeaders = sticky != null ? 1 : 0; + event.setItemCount(event.getItemCount() - numberOfHeaders); + event.setFromIndex(Math.max(event.getFromIndex() - numberOfHeaders, 0)); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + event.setToIndex(Math.max(event.getToIndex() - numberOfHeaders, 0)); } + } } |