在好例子网,分享、交流、成长!
您当前所在位置:首页Java 开发实例Android平台开发 → android 可横向滚动的viewgroup 例子源码下载

android 可横向滚动的viewgroup 例子源码下载

Android平台开发

下载此实例
  • 开发语言:Java
  • 实例大小:9.76M
  • 下载次数:9
  • 浏览次数:283
  • 发布时间:2015-05-09
  • 实例类别:Android平台开发
  • 发 布 人:crazycode
  • 文件格式:.zip
  • 所需积分:2
 相关标签: Android 滚动 viewgroup

实例介绍

【实例简介】

【实例截图】

【核心代码】


import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.Scroller;

/**
 * @author Administrator
 * 
 */
public class ScrollableViewGroup extends ViewGroup {

        private static final int INVALID_SCREEN = -1;
        private static final int TOUCH_STATE_REST = 0;
        private static final int TOUCH_STATE_SCROLLING = 1;
        private static final int SNAP_VELOCITY = 1000;

        private int mDefaultScreen;
        private int mCurrentScreen;
        private int mNextScreen = INVALID_SCREEN;

        private int mMaximumVelocity;
        private Scroller mScroller;
        private int mTouchState;
        private boolean mFirstLayout = true;
        private float mLastMotionX;
        private float mLastMotionY;
        private int mTouchSlop;
        private boolean mAllowLongPress;
        private VelocityTracker mVelocityTracker;

        private int mPaintFlag = 0;

        private OnCurrentViewChangedListener mOnCurrentViewChangedListener;

        public interface OnCurrentViewChangedListener {
                public void onCurrentViewChanged(View view, int currentview);
        };

        /**
         * @param context
         */
        public ScrollableViewGroup(Context context) {
                super(context);
                initViewGroup();
        }

        /**
         * @param context
         * @param attrs
         */
        public ScrollableViewGroup(Context context, AttributeSet attrs) {
                super(context, attrs);
                initViewGroup();
        }

        /**
         * @param context
         * @param attrs
         * @param defStyle
         */
        public ScrollableViewGroup(Context context, AttributeSet attrs, int defStyle) {
                super(context, attrs, defStyle);
                initViewGroup();
        }

        /*
         * (non-Javadoc)
         * 
         * @see android.view.ViewGroup#onLayout(boolean, int, int, int, int)
         */
        @Override
        protected void onLayout(boolean changed, int l, int t, int r, int b) {
                int childLeft = 0;
                final int count = getChildCount();
                for (int i = 0; i < count; i  ) {
                        final View child = getChildAt(i);
                        if (child.getVisibility() != View.GONE) {
                                final int childWidth = child.getMeasuredWidth();
                                child.layout(childLeft, 0, childLeft   childWidth, child
                                                .getMeasuredHeight());
                                childLeft  = childWidth;
                        }
                }
        }

        /**
         * Initializes various states for this viewgroup.
         */
        private void initViewGroup() {
                mScroller = new Scroller(getContext());
                mCurrentScreen = mDefaultScreen;
                final ViewConfiguration configuration = ViewConfiguration
                                .get(getContext());
                mTouchSlop = configuration.getScaledTouchSlop();

                // mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
        }

        public boolean isDefaultViewShowing() {
                return mCurrentScreen == mDefaultScreen;
        }

        public int getCurrentView() {
                return mCurrentScreen;
        }

        public void setCurrentView(int currentView) {
                // snapToScreen(currentView);
                mCurrentScreen = Math
                                .max(0, Math.min(currentView, getChildCount() - 1));
                scrollTo(mCurrentScreen * getWidth(), 0);
                if (mOnCurrentViewChangedListener != null)
                        mOnCurrentViewChangedListener.onCurrentViewChanged(this,
                                        mCurrentScreen);
                invalidate();
        }

