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下载地址:https://files.cnblogs.com/files/feijian/QQmini2.rar

 

posted @ 2015-06-19 17:14  飞剑  阅读(997)  评论(0编辑  收藏  举报