侧滑菜单(自定义View)

本文详细介绍了滑动菜单的实现原理,通过提供Java代码、布局文件及示例,深入探讨了如何在Android应用中实现侧滑菜单功能。包括主活动类、滑动横幅视图类、自定义样式及布局文件的使用,以及如何通过触摸事件控制菜单的展开与收起。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、先来几张效果图

不打开侧滑菜单状态

不打开侧滑菜单状态

打开侧滑菜单状

打开侧滑菜单状

2、Java代码

MainActivity.java

public class MainActivity extends Activity {
    SlidingHorizontalScrollView shs_menu;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        shs_menu = (SlidingHorizontalScrollView) findViewById(R.id.shs_menu);
    }

    public void toggleMenu(View v) {
        switch (v.getId()) {
        case R.id.btn_left_menu:
            shs_menu.toggle();
            break;

        }
    }
}

SlidingHorizontalScrollView.java

public class SlidingHorizontalScrollView extends HorizontalScrollView {

    private int mScrollWidth;// 屏幕的宽度
    private int mMenuRightPadding;// 菜单项完全展示时距离右边的距离
    private int mLeftMenuWidth;// 左边菜单项的宽度
    private LinearLayout mWapper;// 最外层的布局容器
    private ViewGroup mLeftMenu;// 左边菜单项
    private ViewGroup mContent;// 主界面
    private boolean once; // 判断是否已绘制View的宽和高
    private boolean isOpen;// 判断菜单项是否被打开

    public SlidingHorizontalScrollView(Context context, AttributeSet attrs,
            int defStyle) {
        super(context, attrs, defStyle);
        // 取得系统的窗口服务
        WindowManager wm = (WindowManager) context
                .getSystemService(Context.WINDOW_SERVICE);
        // 取得屏幕宽度
        mScrollWidth = wm.getDefaultDisplay().getWidth();
        //mMenuRightPadding = mScrollWidth / 3;

        TypedArray typedArray = getContext().obtainStyledAttributes(attrs,
                R.styleable.SlidingHorizontalScrollView);
        //自定义属性的值
        float menuRightPading = typedArray.getDimension(
                R.styleable.SlidingHorizontalScrollView_menuRightPading,
                mMenuRightPadding);
        mMenuRightPadding = (int) menuRightPading;
    }

    public SlidingHorizontalScrollView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public SlidingHorizontalScrollView(Context context) {
        this(context, null);
    }

    // View的高和宽
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        if (!once) {
            mWapper = (LinearLayout) getChildAt(0);
            mLeftMenu = (ViewGroup) mWapper.getChildAt(0);
            mContent = (ViewGroup) mWapper.getChildAt(1);
            mLeftMenuWidth = mLeftMenu.getLayoutParams().width = mScrollWidth
                    - mMenuRightPadding;
            mContent.getLayoutParams().width = mScrollWidth;
            once = true;
        }
    }

    // View的位置
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        if (!changed) {
            // 设置偏移量隐藏菜单项
            this.scrollTo(mLeftMenuWidth, 0);
        }
    }

    // 监听事件
    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        int action = ev.getAction();
        switch (action) {
        case MotionEvent.ACTION_UP:
            // 隐藏在左边的宽度
            int scrollX = getScrollX();
            if (scrollX >= mLeftMenuWidth / 2) {
                this.smoothScrollTo(mLeftMenuWidth, 0);
                isOpen = false;
            } else {
                this.smoothScrollTo(0, 0);
                isOpen = true;
            }
            return true;
        }

        return super.onTouchEvent(ev);
    }

    // 打开菜单
    public void openMenu() {
        if (isOpen)
            return;
        this.smoothScrollTo(0, 0);
        isOpen = true;
    }

    // 关闭菜单
    public void closeMenu() {
        if (!isOpen)
            return;
        this.smoothScrollTo(mLeftMenuWidth, 0);
        isOpen = false;
    }

    // 切换菜单
    public void toggle() {
        if (isOpen) {
            closeMenu();
        } else {
            openMenu();
        }
    }

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
        //设置打开抽屉时的动画效果
        ViewHelper.setTranslationX(mLeftMenu, l);

    }

}

3、布局文件

attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="SlidingHorizontalScrollView">
        <attr name="menuRightPading" format="dimension" />
    </declare-styleable>

</resources>

说明:attrs.xml位于values目录下

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:slidingMenu="http://schemas.android.com/apk/res/cn.lyh.slidingmenudemo"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <include layout="@layout/title_layout" />

    <cn.lyh.slidingmenudemo.view.SlidingHorizontalScrollView
        android:id="@+id/shs_menu"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        slidingMenu:menuRightPading="100dp" >

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:orientation="horizontal" >

            <include layout="@layout/left_menu_layout" />

            <include layout="@layout/content_layout" />
        </LinearLayout>
    </cn.lyh.slidingmenudemo.view.SlidingHorizontalScrollView>

</LinearLayout>

left_menu_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#4BA368"
    android:gravity="center"
    android:orientation="vertical" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:orientation="horizontal" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="LEFT"
            android:textSize="45sp" />
    </LinearLayout>

</LinearLayout>

content_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#E0E0E0"
    android:gravity="center"
    android:orientation="vertical" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:orientation="horizontal" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="CONTENT"
            android:textSize="45sp" />
    </LinearLayout>

</LinearLayout>

title_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:background="#424242"
    android:orientation="horizontal" >

    <Button
        android:id="@+id/btn_left_menu"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="toggleMenu"
        android:text="切换菜单" />

</RelativeLayout>

4、Demo下载地址
http://download.youkuaiyun.com/detail/tuu_zed/8659387

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值