侧边栏 SlidingMenu

本文介绍了一种自定义的侧边栏组件SlidingMenu,该组件基于HorizontalScrollView实现,支持通过滑动或按钮操作来显示或隐藏侧边栏。文章详细解释了组件的工作原理、实现步骤及关键代码。

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

自定义组件之侧边栏 SlidingMenu

1、侧边栏的功能
A、滑动Activity可以打开侧边栏
B、如果滑动的距离小于临界边距,则自动回滚,否则,惯性打开
C、点击某个按钮可以打开/隐藏侧边栏

2、侧边栏的实现思路
A、侧边栏组件的父类不再使用ViewGroup,而是使用HorizontalScrollView,使用该类的目的是可以简化滚动功能的实现,HorizontalScrollView已经实现了自动滚动的功能

B、结构图

这里写图片描述


说明:
1)默认情况下,侧边栏隐藏
2)指定侧边栏的宽度,主界面的宽度和屏幕宽度相同

3、HorizontalScrollView的相关方法
A、getScrollX()
     获取x方向左部被隐藏的距离,(侧边栏隐藏的长度)
B、smoothScrollTo(int x, int y)
     滚动到指定的位置(有动画)

4、需要重写的方法
A、重写onMeasure()方法,指定侧边栏和主界面的宽度,HorizontalScrollView会自动算出总宽度
B、重写onLayout()方法,默认情况下在该方法中隐藏侧边栏
C、重写onTouchEvent()方法,当手指松开的时候,决定侧边栏是显示还是隐藏

5、实现
A、SlidingMenu.java
package com.trkj.dept12_slidingmenu;

import android.app.Activity;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;

/**
* 侧边栏
* @author huzhiwei
*
*/
public class SlidingMenu extends HorizontalScrollView {
     private int leftPaddingWidth; //侧边栏的宽度
     private boolean isOpen = false;//侧边栏是否打开
     private boolean once = false;//默认只隐藏一次

     /**
     * 获取屏幕的宽度
     * @return
     */
     private int getScreenWidth(){
          Activity context = (Activity) getContext();
          DisplayMetrics dm = new DisplayMetrics();
          context.getWindow().getWindowManager()
               .getDefaultDisplay().getMetrics(dm);
          return dm.widthPixels;
     }

     /**
     * 指定侧边栏和主界面的宽
     */
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
          once = true;

          //水平滚动View只能有一个直接子组件
          LinearLayout subView = (LinearLayout) this.getChildAt(0);

          //指定侧边栏和主界面的宽
          //第0个子组件就是侧边栏,第1个组件就是主界面
          LinearLayout slidingMenu =
                    (LinearLayout) subView.getChildAt(0);
          //第1个子组件是主界面
          ViewGroup content = (ViewGroup) subView.getChildAt(1);

          //设置侧边的宽度
          slidingMenu.getLayoutParams().width = leftPaddingWidth;
          //设置主界面的宽度
          content.getLayoutParams().width = this.getScreenWidth();

          super.onMeasure(widthMeasureSpec, heightMeasureSpec);
     }

     /**
     * 默认情况下在该方法中隐藏侧边栏
     */
     @Override
     protected void onLayout(boolean changed, int l, int t, int r, int b) {
          super.onLayout(changed, l, t, r, b);
          //下面的代码只调用一次
          if(once){
               //隐藏侧边栏
               this.scrollTo(leftPaddingWidth, 0);
          }
          once = false;
     }

     @Override
     public boolean onTouchEvent(MotionEvent ev) {
          //当手指松开的时候,决定侧边栏是显示还是隐藏
          //如果侧边栏滑动显示的宽度大于等于侧边栏的一半,则显示完整的侧边栏
          //如果侧边栏滑动显示的宽度小于侧边栏的一半,则隐藏侧边栏
          if(ev.getAction() == MotionEvent.ACTION_UP){
               int dx = this.getScrollX();//dx为侧边栏隐藏的长度
               int halfWidth = this.leftPaddingWidth / 2;
               Log.i("SlidingMenu", "dx:" + this.getScrollX() + " halfWidth:" + halfWidth);
               if(dx < halfWidth){
                    //显示侧边栏
                    this.smoothScrollTo(0, 0);
                    Log.i("SlidingMenu", "显示");
                    this.isOpen = true;
               }else{
                    //隐藏侧边栏
                    this.smoothScrollTo(leftPaddingWidth, 0);
                    Log.i("SlidingMenu", "隐藏");
                    this.isOpen = false;
               }

               return true;
          }

          return super.onTouchEvent(ev);
     }

     /**
     * 打开
     */
     public void open(){
          if(!isOpen){
               this.smoothScrollTo(0, 0);
               isOpen = true;
          }
     }

     /**
     * 隐藏
     */
     public void hide(){
          if(isOpen){
               this.smoothScrollTo(leftPaddingWidth, 0);
               isOpen = false;
          }
     }

     /**
     * 打开隐藏
     */
     public void toggle(){
          if(isOpen){
               hide();
          }else{
               open();
          }
     }



     public SlidingMenu(Context context, AttributeSet attrs, int defStyle) {
          super(context, attrs, defStyle);
     }

     public SlidingMenu(Context context, AttributeSet attrs) {
          super(context, attrs);
          TypedArray a = context.obtainStyledAttributes(attrs,
                    R.styleable.SlidingMenu);
          leftPaddingWidth = a.getDimensionPixelSize(
                    R.styleable.SlidingMenu_left_padding_width,
                    (int)TypedValue.applyDimension(
                              TypedValue.COMPLEX_UNIT_DIP, 200,
                              context.getResources().getDisplayMetrics()));
          a.recycle();
     }

     public SlidingMenu(Context context) {
          super(context);
     }

}

B、attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="SlidingMenu">
        <!-- 指定侧边栏的宽度 -->
        <attr name="left_padding_width" format="dimension"/>
    </declare-styleable>
</resources>

C、activity_main.xml
<com.trkj.dept12_slidingmenu.SlidingMenu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:trkj="http://schemas.android.com/apk/res-auto"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:id="@+id/slidingMenu"
    android:scrollbars="none"
    trkj:left_padding_width="200dp" >

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

        <!-- 侧边栏 -->

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:background="#FF0000"
            android:orientation="vertical" >
        </LinearLayout>

        <!-- 主界面 -->

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:background="#FFFFFF"
            android:orientation="vertical" >

            <Button android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="侧边栏"
                android:id="@+id/btn"
                android:onClick="toggle"
                />

        </LinearLayout>
    </LinearLayout>

</com.trkj.dept12_slidingmenu.SlidingMenu>

D、MainActivity.java
package com.trkj.dept12_slidingmenu;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;

public class MainActivity extends Activity {
     private SlidingMenu slidingMenu;

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

    public void toggle(View v){
         slidingMenu.toggle();
    }
}


效果图:

这里写图片描述
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值