首页 > 系统 > Android > 正文

Android自定义实现侧滑菜单效果

2019-10-21 21:26:16
字体:
来源:转载
供稿:网友

本文实例为大家分享了Android自定义实现侧滑菜单的具体代码,供大家参考,具体内容如下

实现原理:继承ViewGroup控件要显示到界面上需要重写OnMeature() 
OnLayout(),因此在实现OnLayout()的时候,将菜单界面划出到屏幕左侧,动态改变菜单界面距离scrollXto()左边界的距离就能实现滑动效果。

1.继承ViewGroup
2.事件分发机制
3.状态监听

在主界面中添加两个子控件

<com.oblivion.ui.SlideMenu xmlns:android="http://schemas.android.com/apk/res/android"  android:id="@+id/sliding_menu"  android:layout_width="match_parent"  android:layout_height="match_parent">  <!-- 在SlidingMenu中的索引0 -->  <include layout="@layout/menu" />  <!-- 在SlidingMenu中的索引1 -->  <include layout="@layout/main" /></com.oblivion.ui.SlideMenu>

menu菜单布局

<?xml version="1.0" encoding="utf-8"?><ScrollView xmlns:android="http://schemas.android.com/apk/res/android"  android:layout_width="240dp"  android:layout_height="match_parent"  android:background="@drawable/menu_bg">  <LinearLayout    android:layout_width="240dp"    android:layout_height="wrap_content"    android:orientation="vertical">    <TextView      android:id="@+id/tv_news"      style="@style/menu_item"      android:layout_width="match_parent"      android:layout_height="wrap_content"      android:background="@drawable/select_menu"      android:clickable="true"      android:drawableLeft="@drawable/tab_news"      android:drawablePadding="10dp"      android:text="新闻" />    <TextView      android:id="@+id/tv_read"      style="@style/menu_item"      android:layout_width="match_parent"      android:layout_height="wrap_content"      android:drawableLeft="@drawable/tab_read"      android:drawablePadding="10dp"      android:text="订阅" />    <TextView      android:id="@+id/tv_local"      style="@style/menu_item"      android:layout_width="match_parent"      android:layout_height="wrap_content"      android:drawableLeft="@drawable/tab_local"      android:drawablePadding="10dp"      android:text="本地" />    <TextView      android:id="@+id/tv_ties"      style="@style/menu_item"      android:layout_width="match_parent"      android:layout_height="wrap_content"      android:drawableLeft="@drawable/tab_ties"      android:drawablePadding="10dp"      android:text="跟帖" />    <TextView      android:id="@+id/tv_pics"      style="@style/menu_item"      android:layout_width="match_parent"      android:layout_height="wrap_content"      android:drawableLeft="@drawable/tab_pics"      android:drawablePadding="10dp"      android:text="图片" />    <TextView      android:id="@+id/tv_ugc"      style="@style/menu_item"      android:layout_width="match_parent"      android:layout_height="wrap_content"      android:drawableLeft="@drawable/tab_ugc"      android:drawablePadding="10dp"      android:text="话题" />    <TextView      android:id="@+id/tv_vote"      style="@style/menu_item"      android:layout_width="match_parent"      android:layout_height="wrap_content"      android:drawableLeft="@drawable/tab_vote"      android:drawablePadding="10dp"      android:text="投票" />    <TextView      android:id="@+id/tv_focus"      style="@style/menu_item"      android:layout_width="match_parent"      android:layout_height="wrap_content"      android:drawableLeft="@drawable/tab_focus"      android:drawablePadding="10dp"      android:text="焦点" />  </LinearLayout></ScrollView>

显示界面布局

<?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:orientation="vertical">  <LinearLayout    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:background="@drawable/top_bar_bg"    android:orientation="horizontal">    <ImageView      android:id="@+id/iv_showmenu"      android:layout_width="wrap_content"      android:layout_height="wrap_content"      android:src="@drawable/main_back" />    <View      android:layout_width="1dp"      android:layout_height="match_parent"      android:background="@drawable/top_bar_divider"></View>    <TextView      android:layout_width="match_parent"      android:layout_height="match_parent"      android:gravity="center"      android:text="新闻首页"      android:textColor="#ffffff"      android:textSize="30sp" />  </LinearLayout>  <TextView    android:layout_width="match_parent"    android:layout_height="match_parent"    android:gravity="center_horizontal"    android:text="我操,这么low"    android:textColor="#000000"    android:textSize="20sp" /></LinearLayout>

实现原理:继承ViewGroup控件要显示到界面上需要重写OnMeature() OnLayout(),因此在实现OnLayout()的时候,将菜单界面划出到屏幕左侧,动态改变菜单界面距离scrollXto()左边界的距离就能实现滑动效果。

实现onMeasure()和onLayout()方法,对控件进行布局

