1.布局

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context="com.example.slidemenu.MainActivity" >   <com.example.slidemenu.SlideMenuandroid:id="@+id/sm"android:layout_width="match_parent"android:layout_height="match_parent" >

      <!-- 引入菜单布局, 索引为: 0 -->

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

      <!-- 引入菜单布局, 索引为: 0 -->

        <include layout="@layout/slide_content" /></com.example.slidemenu.SlideMenu></RelativeLayout>

这个布局文件用到了自定义的ViewGroup对象com.example.slidemenu.SlideMenu,

继承了ViewGroup类的控件时可以在其内部嵌套子控件。

slide_content.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:orientation="vertical" ><LinearLayout android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"android:background="@drawable/top_bar_bg"android:gravity="center_vertical"><ImageViewandroid:id="@+id/iv" android:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/main_back"/><TextView android:layout_width="1dp"android:layout_height="match_parent"android:background="@drawable/top_bar_divider"android:layout_margin="5dp"/><TextView android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="新闻"android:textSize="30sp"android:textColor="#ffffff"/></LinearLayout><TextView android:layout_width="match_parent"android:layout_height="match_parent"android:textSize="30sp"android:text="!!!!!!!!!!!"android:gravity="center"/>
</LinearLayout>

slide_menu.xml

<?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" ><LinearLayoutandroid:layout_width="240dp"android:layout_height="match_parent"android:background="@drawable/menu_bg"android:orientation="vertical" ><TextView android:text="新闻"android:drawableLeft="@drawable/tab_news"style="@style/SlideMenuStyle"/><TextView android:text="订阅"android:drawableLeft="@drawable/tab_read"style="@style/SlideMenuStyle"/><TextView android:text="本地"android:drawableLeft="@drawable/tab_local"style="@style/SlideMenuStyle"/><TextView android:text="跟帖"android:drawableLeft="@drawable/tab_ties"style="@style/SlideMenuStyle"/><TextView android:text="图片"android:drawableLeft="@drawable/tab_pics"style="@style/SlideMenuStyle"/><TextView android:text="话题"android:drawableLeft="@drawable/tab_ugc"style="@style/SlideMenuStyle"/><TextView android:text="投票"android:drawableLeft="@drawable/tab_vote"style="@style/SlideMenuStyle"/><TextView android:text="聚合阅读"android:drawableLeft="@drawable/tab_focus"style="@style/SlideMenuStyle"/></LinearLayout></ScrollView>

/res/values/styles.xml

<resources><style name="AppBaseTheme" parent="Theme.AppCompat.Light"></style><!-- Application theme. --><style name="AppTheme" parent="AppBaseTheme"></style> <!-- slideMenu style --><style name="SlideMenuStyle"><item name="android:layout_width">match_parent</item><item name="android:layout_height">wrap_content</item><item name="android:gravity">center_vertical</item><item name="android:textSize">18sp</item><item name="android:textColor">#ffffff</item><item name="android:background">@drawable/selector_slidemenuitem_bg</item><item name="android:padding">10dp</item><item name="android:drawablePadding">20dp</item><item name="android:onClick">click</item><item name="android:clickable">true</item></style></resources>

res/drawable-hdpi/selector_slidemenuitem_bg.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<!--     @android:color/transparent为透明色 --><item android:drawable="@android:color/transparent" android:state_pressed="true"></item><item android:drawable="@color/slidemenu_press_bg" android:state_pressed="false"></item></selector>

res/values/colors.xml

<?xml version="1.0" encoding="utf-8"?>
<resources><color name="slidemenu_press_bg">#3333cccc</color>
</resources>

业务逻辑实现

自定义ViewGroup控件

Android事件处理机制

--------------------------------------------------

自定义类SlideMenu继承ViewGroup。该类作为自定义控件类。

SlideMenu.java