        /*
         * (non-Javadoc)
         * 
         * @see android.view.View#computeScroll()
         */
        @Override
        public void computeScroll() {
        //	Log.d("Curt", "computeScroll");
                if (mScroller.computeScrollOffset()) {
                        // FIXED 鍗峰姩鏃犳硶瑙﹀彂涓嬫鐨刢omputeScroll;
                        final int currx = mScroller.getCurrX(), curry = mScroller
                                        .getCurrY(), scrx = getScrollX(), scry = getScrollY();

                        if (currx != scrx || curry != scry)
                                scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
                        else
                                invalidate();
                } else if (mNextScreen != INVALID_SCREEN) {
                        mCurrentScreen = Math.max(0, Math.min(mNextScreen,
                                        getChildCount() - 1));
                        mNextScreen = INVALID_SCREEN;
                        mPaintFlag = 0;
                        clearChildrenCache();
                        final int scrx = getScrollX(), scry = getScrollY(), mCurrentScrollX = mCurrentScreen
                                        * getWidth();
                        if (scrx != mCurrentScrollX)
                                scrollTo(mCurrentScrollX, scry);
                        if (mOnCurrentViewChangedListener != null)
                                mOnCurrentViewChangedListener.onCurrentViewChanged(this,
                                                mCurrentScreen);
                }
        }

        /*
         * (non-Javadoc)
         * 
         * @see android.view.ViewGroup#dispatchDraw(android.graphics.Canvas)
         */
        @Override
        protected void dispatchDraw(Canvas canvas) {
                boolean fastDraw = mTouchState != TOUCH_STATE_SCROLLING
                                && mNextScreen == INVALID_SCREEN;
                // If we are not scrolling or flinging, draw only the current screen
                if (fastDraw) {
                        drawChild(canvas, getChildAt(mCurrentScreen), getDrawingTime());
                } else {
                        final long drawingTime = getDrawingTime();
                        // If we are flinging, draw only the current screen and the target
                        // screen
                        if (mNextScreen >= 0
                                        && mNextScreen < getChildCount()
                                        && (Math.abs(mCurrentScreen - mNextScreen) == 1 || mPaintFlag != 0)) {
                                final View viewCurrent = getChildAt(mCurrentScreen), viewNext = getChildAt(mNextScreen);

                                drawChild(canvas, viewCurrent, drawingTime);
                                if (mPaintFlag == 0) {
                                        drawChild(canvas, viewNext, drawingTime);
                                } else {
                                        Paint paint = new Paint();
                                        if (mPaintFlag < 0) {
                                                canvas.drawBitmap(viewNext.getDrawingCache(), -viewNext
                                                                .getWidth(), viewNext.getTop(), paint);
                                        } else {
                                                canvas.drawBitmap(viewNext.getDrawingCache(),
                                                                getWidth() * getChildCount(),
                                                                viewNext.getTop(), paint);
                                        }
                                }
                        } else {
                                // If we are scrolling, draw all of our children
                                final int count = getChildCount();
                                for (int i = 0; i < count; i  ) {
                                        drawChild(canvas, getChildAt(i), drawingTime);
                                }

                                if (mPaintFlag != 0) {
                                        final View viewNext;
                                        Paint paint = new Paint();
                                        if (mPaintFlag < 0) {
                                                viewNext = getChildAt(getChildCount() - 1);
                                           //     Log.d("Curt", "dispatchDraw: "   viewNext.getDrawingCache());
                                                if (viewNext.getDrawingCache() == null) {
                                                	viewNext.buildDrawingCache();
                                                }
                                                canvas.drawBitmap(viewNext.getDrawingCache(), -viewNext
                                                                .getWidth(), viewNext.getTop(), paint);
                                        } else {
                                                viewNext = getChildAt(0);
                                                canvas.drawBitmap(viewNext.getDrawingCache(),
                                                                getWidth() * getChildCount(),
                                                                viewNext.getTop(), paint);
                                        }
                                }
                        }
                }
        }

