当前位置: 代码迷 >> Android >> 怎么实现类似Path、海豚浏览器、人人那样的横向侧滑导航栏?求解
  详细解决方案

怎么实现类似Path、海豚浏览器、人人那样的横向侧滑导航栏?求解

热度:65   发布时间:2016-05-01 18:03:08.0
如何实现类似Path、海豚浏览器、人人那样的横向侧滑导航栏?求解~
最近要做一个类似Path、海豚浏览器、人人那样的横向侧滑导航栏 

这个效果最早应该是在pad上用的比较多,现在手机端也逐渐开始流行起来了,

但是发现网上没有相关资料,不太清楚具体是怎么实现的,

开始觉得是用SlidingDrawer抽屉做的,但是发现抽屉没办法在收起的时候多留出一块,只能在收起时完全隐藏,同时在拉出抽屉时下面的页面是保持不动,不像海豚浏览器的收藏页面,有那种页面顶出屏幕的效果。


不知道哪位高手做过这个效果,能否分享一下或者给点思路,谢谢啦~~




------解决方案--------------------
那你就判断ScrollView的move事件以及方向噢,然后强制滑动到指定位置即可。
------解决方案--------------------
Java code
/** * 包裹在该布局内部的子视图可以左右滑动<br> * @author http://blog.csdn.net/Yao_GUET date: 2011-05-04 */public class HorizonalScrollLayout extends LinearLayout {        /**     * 通过Handler将滑屏结果通知使用该滑屏控件的Activity<br>     * 必须先调用<br><code>public void setHandler(Handler handler) </code><br>来设置handler.返回的消息为:<br>     * <code>     * Message msg = new Message();<br>        msg.what = ON_SCROLL_CHANGED_MESSAGE_WHAT;<br>        msg.arg1 = whichScreen;//滑到的目标屏幕索引(0为第一个屏幕)<br>        handler.sendMessage(msg);<br>     *      * </code>     */    public static final int ON_SCROLL_CHANGED_MESSAGE_WHAT = 2087;    private static final String TAG = "HorizonalScrollLayout";    private Scroller mScroller;    private VelocityTracker mVelocityTracker;    private int mCurScreen;    private int mDefaultScreen = 0;    private static final int TOUCH_STATE_REST = 0;    private static final int TOUCH_STATE_SCROLLING = 1;    private static final int SNAP_VELOCITY = 600;    private int mTouchState = TOUCH_STATE_REST;    private int mTouchSlop;    private float mLastMotionX;    private float mLastMotionY;        private OnSnapDestinationListener onSnapDestinationListener;            Handler handler ;    public HorizonalScrollLayout(Context context, AttributeSet attrs) {        super(context, attrs);        mScroller = new Scroller(context);        mCurScreen = mDefaultScreen;        mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();    }    @Override    protected void onLayout(boolean changed, int l, int t, int r, int b) {//        if (changed) { //如果不注释掉,里面的ListView显示出不来            int childLeft = 0;            final int childCount = getChildCount();            for (int i = 0; i < childCount; i++) {                final View childView = getChildAt(i);                if (childView.getVisibility() != View.GONE) {                    final int childWidth = childView.getMeasuredWidth();                    childView.layout(childLeft, 0, childLeft + childWidth, childView                            .getMeasuredHeight());                    childLeft += childWidth;                }            }//        }    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        final int width = MeasureSpec.getSize(widthMeasureSpec);        final int widthMode = MeasureSpec.getMode(widthMeasureSpec);        if (widthMode != MeasureSpec.EXACTLY) {            throw new IllegalStateException("ScrollLayout only canmCurScreen run at EXACTLY mode!");        }        final int heightMode = MeasureSpec.getMode(heightMeasureSpec);        if (heightMode != MeasureSpec.EXACTLY) {            throw new IllegalStateException("ScrollLayout only can run at EXACTLY mode!");        }        // The children are given the same width and height as the scrollLayout        final int count = getChildCount();        for (int i = 0; i < count; i++) {            getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec);        }        // Log.e(TAG, "moving to screen "+mCurScreen);        scrollTo(mCurScreen * width, 0);    }        public void setOnSnapDestinationListener(OnSnapDestinationListener onSnapDestinationListener) {        this.onSnapDestinationListener = onSnapDestinationListener;    }    /**     * According to the position of current layout scroll to the destination     * page.     */    public void snapToDestination() {        final int screenWidth = getWidth();        final int destScreen = (getScrollX() + screenWidth / 2) / screenWidth;        snapToScreen(destScreen);    }    public void snapToScreen(int whichScreen) {        int tmp = mCurScreen;        // get the valid layout page        whichScreen = Math.max(0, Math.min(whichScreen, getChildCount() - 1));        if (getScrollX() != (whichScreen * getWidth())) {            final int delta = whichScreen * getWidth() - getScrollX();            mScroller.startScroll(getScrollX(), 0, delta, 0, Math.abs(delta));            mCurScreen = whichScreen;            invalidate(); // Redraw the layout        }        if(tmp == whichScreen){            return;        }        if(handler!= null){            Message msg = new Message();            msg.what = ON_SCROLL_CHANGED_MESSAGE_WHAT;            msg.arg1 = whichScreen;            handler.sendMessage(msg);        }    }    public void setToScreen(int whichScreen) {        whichScreen = Math.max(0, Math.min(whichScreen, getChildCount() - 1));        mCurScreen = whichScreen;        scrollTo(whichScreen * getWidth(), 0);        invalidate();    }    public int getCurScreen() {        return mCurScreen;    }    @Override    public void computeScroll() {        if (mScroller.computeScrollOffset()) {            scrollTo(mScroller.getCurrX(), mScroller.getCurrY());            postInvalidate();        }    }    @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();        final float y = event.getY();        switch (action) {        case MotionEvent.ACTION_DOWN://            Log.e(TAG, "event down!");            if (!mScroller.isFinished()) {                mScroller.abortAnimation();            }            mLastMotionX = x;            break;        case MotionEvent.ACTION_MOVE:            int deltaX = (int) (mLastMotionX - x);            mLastMotionX = x;            scrollBy(deltaX, 0);            break;        case MotionEvent.ACTION_UP://            Log.e(TAG, "event : up");            // if (mTouchState == TOUCH_STATE_SCROLLING) {            final VelocityTracker velocityTracker = mVelocityTracker;            velocityTracker.computeCurrentVelocity(1000);            int velocityX = (int) velocityTracker.getXVelocity();//            Log.e(TAG, "velocityX:" + velocityX);            if (velocityX > SNAP_VELOCITY && mCurScreen > 0) {                // Fling enough to move left//                Log.e(TAG, "snap left");                if(onSnapDestinationListener == null || onSnapDestinationListener.isAbleToSnap())                    snapToScreen(mCurScreen - 1);                else                     snapToScreen(mCurScreen);            } else if (velocityX < -SNAP_VELOCITY && mCurScreen < getChildCount() - 1) {                // Fling enough to move right//                Log.e(TAG, "snap right");                if(onSnapDestinationListener == null || onSnapDestinationListener.isAbleToSnap())                    snapToScreen(mCurScreen + 1);                else                     snapToScreen(mCurScreen);            } else {                snapToDestination();            }            if (mVelocityTracker != null) {                mVelocityTracker.recycle();                mVelocityTracker = null;            }            // }            mTouchState = TOUCH_STATE_REST;            break;        case MotionEvent.ACTION_CANCEL:            mTouchState = TOUCH_STATE_REST;            break;        }        return true;    }        public void setHandler(Handler handler) {        this.handler = handler;    }        @Override    public boolean onInterceptTouchEvent(MotionEvent ev) {//        Log.e(TAG, "onInterceptTouchEvent-slop:" + mTouchSlop);        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:                        /*             * 2011.12.29              * 如果内部的子视图有ScrollView,当用户在ScrollView上下滑动的时候,判断如果Y轴变化值大于X轴变化的1.2倍,就不要消费这个事件了             * 否则会导致用户本来是想上下滑动ScrollView 结果这个滑动事件被本视图吸收了,变为左右滑动             */            int deltaX = (int) (mLastMotionX - x);            int deltaY = (int) (mLastMotionY - y);            if(Math.abs(deltaY) > Math.abs(deltaX * 1.2)){                return false;            }            /*             * =========================================             */                        final int xDiff = (int) Math.abs(mLastMotionX - x);            if (xDiff > mTouchSlop) {                mTouchState = TOUCH_STATE_SCROLLING;            }            break;        case MotionEvent.ACTION_DOWN:            mLastMotionX = x;            mLastMotionY = y;            mTouchState = mScroller.isFinished() ? TOUCH_STATE_REST : TOUCH_STATE_SCROLLING;            break;        case MotionEvent.ACTION_CANCEL:        case MotionEvent.ACTION_UP:            mTouchState = TOUCH_STATE_REST;            break;        }        return mTouchState != TOUCH_STATE_REST;    }        public interface OnSnapDestinationListener{                /**         * 当滑到目标屏幕的时间发生之前调用,如果返回false;则不继续         * @return         * @author : wang.jun<br>         * @time : Mar 12, 2012 4:17:24 PM<br>         */        public boolean isAbleToSnap();            }}
  相关解决方案