zoukankan      html  css  js  c++  java
  • android实现左右滑动菜单

    直接看效果图:

         

    主要实现代码:

    package com.way.view;
    
    import android.content.Context;
    import android.media.DeniedByServerException;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.view.MotionEvent;
    import android.view.View;
    import android.view.ViewConfiguration;
    import android.view.WindowManager;
    import android.view.animation.AnimationUtils;
    import android.widget.LinearLayout;
    import android.widget.RelativeLayout;
    import android.widget.Scroller;
    
    public class HomeCenterLayout extends RelativeLayout {
    
        private final static String TAG = "HomeCenterLayout";
    
        public static final int LEFT = 0x001;
    
        public static final int RIGHT = 0x002;
    
        public static final int MIDDLE = 0x000;
    
        private int mCurState = MIDDLE;// 当前显示的view
    
        public int MENU_border_Width = 100;  
    
        private Scroller mScroller;
    
        private RelativeLayout leftLayout, rightLayout, childLayout;
    
        private Context context;
    
        private boolean fling;
    
        private boolean mIsBeingDragged = false;
    
        private int mTouchSlop;
        /**
         * Position of the last motion event.
         */
        private float mLastMotionX, mLastMotionY;
    
        /**
         * ID of the active pointer. This is used to retain consistency during
         * drags/flings if multiple pointers are used.
         */
        private int mActivePointerId = INVALID_POINTER;
    
        /**
         * Sentinel value for no current active pointer. Used by
         * {@link #mActivePointerId}.
         */
        private static final int INVALID_POINTER = -1;
    
        int menuWidth = 0;
        int moveWidth = 0;
    
        public HomeCenterLayout(Context context, AttributeSet attrs) {
            super(context, attrs);
            initView(context);
        }
    
        public HomeCenterLayout(Context context) {
            super(context);
            initView(context);
        }
    
        public Scroller getScroller() {
            return mScroller;
        }
    
        public void initView(Context context) {
            MENU_border_Width = DensityUtils.dp2px(context, 100);
            this.context = context;
            this.menuWidth = MENU_border_Width;
            this.mScroller = new Scroller(context, AnimationUtils.loadInterpolator(
                    context, android.R.anim.overshoot_interpolator));
    
            final ViewConfiguration configuration = ViewConfiguration.get(context);
            mTouchSlop = configuration.getScaledTouchSlop();
            mCurState = MIDDLE;
        }
    
        public void addChildView(View child) {
            this.childLayout.addView(child);
        }
    
        /**
         * 获取屏幕宽度
         * 
         * @param context
         * @return
         */
        private int getViewWidthInPix(Context context) {
            int viewWidthInPix = -1;
            if (viewWidthInPix == -1) {
                WindowManager manager = (WindowManager) context
                        .getSystemService(Context.WINDOW_SERVICE);
                viewWidthInPix = manager.getDefaultDisplay().getWidth();
            }
            return viewWidthInPix;
        }
    
        @Override
        protected void onLayout(boolean changed, int left, int top, int right,
                int bottom) {
            super.onLayout(changed, left, top, right, bottom);
    
            for (int i = 0; i < getChildCount(); i++) {
                View child = getChildAt(i);
                child.layout(child.getLeft() + moveWidth, child.getTop(),
                        child.getRight() + moveWidth, child.getBottom());
            }
    
        }
    
        @Override
        public void computeScroll() {
            if (mScroller.computeScrollOffset()) {
                scrollTo(mScroller.getCurrX(), 0);
                postInvalidate();
            }
        }
    
        @Override
        public boolean onInterceptTouchEvent(MotionEvent ev) {
            // TODO Auto-generated method stub
            // Log.i(TAG, "onInterceptTouchEvent------>" + ev.getAction());
            final int action = ev.getAction();
            if ((action == MotionEvent.ACTION_MOVE) && (mIsBeingDragged)) {
                return true;// 拦截不传递给child view
            }
    
            switch (action & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN: {
                final float x = ev.getX();
                final float y = ev.getY();
                if (!inChild((int) x, (int) y)) {
                    mIsBeingDragged = false;
                    break;
                    // 超出边界,return false传递给子view处理
                }
    
                /*
                 * Remember location of down touch. ACTION_DOWN always refers to
                 * pointer index 0.
                 */
                mLastMotionX = x;
                mLastMotionY = y;
                mActivePointerId = ev.getPointerId(0);
    
                /*
                 * If being flinged and user touches the screen, initiate drag;
                 * otherwise don't. mScroller.isFinished should be false when being
                 * flinged.
                 */
                mIsBeingDragged = !mScroller.isFinished();
                break;
            }
            case MotionEvent.ACTION_MOVE: {
                /*
                 * mIsBeingDragged == false, otherwise the shortcut would have
                 * caught it. Check whether the user has moved far enough from his
                 * original down touch.
                 */
    
                /*
                 * Locally do absolute value. mLastMotionY is set to the y value of
                 * the down event.
                 */
                final int activePointerId = mActivePointerId;
                if (activePointerId == INVALID_POINTER) {
                    // If we don't have a valid id, the touch down wasn't on
                    // content.
                    break;
                }
    
                final int pointerIndex = ev.findPointerIndex(activePointerId);
                final float x = ev.getX(pointerIndex);
                final float y = ev.getY(pointerIndex);
                final int xDiff = (int) Math.abs(x - mLastMotionX);
                final int yDiff = (int) Math.abs(y - mLastMotionY);
                if (xDiff > mTouchSlop && yDiff < xDiff) {
                    mIsBeingDragged = true;
                }
                break;
            }
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
                mIsBeingDragged = false;
                mActivePointerId = INVALID_POINTER;
                scrollToScreen();
                break;
            }
            return mIsBeingDragged;
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent event) {
    
            // Log.i(TAG, "onTouchEvent ---->>>>>" + event.getAction());
            if (event.getAction() == MotionEvent.ACTION_DOWN
                    && !inChild((int) event.getX(), (int) event.getY())) {
                // Don't handle edge touches immediately -- they may actually belong
                // to one of our
                // descendants.
                return false;
            }
    
            switch (event.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:
                return true; // 本VIEW消化掉
    
            case MotionEvent.ACTION_MOVE:
                final int activePointerIndex = event
                        .findPointerIndex(mActivePointerId);
    
                final float x = event.getX(activePointerIndex);
                final float y = event.getY(activePointerIndex);
    
                final int distanceX = (int) /* Math.abs */-(x - mLastMotionX);
    
                // 在滑动过程中,就需要显示新的brotherView,不然显示的还是之前的brotherView,最后松开手时会突然变称新brotherView,影响体验
                if (distanceX < 0 && getScrollX() < 0 && leftLayout != null) {
                    setBrotherVisibility(LEFT);
                } else if (distanceX > 0 && getScrollX() > 0 && rightLayout != null) {
                    setBrotherVisibility(RIGHT);
                } else {
                    setBrotherVisibility(MIDDLE);
                }
    
                scrollBy((int) distanceX, 0);
    
                mLastMotionX = x;
                mLastMotionY = y;
                break;
    
            case MotionEvent.ACTION_UP:
                mIsBeingDragged = false;
                mActivePointerId = INVALID_POINTER;
                scrollToScreen();
                break;
    
            default:
                return super.onTouchEvent(event);
            }
            return mIsBeingDragged;
    
        }
    
        @Override
        protected void onScrollChanged(int l, int t, int oldl, int oldt) {
            // TODO Auto-generated method stub
            super.onScrollChanged(l, t, oldl, oldt);
        }
    
        private void scrollToScreen() {
    
            int scrollDistance = 0;
    
            if (Math.abs(getScrollX()) > getWidth() / 2)
                scrollDistance = (getScrollX() > 0) ? getWidth() - menuWidth
                        - getScrollX() : -(getWidth() - menuWidth - Math
                        .abs(getScrollX()));
            else
                scrollDistance = -getScrollX();
    
            int distance = scrollDistance + getScrollX();
            Log.i(TAG, " distance = " + distance);
            if (distance > 0) {
                mCurState = RIGHT;
            } else if (distance < 0) {
                mCurState = LEFT;
            } else {
                mCurState = MIDDLE;
            }
            mScroller.startScroll(getScrollX(), 0, scrollDistance, 0,
                    Math.abs(scrollDistance) * 2);
            invalidate();
    
        }
    
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
                float velocityY) {
            if (Math.abs(velocityX) > ViewConfiguration.get(context)
                    .getScaledMinimumFlingVelocity()) {
                fling = true;
                scrollToScreen();
            }
    
            return fling;
        }
    
        private boolean inChild(int x, int y) {
            if (getChildCount() > 0) {
                final int scrollX = mScroller.getCurrX();
                final View child = getChildAt(0);
    
                return !(scrollX + x < 0 || scrollX + x > getWidth() || y < 0 || y > getHeight());
    
            }
            return false;
        }
    
        /**
         * 设置当前显示的view
         * 
         * @param whichpg
         */
        public void setPage(int whichpg) {
            int targetX = 0, moveDistance = 0;
    
            if (whichpg == LEFT) {
                targetX = -(getViewWidthInPix(context) - menuWidth);
                mCurState = LEFT;
            } else if (whichpg == RIGHT) {
                targetX = getViewWidthInPix(context) - menuWidth;
                mCurState = RIGHT;
            } else {
                mCurState = MIDDLE;
            }
            setBrotherVisibility(whichpg);
            moveDistance = targetX - getScrollX();
            mScroller.startScroll(getScrollX(), 0, moveDistance, 0,
                    Math.abs(moveDistance) * 2);
            invalidate();
        }
    
        /**
         * 返回当前显示的view
         * 
         * @return
         */
        public int getPage() {
            return mCurState;
        }
    
        /**
         * 设置BrotherView
         * 
         * @param left
         * @param right
         */
        public void setBrotherLayout(RelativeLayout left, RelativeLayout right) {
            this.leftLayout = left;
            this.rightLayout = right;
        }
    
        /**
         * 根据当前状态显示或隐藏view
         * 
         * @param state
         */
        private void setBrotherVisibility(int state) {
            switch (state) {
            case LEFT:
                rightLayout.setVisibility(View.GONE);
                leftLayout.setVisibility(View.VISIBLE);
                break;
            case RIGHT:
                rightLayout.setVisibility(View.VISIBLE);
                leftLayout.setVisibility(View.GONE);
                break;
            case MIDDLE:
                break;
            default:
                break;
            }
        }
    }

    xml:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical" >
    
        <FrameLayout
            android:layout_width="fill_parent"
            android:layout_height="fill_parent" >
    
            <RelativeLayout
                android:id="@+id/homeLeft"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:background="@drawable/friend_list_bg_repeat" >
                <TextView 
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:text="hhhhh"
                    android:gravity="center"
                    android:textSize="18sp"
                    android:textColor="#fff"/>
            </RelativeLayout>
    
            <RelativeLayout
                android:id="@+id/homeRight"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:layout_marginLeft="30dp"
                 >
    
                <ImageView
                    android:id="@+id/iv1"
                    android:layout_width="wrap_content"
                    android:layout_height="0dp"
                    android:layout_weight="1"
                    android:scaleType="center"
                    android:src="@drawable/bg" />
    
                <ImageView
                    android:id="@+id/iv"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:src="@drawable/bottom" />
            </RelativeLayout>
    
            <com.way.view.HomeCenterLayout
                android:id="@+id/homeCenter"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent" >
        <!-- 特别注意: HomeCenterLayout标签下面是不能放背景的,否则你看看效果-->
                <LinearLayout
                    android:layout_width="fill_parent"
                    android:layout_height="fill_parent"
                    android:background="@android:color/darker_gray" >
    
                    <include layout="@layout/common_title_bg" />
                </LinearLayout>
            </com.way.view.HomeCenterLayout>
        </FrameLayout>
    
    </RelativeLayout>

    demo下载地址:http://files.cnblogs.com/files/feijian/QQmini2.rar

  • 相关阅读:
    MySQL DDL 在指定位置新增字段
    .NET平台常见技术框架整理汇总
    使用Linq求和方法Sum计算集合中多个元素和时应该注意的性能问题
    python时间操作
    django 利用原生sql操作数据库
    滑动验证码获取像素偏移量
    python opencv简单使用
    django通过旧数据库库生成models
    pandas 操作csv文件
    简单工厂模式(Simple Factory Pattern)
  • 原文地址:https://www.cnblogs.com/feijian/p/4589276.html
Copyright © 2011-2022 走看看