        /*
         * (non-Javadoc)
         * 
         * @see android.view.View#onMeasure(int, int)
         */
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
                super.onMeasure(widthMeasureSpec, heightMeasureSpec);
                final int width = MeasureSpec.getSize(widthMeasureSpec);
                final int count = getChildCount();
                for (int i = 0; i < count; i  ) {
                        getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec);
                }

                if (mFirstLayout) {
                        scrollTo(mCurrentScreen * width, 0);
                        mFirstLayout = false;
                }
        }

        /*
         * (non-Javadoc)
         * 
         * @see
         * android.view.ViewGroup#requestChildRectangleOnScreen(android.view.View,
         * android.graphics.Rect, boolean)
         */
        @Override
        public boolean requestChildRectangleOnScreen(View child, Rect rectangle,
                        boolean immediate) {
                int screen = indexOfChild(child);
                if (screen != mCurrentScreen || !mScroller.isFinished()) {
                        snapToScreen(screen);
                        return true;
                }
                return false;
        }

        /*
         * (non-Javadoc)
         * 
         * @see android.view.ViewGroup#onRequestFocusInDescendants(int,
         * android.graphics.Rect)
         */
        @Override
        protected boolean onRequestFocusInDescendants(int direction,
                        Rect previouslyFocusedRect) {
                int focusableScreen;
                if (mNextScreen != INVALID_SCREEN) {
                        focusableScreen = mNextScreen;
                } else {
                        focusableScreen = mCurrentScreen;
                }
         //       Log.d("Curt", "onRequestFocusInDescendants: "   focusableScreen);
                boolean log = getChildAt(focusableScreen).requestFocus(direction,
                                previouslyFocusedRect);
         //       Log.d("Curt", "onRequestFocusInDescendants"   log);
                return false;
        }

        /*
         * (non-Javadoc)
         * 
         * @see android.view.ViewGroup#dispatchUnhandledMove(android.view.View, int)
         */
        @Override
        public boolean dispatchUnhandledMove(View focused, int direction) {
                if (direction == View.FOCUS_LEFT) {
                        if (getCurrentView() > 0) {
                                snapToScreen(getCurrentView() - 1);
                                return true;
                        }
                } else if (direction == View.FOCUS_RIGHT) {
                        if (getCurrentView() < getChildCount() - 1) {
                                snapToScreen(getCurrentView()   1);
                                return true;
                        }
                }
                return super.dispatchUnhandledMove(focused, direction);
        }

        /*
         * (non-Javadoc)
         * 
         * @see
         * android.view.ViewGroup#onInterceptTouchEvent(android.view.MotionEvent)
         */
        @Override
        public boolean onInterceptTouchEvent(MotionEvent ev) {
        //	    Log.d("Curt", "onInterceptTouchEvent");
                final int action = ev.getAction();
                if ((action == MotionEvent.ACTION_MOVE)
                                && (mTouchState != TOUCH_STATE_REST)) {
                        return true;
                }

                final float x = ev.getX();
                final float y = ev.getY();

                switch (action) {
                case MotionEvent.ACTION_MOVE:
                        final int xDiff = (int) Math.abs(x - mLastMotionX);
                        final int yDiff = (int) Math.abs(y - mLastMotionY);

                        final int touchSlop = mTouchSlop;
                        boolean xMoved = xDiff > touchSlop;
                        boolean yMoved = yDiff > touchSlop;

                        if (xMoved || yMoved) {

                                if (xMoved) {
                                        // Scroll if the user moved far enough along the X axis
                                        mTouchState = TOUCH_STATE_SCROLLING;
                                        enableChildrenCache();
                                }
                                // Either way, cancel any pending longpress
                                if (mAllowLongPress) {
                                        mAllowLongPress = false;
                                        // Try canceling the long press. It could also have been
                                        // scheduled
                                        // by a distant descendant, so use the mAllowLongPress flag
                                        // to block
                                        // everything
                                        final View currentScreen = getChildAt(mCurrentScreen);
                                        currentScreen.cancelLongPress();
                                }
                        }
                        break;

                case MotionEvent.ACTION_DOWN:
                        // Remember location of down touch
                        mLastMotionX = x;
                        mLastMotionY = y;
                        mAllowLongPress = true;

                        /*
                         * If being flinged and user touches the screen, initiate drag;
                         * otherwise don't. mScroller.isFinished should be false when being
                         * flinged.
                         */
                        mTouchState = mScroller.isFinished() ? TOUCH_STATE_REST
                                        : TOUCH_STATE_SCROLLING;
                        break;

                case MotionEvent.ACTION_CANCEL:
                case MotionEvent.ACTION_UP:
                        mTouchState = TOUCH_STATE_REST;
                        mAllowLongPress = false;
                        break;
                }
                /*
                 * The only time we want to intercept motion events is if we are in the
                 * drag mode.
                 */
                return mTouchState != TOUCH_STATE_REST;
        }

        void enableChildrenCache() {
                final int count = getChildCount();
                for (int i = 0; i < count; i  ) {
                        final View layout = getChildAt(i);
                        layout.setDrawingCacheEnabled(true);
                        if (layout instanceof ViewGroup) {
                                ((ViewGroup) layout).setAlwaysDrawnWithCacheEnabled(true);
                        }
                }
        }

        void clearChildrenCache() {
                final int count = getChildCount();
                for (int i = 0; i < count; i  ) {
                        final View layout = getChildAt(i);
                        if (layout instanceof ViewGroup) {
                                ((ViewGroup) layout).setAlwaysDrawnWithCacheEnabled(false);
                        }
                }
        }

        /*
         * (non-Javadoc)
         * 
         * @see android.view.View#onTouchEvent(android.view.MotionEvent)
         */
        @Override
        public boolean onTouchEvent(MotionEvent event) {
        	
                if (mVelocityTracker == null) {
                        mVelocityTracker = VelocityTracker.obtain();
                }
                mVelocityTracker.addMovement(event);

                final int action = event.getAction();
                final float x = event.getX();

                switch (action) {
                case MotionEvent.ACTION_DOWN:
                        /*
                         * If being flinged and user touches, stop the fling. isFinished
                         * will be false if being flinged.
                         */
                        if (!mScroller.isFinished()) {
                                mScroller.abortAnimation();
                        }

                        // Remember where the motion event started
                        mLastMotionX = x;
                        mTouchState = TOUCH_STATE_SCROLLING;
                        break;
                case MotionEvent.ACTION_MOVE:
               // 	Log.d("Curt", "move : "   mTouchState);
                        if (mTouchState == TOUCH_STATE_SCROLLING) {
                                // Scroll to follow the motion event
                                final int deltaX = (int) (mLastMotionX - x);
                                mLastMotionX = x;

                                if (deltaX < 0) {
                                        /*
                                         * if (getScrollX() > 0) { scrollBy(Math.max(-getScrollX(),
                                         * deltaX), 0); }
                                         */
                                        if (getScrollX() <= 0) {
                                                mPaintFlag = -1;
                                        }
                                        scrollBy(deltaX, 0);
                                } else if (deltaX > 0) {
                                        int availableToScroll = getChildAt(getChildCount() - 1)
                                                        .getRight()
                                                        - getScrollX() - getWidth();
                                        /*
                                         * if (availableToScroll > 0) {
                                         * scrollBy(Math.min(availableToScroll, deltaX), 0); }
                                         */
                                        if (availableToScroll <= 0) {
                                                mPaintFlag = 1;
                                                availableToScroll  = getWidth() << 1;
                                        }
                                        if (availableToScroll > 0)
                                                scrollBy(Math.min(availableToScroll, deltaX), 0);
                                }
                        }
                        break;
                case MotionEvent.ACTION_UP:
                        if (mTouchState == TOUCH_STATE_SCROLLING) {
                                final VelocityTracker velocityTracker = mVelocityTracker;
                                // velocityTracker.computeCurrentVelocity(1000,
                                // mMaximumVelocity);
                                int velocityX = (int) velocityTracker.getXVelocity();

                                if (velocityX > SNAP_VELOCITY && mCurrentScreen > 0) {
                                        // Fling hard enough to move left
                                        snapToScreen(mCurrentScreen - 1);
                                } else if (velocityX < -SNAP_VELOCITY
                                                && mCurrentScreen < getChildCount() - 1) {
                                        // Fling hard enough to move right
                                        snapToScreen(mCurrentScreen   1);
                                } else {
                                        snapToDestination();
                                }

                                if (mVelocityTracker != null) {
                                        mVelocityTracker.recycle();
                                        mVelocityTracker = null;
                                }
                        }
                        mTouchState = TOUCH_STATE_REST;
                        break;
                case MotionEvent.ACTION_CANCEL:
                //	Log.d("Curt", "cancel");
                        mTouchState = TOUCH_STATE_REST;
                }

                return true;
        }

        private void snapToDestination() {
                final int screenWidth = getWidth();
                final int scrollWidth = getScrollX()   (screenWidth >> 1);
                final int viewCount = getChildCount();
                final int whichScreen;
                if (scrollWidth < 0)
                        whichScreen = -1;
                else if (scrollWidth > screenWidth * viewCount)
                        whichScreen = viewCount;
                else
                        whichScreen = (getScrollX()   (screenWidth / 2)) / screenWidth;
                snapToScreen(whichScreen);
        }

        public void snapToScreen(int whichScreen) {
        	    // Log.d("Curt", "snapToScreen");
        	    if (whichScreen != mCurrentScreen) {
        	    	View child = getChildAt(mCurrentScreen);
        	    	if (child instanceof ImageViewTouch) {
        	    		ImageViewTouch touch = (ImageViewTouch) child;
        	    		if (touch.isSmaller) {
        	    		    touch.zoomTo(1.0f);
        	    		    touch.isSmaller = false;
        	    		}
        	    	}
        	    } else {
        	    	View child = getChildAt(mCurrentScreen);
        	    	if (child instanceof ImageViewTouch) {
        	    		ImageViewTouch touch = (ImageViewTouch) child;
        	    		if (touch.isSmaller) {
        	    		    touch.zoomTo(1.0f);
        	    		    touch.isSmaller = false;
        	    		}
        	    	}
        	    }
                if (!mScroller.isFinished())
                        return;
                enableChildrenCache();
                final int viewCount = getChildCount() - 1;

                final int oldWhichScreen = whichScreen;

                if (whichScreen < 0) {
                        whichScreen = viewCount;
                        mPaintFlag = -1; // next screen should be painted before current
                } else if (whichScreen > viewCount) {
                        whichScreen = 0;
                        mPaintFlag = 1;
                } else
                        mPaintFlag = 0;

                // whichScreen = Math.max(0, Math.min(whichScreen, getChildCount() -
                // 1));
                boolean changingScreens = whichScreen != mCurrentScreen;

                mNextScreen = whichScreen;

                
                View focusedChild = getFocusedChild();
                Log.d("Curt", "snapToScreen: Child is: "   focusedChild);
                if (focusedChild != null && changingScreens
                                && focusedChild == getChildAt(mCurrentScreen)) {
                        focusedChild.clearFocus();
                }
                //getChildAt(mCurrentScreen).requestFocus();
                //Log.d("Curt", "snapToScreen: "   mCurrentScreen);
                final int newX = oldWhichScreen * getWidth();
                final int delta = newX - getScrollX();
                mScroller.startScroll(getScrollX(), 0, delta, 0, Math.abs(delta) * 2);

                invalidate();
                
                /*
                 * if (!mScroller.isFinished()) return; enableChildrenCache();
                 * 
                 * whichScreen = Math.max(0, Math.min(whichScreen, getChildCount() -
                 * 1)); boolean changingScreens = whichScreen != mCurrentScreen;
                 * 
                 * mNextScreen = whichScreen;
                 * 
                 * View focusedChild = getFocusedChild(); if (focusedChild != null &&
                 * changingScreens && focusedChild == getChildAt(mCurrentScreen)) {
                 * focusedChild.clearFocus(); }
                 * 
                 * final int newX = whichScreen * getWidth(); final int delta = newX -
                 * getScrollX(); mScroller.startScroll(getScrollX(), 0, delta, 0,
                 * Math.abs(delta) * 2);
                 * 
                 * invalidate();
                 */}

        public void scrollLeft() {
                if (mNextScreen == INVALID_SCREEN && mCurrentScreen > 0
                                && mScroller.isFinished()) {
                        snapToScreen(mCurrentScreen - 1);
                }
        }

        public void scrollRight() {
                if (mNextScreen == INVALID_SCREEN
                                && mCurrentScreen < getChildCount() - 1
                                && mScroller.isFinished()) {
                        snapToScreen(mCurrentScreen   1);
                }
        }

        public void moveToDefaultScreen() {
                snapToScreen(mDefaultScreen);
                getChildAt(mDefaultScreen).requestFocus();
        }

        public boolean isScrollFinish() {
                return mTouchState != TOUCH_STATE_SCROLLING
                                && mNextScreen == INVALID_SCREEN;
                // return mScroller.isFinished();
        }

        public OnCurrentViewChangedListener getOnCurrentViewChangedListener() {
                return mOnCurrentViewChangedListener;
        }

        public void setOnCurrentViewChangedListener(
                        OnCurrentViewChangedListener mOnCurrentViewChangedListener) {
                this.mOnCurrentViewChangedListener = mOnCurrentViewChangedListener;
        }
}


实例下载地址

android 可横向滚动的viewgroup 例子源码下载

不能下载?内容有错? 点击这里报错 + 投诉 + 提问

好例子网口号:伸出你的我的手 — 分享

网友评论

发表评论

(您的评论需要经过审核才能显示)

查看所有0条评论>>

小贴士

感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。

  • 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
  • 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
  • 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
  • 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。

关于好例子网

本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明

;
报警