package com.example.slidemenu;import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Scroller;public class SlideMenu extends ViewGroup {private int downX;// 按下时x轴的偏移量private int menuMeasuredWidth;int currentState = STATE_MAIN_VIEW;// 当前屏幕显示的界面, 默认为: 主界面static final int STATE_MENU_VIEW = 0;// 菜单界面static final int STATE_MAIN_VIEW = 1;// 主界面// 利用这个对象做出滑动的动画效果
    Scroller scroller;public SlideMenu(Context context, AttributeSet attrs) {super(context, attrs);// TODO Auto-generated constructor stubscroller = new Scroller(context);}// 测量子节点的大小/*** widthMeasureSpec 填充屏幕 heightMeasureSpec 填充屏幕*/@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {// TODO Auto-generated method stubsuper.onMeasure(widthMeasureSpec, heightMeasureSpec);// 调用子节点的measure方法,该方法实际是调用了子节点的onMeasure方法,测量子节点的大小// 测量菜单的宽和高. 宽: 240dip, 高: 填充屏幕View menuView = getChildAt(0);menuView.measure(menuView.getLayoutParams().width, heightMeasureSpec);// 测量主界面的宽和高. 宽: 填充屏幕, 高: 填充屏幕View mainView = getChildAt(1);mainView.measure(widthMeasureSpec, heightMeasureSpec);}// 分配空间// 因为slideMenu占满了父元素,宽高与父元素相同// l:0// t:0// r:slideMenu的宽,也就是父元素的宽// b:slideMenu的高,也就是父元素的高
    @Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {// TODO Auto-generated method stub// 主界面的位置放置在屏幕左上角View mainView = getChildAt(1);mainView.layout(l, t, r, b);// 把菜单的位置放置在屏幕的左侧View menuView = getChildAt(0);menuMeasuredWidth = menuView.getMeasuredWidth();menuView.layout(-menuView.getMeasuredWidth(), t, 0, b);}@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {// 只有在横着滑动时才可以拦截.switch (ev.getAction()) {case MotionEvent.ACTION_DOWN:downX = (int) ev.getX();break;case MotionEvent.ACTION_MOVE:int moveX = (int) ev.getX();if (Math.abs(moveX - downX) > 10) {return true;}break;}return super.onInterceptTouchEvent(ev);}@Overridepublic boolean onTouchEvent(MotionEvent event) {// TODO Auto-generated method stubswitch (event.getAction()) {case MotionEvent.ACTION_DOWN:downX = (int) event.getX();break;case MotionEvent.ACTION_MOVE:int moveX = (int) event.getX();int offsetX = downX - moveX;// 判断一下用户手指滑动是否越界// 判断给定当前的增量移动后, 是否能够超出边界.int scrollX = getScrollX();if (scrollX + offsetX < -menuMeasuredWidth) {// 当前超出了左边界, 应该设置为在菜单的左边界位置上.scrollTo(-menuMeasuredWidth, 0);} else if (scrollX + offsetX > 0) {// 当前超出了右边界, 应该设置为0scrollTo(0, 0);} else {scrollBy(offsetX, 0);}downX = moveX;break;case MotionEvent.ACTION_UP:// 获取菜单宽度的一半int center = -menuMeasuredWidth / 2;scrollX = getScrollX();// 当前屏幕左上角的值if (scrollX < center) {currentState = STATE_MENU_VIEW;refreshViewState();} else {currentState = STATE_MAIN_VIEW;refreshViewState();}break;}return true;}// 松手时根据滑动进度,让mScrollX复位/*** 根据currentScreen变量来切换屏幕显示*/private void refreshViewState() {// TODO Auto-generated method stubint startX = getScrollX();// 开始的位置int dx = 0;// 增量值 = 目的地位置 - 开始的位置;if (currentState == STATE_MAIN_VIEW) {dx = 0 - startX;} else if (currentState == STATE_MENU_VIEW) {dx = -menuMeasuredWidth - startX;}int duration = Math.abs(dx) * 10;if (duration > 1600) {duration = 1600;}// arg0:滑动的开始坐标// arg1:滑动的距离scroller.startScroll(startX, 0, dx, 0, duration);// 只要调用invalidate,那么computeScroll方法就会调用// 刷新当前控件, 会引起onDraw方法的调用.invalidate();// -> drawChild -> view.draw -> view.computeScroll
    }@Overridepublic void computeScroll() {// scroller不会去改变mScrollX的值,它只是帮你计算出你应该把mScrollX的值变为多少// 判断动画是否结束,如果时间到了,那么结束了,返回false,如果时间未到,返回trueif (scroller.computeScrollOffset()) {// 当前mScrollX应该变为多少,这个返回值是startX+应该位移的距离/** scroller .startScroll(0 , 0 , 1000, 0,100);* * 当时间过去了1毫秒时,屏幕应该移动10像素 当时间过去了10毫秒时,屏幕应该移动100像素 例如:* 3点10分50000毫秒,调用那个了scroller.startScroll(0 , 0 , 1000, 0,100);* 3点10分50010毫秒,调用那个了scroller.getcurrx(),返回100* 3点10分50050毫秒,调用那个了scroller.getcurrx(),返回500*/int currX = scroller.getCurrX();scrollTo(currX, 0);invalidate();// 在触发当前方法, 相当于递归.
        }}/*** 是否显示菜单* * @return true 显示菜单, false 不显示*/public boolean isShowMenu() {return currentState == STATE_MENU_VIEW;}/*** 隐藏菜单*/public void hideMenuView() {currentState = STATE_MAIN_VIEW;refreshViewState();}/*** 显示菜单*/public void showMenuView() {currentState = STATE_MENU_VIEW;refreshViewState();}
}

MainActivity.xml

package com.example.slidemenu;import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;public class MainActivity extends ActionBarActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE);setContentView(R.layout.activity_main);final SlideMenu sm = (SlideMenu) findViewById(R.id.sm);ImageView iv = (ImageView) findViewById(R.id.iv);iv.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {// 判断当前状态if (sm.isShowMenu()) {// 是菜单界面, 切换到主界面
                    sm.hideMenuView();} else {// 是主界面, 应该把菜单显示出来
                    sm.showMenuView();}}});}public void click(View v) {Toast.makeText(this, ((TextView) v).getText(), 0).show();}}