/**   * 测量布局中的控件   *   * @param widthMeasureSpec   * @param heightMeasureSpec   */  @Override  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {    super.onMeasure(widthMeasureSpec, heightMeasureSpec);//测量自身宽高    //得到menu界面    menuView = getChildAt(0);    menuViewWidth = menuView.getLayoutParams().width;    //得到main界面    mainView = getChildAt(1);    //设定menuView的宽------不用setMeasure...    menuView.measure(MeasureSpec.makeMeasureSpec(menuViewWidth, MeasureSpec.EXACTLY), heightMeasureSpec);    //设定mainView的宽    mainView.measure(widthMeasureSpec, heightMeasureSpec);  }  @Override  protected void onLayout(boolean changed, int l, int t, int r, int b) {    int menuleft = -menuViewWidth;//menu设定的left    int menuright = 0;//menu设定的right    int menutop = 0;//menu设定的top    int menubottom = b - t;//menu设定的bottom    //布局menuView 控件xx2    menuView.layout(menuleft, menutop, menuright, menubottom);    int mainleft = 0;//main设定的left    int mainright = r - l;//main设定的right    int maintop = 0;//main设定的top    int mainbottom = b - t;//main设定的bottom    //布局mainView ---------------控件.....你妈逼方向---------方向是left,top,right,bottom    mainView.layout(mainleft, maintop, mainright, mainbottom);    System.out.println(menuViewWidth--);//原来这这里减减了;  }

通过onTouch()方法,以及scrollX()和getScrollX()方法获取边界值,动态改变去实现滑动。 
这里需要注意的是scrollX(),getScrollX()得到的值是相对于布局起始点的,所以需要重新封装; 
平滑动画,需要在构造函数中创建一个Scroll 类,然后通过ComplentScroll..方法,判断设定的平滑动画是否结束。

最后通过,动画结束后的边界值,判断是否打开,关闭状态。

 

 /**   * 由于系统scrollTo是取反操作,所以需要封装一下   *   * @param distance   */  private void scrollTo(int distance) {    super.scrollTo(-distance, 0);  }  public int getMyScrollX() {    return -getScrollX();  }  /**   * 控件触莫状态   *   * @param event   * @return   */  @Override  public boolean onTouchEvent(MotionEvent event) {    switch (event.getAction()) {      case MotionEvent.ACTION_DOWN:        //记录按下点        down_dot = (int) event.getX();        System.out.println(down_dot);        break;      case MotionEvent.ACTION_MOVE:        int move_dot = (int) event.getX();        //动态的移动点和按下点的间距绝对值        move2down_distance = move_dot - down_dot;        //移动间距与上次抬起的点        int lastUp_dot = move2down_distance + up_dot;        // 控制边界        if (lastUp_dot >= menuViewWidth) {          lastUp_dot = menuViewWidth;        } else if (lastUp_dot <= 0) {          lastUp_dot = 0;        }        //设定移动后的距离        scrollTo(lastUp_dot);        break;      case MotionEvent.ACTION_UP:        //当前抬起手指点        up_dot = (int) event.getX();        //设定最终的状态        setFinalScroll();        break;    }    return true;//将事件消费掉  }  /**   * 当手指抬起后,记录最终的状态;   */  private void setFinalScroll() {    //得到当前距离左边界的距离    currrentScroll = getMyScrollX();    if (currrentScroll >= menuViewWidth / 2) {      //scrollTo(menuViewWidth);      rightAnimation();    } else {      leftAnimation();    }  }  /**   * 平滑向左的移动动画   */  private void leftAnimation() {    //scrollTo(0);    int dx = 0 - currrentScroll;//要移动的距离    //设定平滑动画    msScroller.startScroll(currrentScroll, 0, dx, 0, 300);    invalidate();    //设定一下抬起点    up_dot = 0;    //调用接口的关闭状态    mOnDragStateListener.onDragClose();  }  /**   * 平滑向右移动的动画   */  private void rightAnimation() {    int dx = menuViewWidth - currrentScroll;//要移动的距离    //设定平滑动画    msScroller.startScroll(currrentScroll, 0, dx, 0, 300);    invalidate();    //设定一下抬起点    up_dot = menuViewWidth;    //调用接口的开启状态    mOnDragStateListener.onDragOpen();  }  /**   * 平滑移动动画是否结束   */  @Override  public void computeScroll() {    super.computeScroll();    if (msScroller.computeScrollOffset()) {      int currX = msScroller.getCurrX();//模拟出来的数值      scrollTo(currX);      invalidate();    }  }

创建监听,以及回调接口

 /**   * 拖拽的监听   */  public void setOnDragStateListener(onDragStateListener listener) {    mOnDragStateListener = listener;  }  /**   * 回调修改状态   *   * @param dragState   */  public void setStateChange(boolean dragState) {    if (dragState) {      currrentScroll = 0;      rightAnimation();    } else {      currrentScroll = menuViewWidth;      leftAnimation();    }  }  /**   * 创建拖拽的回调接口   */  public interface onDragStateListener {    /**     * 被拖拽开     */    void onDragOpen();    /**     * 被关闭     */    void onDragClose();  }

主Activity中实现监听效果

iv_showmenu.setOnClickListener(new View.OnClickListener() {      @Override      public void onClick(View v) {        //图片点击后触发改变状态        sliding_menu.setStateChange(dragState);      }    });    sliding_menu.setOnDragStateListener(new SlideMenu.onDragStateListener() {      @Override      public void onDragOpen() {        ToastUtils.setToast(getApplicationContext(), "open");        dragState = false;        tv_news.setSelected(true);        tv_news.setTextColor(Color.BLUE);      }      @Override      public void onDragClose() {        ToastUtils.setToast(getApplicationContext(), "close");        dragState = true;        tv_news.setSelected(false);        tv_news.setTextColor(Color.WHITE);      }    });    tv_news.setOnClickListener(new View.OnClickListener() {      @Override      public void onClick(View v) {        ToastUtils.setToast(getApplicationContext(), tv_news.getText().toString());      }    });  }

github源码地址

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持VEVB武林网。


注:相关教程知识阅读请移步到Android开发频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表