Code example for Scroller

Methods: computeScrollOffset, getCurrX, getCurrY, startScroll

0
        invalidate();
    } 
 
    @Override 
    public void computeScroll() { 
        if (mScroller.computeScrollOffset()) {
            scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
            postInvalidate();
        } else if (mNextScreen != INVALID_SCREEN) {
            mCurrentScreen = Math.max(0, Math.min(mNextScreen, getChildCount() - 1));
            mNextScreen = INVALID_SCREEN;
            postViewSwitched(mLastScrollDirection);
        } 
    } 
 
    /** 
     * Scroll to the {@link View} in the view buffer specified by the index. 
     * 
     * @param indexInBuffer Index of the view in the view buffer. 
     */ 
    private void setVisibleView(int indexInBuffer, boolean uiThread) {
        mCurrentScreen = Math.max(0, Math.min(indexInBuffer, getChildCount() - 1));
        int dx = (mCurrentScreen * getWidth()) - mScroller.getCurrX();
        mScroller.startScroll(mScroller.getCurrX(), mScroller.getCurrY(), dx, 0, 0);
        if (dx == 0) {
            onScrollChanged(mScroller.getCurrX() + dx, mScroller.getCurrY(), mScroller.getCurrX() + dx, mScroller.getCurrY());
        } 
        if (uiThread) {
            invalidate();
        } else { 
            postInvalidate();
        } 
    } 
 
    /** 
     * Set the listener that will receive notifications every time the {code 
     * ViewFlow} scrolls. 
     * 
     * @param l the scroll listener 
     */ 
    public void setOnViewSwitchListener(ViewSwitchListener l) {
        mViewSwitchListener = l;
    } 
 
    @Override 
    public Adapter getAdapter() {
        return mAdapter;
    } 
 
    @Override 
    public void setAdapter(Adapter adapter) {
        if (mAdapter != null) {
            mAdapter.unregisterDataSetObserver(mDataSetObserver);
        } 
 
        mAdapter = adapter;
 
        if (mAdapter != null) {
            mDataSetObserver = new AdapterDataSetObserver();
            mAdapter.registerDataSetObserver(mDataSetObserver);
 
        } 
        if (mAdapter.getCount() == 0)
            return; 
 
        for (int i = 0; i < Math.min(mAdapter.getCount(), mSideBuffer + 1); i++) {
            mLoadedViews.addLast(makeAndAddView(i, true, null));
        } 
 
        mCurrentAdapterIndex = 0;
        mCurrentBufferIndex = 0;
        requestLayout();
        setVisibleView(mCurrentBufferIndex, false);
        if (mViewSwitchListener != null) {
            mViewSwitchListener.onSwitched(mLoadedViews.get(0), 0);
        } 
    } 
 
    @Override 
    public View getSelectedView() {
        return (mCurrentBufferIndex < mLoadedViews.size() ? mLoadedViews.get(mCurrentBufferIndex) : null);
    } 
 
    /** 
     * Set the FlowIndicator 
     * 
     * @param flowIndicator 
     */ 
    public void setFlowIndicator(FlowIndicator flowIndicator) {
        mIndicator = flowIndicator;
        mIndicator.setViewFlow(this);
    } 
 
    @Override 
    public void setSelection(int position) {
        mNextScreen = INVALID_SCREEN;
        mScroller.forceFinished(true);
 
        if (mAdapter == null || position >= mAdapter.getCount()) {
            return; 
        } 
 
        ArrayList<View> recycleViews = new ArrayList<View>();
        View recycleView;
        while (!mLoadedViews.isEmpty()) {
            recycleViews.add(recycleView = mLoadedViews.remove());
            detachViewFromParent(recycleView);
        } 
 
        for (int i = Math.max(0, position - mSideBuffer); i < Math.min(mAdapter.getCount(), position + mSideBuffer + 1); i++) {
            mLoadedViews.addLast(makeAndAddView(i, true, (recycleViews.isEmpty() ? null : recycleViews.remove(0))));
            if (i == position) {
                mCurrentBufferIndex = mLoadedViews.size() - 1;
            } 
        } 
        mCurrentAdapterIndex = position;
 
        for (View view : recycleViews) {
            removeDetachedView(view, false);
        } 
        requestLayout();
        setVisibleView(mCurrentBufferIndex, false);
        if (mIndicator != null) {
            mIndicator.onSwitched(mLoadedViews.get(mCurrentBufferIndex), mCurrentAdapterIndex);
        } 
        if (mViewSwitchListener != null) {
            mViewSwitchListener.onSwitched(mLoadedViews.get(mCurrentBufferIndex), mCurrentAdapterIndex);
        } 
    } 
 
    private void resetFocus() { 
        logBuffer(); 
        mLoadedViews.clear();
        removeAllViewsInLayout();
 
        for (int i = Math.max(0, mCurrentAdapterIndex - mSideBuffer); i < Math.min(mAdapter.getCount(), mCurrentAdapterIndex + mSideBuffer + 1); i++) {
            mLoadedViews.addLast(makeAndAddView(i, true, null));
            if (i == mCurrentAdapterIndex) {
                mCurrentBufferIndex = mLoadedViews.size() - 1;
            } 
        } 
        logBuffer(); 
        requestLayout();
    } 
 
    private void postViewSwitched(int direction) {
        if (direction == 0) {
            return; 
        } 
 
        if (direction > 0) { // to the right
            mCurrentAdapterIndex++;
            mCurrentBufferIndex++;
 
            View recycleView = null;
 
            // Remove view outside buffer range 
            if (mCurrentAdapterIndex > mSideBuffer) {
                recycleView = mLoadedViews.removeFirst();
                detachViewFromParent(recycleView);
                // removeView(recycleView); 
                mCurrentBufferIndex--;
            } 
 
            // Add new view to buffer 
            int newBufferIndex = mCurrentAdapterIndex + mSideBuffer;
            if (newBufferIndex < mAdapter.getCount()) {
                mLoadedViews.addLast(makeAndAddView(newBufferIndex, true, recycleView));
            } 
 
        } else { // to the left 
            mCurrentAdapterIndex--;
            mCurrentBufferIndex--;
            View recycleView = null;
 
            // Remove view outside buffer range 
            if (mAdapter.getCount() - 1 - mCurrentAdapterIndex > mSideBuffer) {
                recycleView = mLoadedViews.removeLast();
                detachViewFromParent(recycleView);
            } 
 
            // Add new view to buffer 
            int newBufferIndex = mCurrentAdapterIndex - mSideBuffer;
            if (newBufferIndex > -1) {
                mLoadedViews.addFirst(makeAndAddView(newBufferIndex, false, recycleView));
                mCurrentBufferIndex++;
            } 
        } 
 
        requestLayout();
        setVisibleView(mCurrentBufferIndex, true);
        if (mIndicator != null) {
            mIndicator.onSwitched(mLoadedViews.get(mCurrentBufferIndex), mCurrentAdapterIndex);
        } 
        if (mViewSwitchListener != null) {
            mViewSwitchListener.onSwitched(mLoadedViews.get(mCurrentBufferIndex), mCurrentAdapterIndex);
        } 
        logBuffer(); 
    } 
 
    private View setupChild(View child, boolean addToEnd, boolean recycle) {
        ViewGroup.LayoutParams p = child.getLayoutParams();
        if (p == null) {
            p = new AbsListView.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, 0);
        } 
        if (recycle)
            attachViewToParent(child, (addToEnd ? -1 : 0), p);
        else 
            addViewInLayout(child, (addToEnd ? -1 : 0), p, true);
        return child;
    } 
 
    private View makeAndAddView(int position, boolean addToEnd, View convertView) {
        View view = mAdapter.getView(position, convertView, this);
        return setupChild(view, addToEnd, convertView != null);
    } 
 
    class AdapterDataSetObserver extends DataSetObserver {
 
        @Override 
        public void onChanged() { 
            View v = getChildAt(mCurrentBufferIndex);
            if (v != null) {
                for (int index = 0; index < mAdapter.getCount(); index++) {
                    if (v.equals(mAdapter.getItem(index))) {
                        mCurrentAdapterIndex = index;
                        break; 
                    } 
                } 
            } 
            resetFocus(); 
        } 
 
        @Override 
        public void onInvalidated() { 
            // Not yet implemented! 
        } 
    } 
 
    private void logBuffer() { 
        Log.d("FlowView", "Size of mLoadedViews: " + mLoadedViews.size() + ", X: " + mScroller.getCurrX() + ", Y: " + mScroller.getCurrY());
        Log.d("FlowView", "IndexInAdapter: " + mCurrentAdapterIndex + ", IndexInBuffer: " + mCurrentBufferIndex);
    } 
 
    /** */ 
    private OnScrollListener onScrollListener;