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

时间: 2024-10-07 01:30:41

android实现左右滑动菜单的相关文章

Android之 左右滑动菜单

近来学习了极客学院有关于界面左右滑动的视频,就在这里写个博客,巩固一下知识点,以免忘了. 这里主要介绍界面是如何左右滑动的: 1.首先我们应该设置好将要滑动的三个界面,即leftMenu.middleMenu.rightMenu三个布局,并且放置好它们的位置,这段大家自己在源码中看 2.当位置放好后,就可以开始关于滑动方面的代码. 页面的滑动是通过点的坐标变化距离来进行来实现的.首先我们定义了20dp来确保最小下限滑动的距离,来确定是否进行了滑动:接着就可以进行判断页面的滑动方向,ACTION_

Android 3D滑动菜单完全解析,实现推拉门式的立体特效

转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/10471245 在上一篇文章中,我们学习了Camera的基本用法,并借助它们编写了一个例子,实现了类似于API Demos里的图片中轴旋转功能.不过那个例子的核心代码是来自于API Demos中带有的Rotate3dAnimation这个类,是它帮助我们完成了所有的三维旋转操作,所有Matrix和Camera相关的代码也是封装在这个类中. 这样说来的话,大家心里会不会痒痒的呢?虽然

Android双向滑动菜单完全解析,教你如何一分钟实现双向滑动特效

转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/9671609 记得在很早之前,我写了一篇关于Android滑动菜单的文章,其中有一个朋友在评论中留言,希望我可以帮他将这个滑动菜单改成双向滑动的方式.当时也没想花太多时间,简单修改了一下就发给了他,结果没想到后来却有一大批的朋友都来问我要这份双向滑动菜单的代码.由于这份代码写得很不用心,我发了部分朋友之后实在不忍心继续发下去了,于是决定专门写一篇文章来介绍更好的Android双向滑

Android 学习笔记之AndBase框架学习(七) SlidingMenu滑动菜单的实现

PS:努力的往前飞..再累也无所谓.. 学习内容: 1.使用SlidingMenu实现滑动菜单..   SlidingMenu滑动菜单..滑动菜单在绝大多数app中也是存在的..非常的实用..Github有位牛人将这个东西书写成了一个简单的框架..我们只需要通过引用相关的资源就能够完成一个滑动菜单的实现..有了这一层的基础..那么滑动菜单就很容易实现了..就拿我们最为熟悉的QQ来说吧..当我们进行滑动操作的时候..会有一个新的View去覆盖原本的View..我们可以通过触发新的视图上的控件来执行

它们的定义android滑动菜单

在这里实现了两个滑动菜单效果,的拖放内容的第一部分,菜单拖出像这样的效果感觉,另一种是拖动内容.后面的内容固定菜单.我感觉有层次感的效果,如下面 第一种效果的代码实现例如以下: package com.tenghu.customsideslip.menu.view; import android.content.Context; import android.os.AsyncTask; import android.util.AttributeSet; import android.util.D

Android 自定义ViewGroup,实现侧方位滑动菜单

侧方位滑动菜单 1.现在adnroid流行的应用当中很多都是用的侧方位滑动菜单如图: 将菜单显示在左边,内容页面显示在右边,通过滑动或则按钮点击来隐藏和显示菜单. 2.首先对ViewGroup进行个了解: View是ViewGroup的父类,ViewGroup具有View的所有特性,ViewGroup主要用用来充当View的容器,将其中的View作为自己孩子, 并对其进行管理,当然孩子也是可以是ViewGroup类型. View类一般用于绘图操作,重写他的onDraw方法,但它不可以包含其他组件

【转】Android双向滑动菜单完全解析,教你如何一分钟实现双向滑动特效

转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/9671609 记得在很早之前,我写了一篇关于Android滑动菜单的文章,其中有一个朋友在评论中留言,希望我可以帮他将这个滑动菜单改成双向滑动的方式.当时也没想花太多时间,简单修改了一下就发给了他,结果没想到后来却有一大批的朋友都来问我要这份双向滑动菜单的代码.由于这份代码写得很不用心,我发了部分朋友之后实在不忍心继续发下去了,于是决定专门写一篇文章来介绍更好的Android双向滑

Android 滑动菜单SlidingMenu

首先我们看下面视图: 这种效果大家都不陌生,网上好多都说是仿人人网的,估计人家牛逼出来的早吧,我也参考了一一些例子,实现起来有三种方法,我下面简单介绍下: 方法一:其实就是对GestureDetector手势的应用及布局文件的设计. 布局文件main.xml    采用RelativeLayout布局. <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android=&quo

android ——滑动菜单

DrawerLayout是一个拥有两个子控件的布局,第一个子控件是主屏幕中显示的内容,第二个子控件是滑动菜单中显示的内容: 1 <android.support.v4.widget.DrawerLayout 2 xmlns:android="http://schemas.android.com/apk/res/android" 3 xmlns:app="http://schemas.android.com/apk/res-auto" 4 android:id=