转载于:https://www.cnblogs.com/crazyzx/articles/5545970.html

自定义控件-侧边菜单SlidingMenu(滑动菜单)相关推荐

  1. java竖向菜单,垂直滑动菜单

    www.lanrentuku.com td {font-size: 12px;} width="200" /> height=9 src="images/bit05 ...

  2. android 自定义ViewGroup和对view进行切图动画实现滑动菜单SlidingMenu[转]

    http://blog.csdn.net/jj120522/article/details/8095852 示意图就不展示了,和上一节的一样,滑动菜单SlidingMenu效果如何大家都比较熟悉,在这 ...

  3. Android UI(三)SlidingMenu实现滑动菜单(详细 官方)

    Jeff Lee blog:   http://www.cnblogs.com/Alandre/  (泥沙砖瓦浆木匠),retain the url when reproduced ! Thanks ...

  4. html5手机端的点击弹出侧边滑动菜单代码

    效果预览:http://hovertree.com/texiao/html5/19/ 本效果适用于移动设备,可以使用手机等浏览效果. 源码下载:http://hovertree.com/h/bjaf/ ...

  5. 第三方侧滑菜单SlidingMenu在android studio中的使用

    南尘:每天进步一点点! 前面讲了官方的侧滑菜单DrawerLayout的使用,其实早在官方没有推出这个之前,就有很多第三方的jar包如SlidingMenu等,感谢开源的力量. SlidingMenu ...

  6. css菜单缓慢滑动_如何使用HTML,CSS和JavaScript构建滑动菜单栏

    css菜单缓慢滑动 by Supriya Shashivasan 由Supriya Shashivasan 如何使用HTML,CSS和JavaScript构建滑动菜单栏 (How to build a ...

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

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/9671609 记得在很早之前,我写了一篇关于Android滑动菜单的文章,其中有一个 ...

  8. 超酷的Android 侧滑(双向滑动菜单)效果

    Java代码   下面看看我们如何使用它,达到我们想要的效果 public class MainActivity extends Activity { /** * 双向滑动菜单布局 */ privat ...

  9. Android实现导航菜单左右滑动效果

    本文给大家介绍在Android中如何实现顶部导航菜单左右滑动效果. 今天给大家介绍在Android中实现顶部导航菜单左右滑动效果的二种解决方案. 第一种解决方案:  在以前的一篇博文中我使用andro ...

  10. 实现滑动菜单(富文本版本)

    所谓的滑动菜单就是将一些菜单选项隐藏起来,而不是放置在主屏幕上,然后可以通过滑动的方式将菜单显示出来.这种方式既节省了屏幕空间,又实现了非常好的动画效果. 下面我们实现一个相对基本的滑动菜单. 参考文 ...

最新文章

  1. 硬件delay评估表
  2. pandas 实现DataFrame的合并Merge
  3. php手机底部菜单,html5手机web页面底部菜单
  4. 单例模式(Singleton-Pattern)百媚生
  5. 利用条件GANs的pix2pix进化版:高分辨率图像合成和语义操作 | PaperDaily #23
  6. svn服务器如何扫描文件,基于文件仓库进行建模协作(EA+SVN)
  7. 【java】从进程角度理解java
  8. TypeScript 乱糟笔记
  9. Alibaba船新出品“Java架构核心宝典”,java教程视频百度网盘
  10. 百度地图API图标、文本、图例与连线
  11. android 7.1 自动启动wifi,设置自动连接wifi-ssid
  12. 【土旦】 使用Vant 的Uploader 上传图片 重定义返回格式 使用FormData格式提交
  13. 软件测试:给你一个网站,你如何测试
  14. IntelliJ IDEA重置配置设定
  15. 蜗牛学院:这6种心态,容易毁掉你的职场
  16. Chrome浏览器自带翻译功能不能使用了?看我的解决方法
  17. 智慧档案馆档案库房一体化平台建设
  18. vlookup使用步骤_Excel Vlookup函数的使用方法及实例图解
  19. 国内软件好压,能够打开各种exe安装包,并直接解压安装 - 国内软件质量测评
  20. Linux命令如何进入screen,linux screen命令基础

热门文章

  1. Caused by: java.lang.NoClassDefFoundError: Lorg/sl
  2. CString::Format
  3. Java Instant类
  4. 为nginx反向代理设置自定义错误页面
  5. 去中心化多链钱包CoinU 30问(你想要的答案都在这里)
  6. Android 5.0及以上实现屏幕截图
  7. AndroidLinker与SO加壳技术之下篇
  8. spring 事务原理_Spring声明式事务处理的实现原理,来自面试官的穷追拷问
  9. BZOJ 2049: [Sdoi2008]Cave 洞穴勘测
  10. 统计各个函数的耗时_Prometheus 常用函数 histogram_quantile 的若干“反直觉”问题...