android 自定义ViewGroup实现滑动菜单SlidingMenu

摘要 滑动菜单SlidingMenu效果如何大家都比较熟悉,在你的UI布局有限的情况下,放不下太多的控件的时候,可以考虑用这个滑动式菜单。在这里我简单说明一下用自定义ViewGroup来实现. 实现方法:我们自定义一个ViewGroup实现左右滑动,第一屏隐藏,第二屏显示. 代码

    滑动菜单SlidingMenu效果如何大家都比较熟悉,在你的UI布局有限的情况下,放不下太多的控件的时候,可以考虑用这个滑动式菜单。在这里我简单说明一下用自定义ViewGroup来实现.
实现方法:我们自定义一个ViewGroup实现左右滑动,第一屏隐藏,第二屏显示.
代码如下:

package com.jj.sliding_6;
  
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.View.MeasureSpec;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.AbsoluteLayout;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.Scroller;
  
/***
 * 自定义view
 * 
 * @author zhangjia
 * 
 */
public class MyViewGroup extends ViewGroup {
    private Scroller scroller;// 滑动
    private int distance;// 滑动距离
  
    private View menu_view, content_view;
    private int duration = 500;
  
    private ViewTreeObserver viewTreeObserver;
    private Context context;
    private CloseAnimation closeAnimation;
  
    public static boolean isMenuOpned = false;// 菜单是否打开
  
    public MyViewGroup(Context context) {
        super(context, null);
    }
  
    public void setCloseAnimation(CloseAnimation closeAnimation) {
        this.closeAnimation = closeAnimation;
    }
  
    public MyViewGroup(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        scroller = new Scroller(context);
    }
  
    public void setDistance(int distance) {
        this.distance = distance;
    }
  
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        if (changed) {
            menu_view = getChildAt(0);// 获取滑动菜单的view
            content_view = getChildAt(1);// 获得主页view
  
            // 相当于fill_parent
            content_view.measure(0, 0);
            content_view.layout(0, 0, getWidth(), getHeight());
        }
    }
  
    @Override
    public void computeScroll() {
        Log.e("jj", "isMenuOpned=" + isMenuOpned);
        if (scroller.computeScrollOffset()) {
            scrollTo(scroller.getCurrX(), scroller.getCurrY());
            postInvalidate();// 刷新
            if (closeAnimation != null)
                closeAnimation.closeMenuAnimation();
  
        }else{
            MainActivity.isScrolling=false;
        }
    }
  
    void showMenu() {
        Log.e("jj", "shoeMenu");
        isMenuOpned = true;
        scroller.startScroll(getScrollX(), 0, -distance, 0, duration);
        invalidate();// 刷新
    }
  
    // 关闭菜单(执行自定义动画)
    void closeMenu() {
        Log.e("jj", "closeMenu");
        isMenuOpned = false;
        scroller.startScroll(getScrollX(), 0, distance, 0, duration);
  
        invalidate();// 刷新
    }
  
    // 关闭菜单(执行自定义动画)
    void closeMenu_1() {
        isMenuOpned = false;
        scroller.startScroll(getScrollX(), 0, distance - getWidth(), 0,
                duration);
        invalidate();// 刷新
    }
  
    // 关闭菜单(执行自定义动画)
    void closeMenu_2() {
        isMenuOpned = false;
        scroller.startScroll(getScrollX(), 0, getWidth(), 0, duration);
        invalidate();// 刷新
    }
  
    /***
     * Menu startScroll(startX, startY, dx, dy)
     * 
     * dx=e1的减去e2的x,所以右移为负,左移动为正 dx为移动的距离,如果为正,则标识向左移动|dx|,如果为负,则标识向右移动|dx|
     */
    void slidingMenu() {
        Log.e("jj", "slidingMenu");
        // 没有超过半屏
        if (getScrollX() > -getWidth() / 2) {
            scroller.startScroll(getScrollX(), 0, -getScrollX(), 0, duration);
            isMenuOpned = false;
        }
        // 超过半屏
        else if (getScrollX() <= -getWidth() / 2) {
            scroller.startScroll(getScrollX(), 0, -(distance + getScrollX()),
                    0, duration);
            isMenuOpned = true;
        }
  
        invalidate();// 刷新
        Log.v("jj", "getScrollX()=" + getScrollX());
    }
}
  
  abstract class CloseAnimation {
    // 点击list item 关闭menu动画
    public void closeMenuAnimation() {
  
    };
}

上诉大部分我都加以注释,想必不用我解释太多,大家仔细看都应该可以看懂.

之后我们只需要在MainActivity中把要显示的view添加进去就可以了。

运行效果:

             /      / 我把源码上传网上,大家可以下载运行.

源码下载

说明一点:listview上下左右滑动冲突没有解决,不过我运行看过很多应用,要么listview不能左右滑动,要么能左右滑动但是listview不到一屏.