效果图:

需要继承ViewGroup,因为包含了子控件,菜单子控件 与 主页面子控件

Activity Xml布局相关:

<!-- 自定义侧滑菜单 SlideMenu -->

<LinearLayout
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" > <view.custom.heimacustomview.my_slide_menu.MySlideMenu
android:layout_width="match_parent"
android:layout_height="match_parent"> <include layout="@layout/slide_menu" /> <include layout="@layout/slide_main" /> </view.custom.heimacustomview.my_slide_menu.MySlideMenu> </LinearLayout>

菜单界面子控件布局相关:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="300dp"
android:layout_height="match_parent"
android:background="#ffff80"
android:orientation="vertical"> <!-- 这里的View不能写 wrap_content 不然在测量后,一直是TextView的宽度 -->
<TextView
android:layout_width="300dp"
android:layout_height="wrap_content"
android:textSize="30sp"
android:text="侧滑菜单"
android:gravity="center_horizontal"
/> </LinearLayout>

主页界面子控件布局相关:

<?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="match_parent"
android:background="#80ffff"> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="我是首页"
android:textSize="30sp"
android:layout_centerInParent="true"
android:layout_centerHorizontal="true"/> </RelativeLayout>

自定义侧滑菜单类相关:

package view.custom.heimacustomview.my_slide_menu;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Scroller; public class MySlideMenu extends ViewGroup { private static final String TAG = MySlideMenu.class.getSimpleName(); private Scroller mScroller; /**
* 以往我是在onTouchEvent方法中处理,这次我采用手势识别器
* 注意:手势识别器只处理事件相关,不能拦截时间,相当于只过滤处理水,并不能阻止水
*/
private GestureDetector mGestureDetector; float mDistanceX;
float countX = 0f; /**
* 构造方法,由布局xml指引来初始化,并传入属性集合
* @param context
* @param attrs
*/
public MySlideMenu(final Context context, AttributeSet attrs) {
super(context, attrs); mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener(){ /**
* 滑动过程中的方法
* @param e1 可以理解为 手指按下记录用到的MotionEvent
* @param e2 可以理解为 手机滑到某个点记录用到的MotionEvent
* @param distanceX 计算好的X轴距离值
* @param distanceY 计算好的Y轴距离值
* @return
*/
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
// return super.onScroll(e1, e2, distanceX, distanceY);
/* if (getScrollX() < 0) {
distanceX = 0;
}*/ Log.d(TAG, "onScroll() distanceX:" + distanceX + " getScrollX:" + getScrollX());
mDistanceX = distanceX;
countX += distanceX; if (countX > 0) {
countX = 0;
} else if (countX < -slideMenuView.getMeasuredWidth()) {
countX = -slideMenuView.getMeasuredWidth();
} scrollTo((int) countX, getScrollY()); return true;
} /*@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
// return super.onFling(e1, e2, velocityX, velocityY);
Log.d(TAG, "onFling() velocityX:" + velocityX + " velocityY:" + velocityY); if (countX > -slideMenuView.getMeasuredWidth() / 2) {
countX = 0;
} else if (countX < -slideMenuView.getMeasuredWidth() / 2) {
countX = -slideMenuView.getMeasuredWidth();
} int dx = (int) countX - getScrollX(); // scrollTo((int) countX, getScrollY());
mScroller.startScroll(getScrollX(), 0, dx, 0, Math.abs(1000));
invalidate();
return true;
}*/ }); // 实现弹性滑动,不要滑动那么生硬
mScroller = new Scroller(context);
} /**
* 定义两个子控件
*/
private View slideMenuView;
private View slideMainView; /**
* 当布局xml加载完成后,就会调用此方法,然后此方法再去获取子控件View
*/
@Override
protected void onFinishInflate() {
super.onFinishInflate(); // 获取子控件View
slideMenuView = getChildAt(0);
slideMainView = getChildAt(1);
} /**
* 测量方法
* @param widthMeasureSpec
* @param heightMeasureSpec
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec); // 测量菜单子控件的高和宽,宽是布局文件设置的宽度,高度获取当前MySlideMenu的高度(与屏幕保存一致高度)
int slideMenuViewWidth = slideMenuView.getLayoutParams().width;
Log.d(TAG, "获取布局中的宽度 slideMenuViewWidth:" + slideMenuViewWidth);
if (null != slideMenuView) {
slideMenuView.measure(slideMenuViewWidth, heightMeasureSpec);
} // 测量主页子控件的高和宽,宽度高度获取当前MySlideMenu的宽度高度(与屏幕保存一致高度)
if (null != slideMainView) {
slideMainView.measure(widthMeasureSpec, heightMeasureSpec);
}
} /**
* 给子控件位置排版,固定好位置
* @param changed 当发生改变的时候
* @param l 父控件距离左手边左边线距离
* @param t 父控件距离顶边顶边线距离
* @param r 父控件距离左手边右边线距离
* @param b 父控件距离顶部边底部线距离
*/
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) { slideMenuView = getChildAt(0); Log.d(TAG, "slideMenuView.getMeasuredWidth():" + slideMenuView.getMeasuredWidth());
Log.d(TAG, "slideMainView.getMeasuredWidth():" + slideMainView.getMeasuredWidth()); // 给菜单子控件固定好位置
slideMenuView.layout(-slideMenuView.getMeasuredWidth(), 0, 0, slideMenuView.getMeasuredHeight()); // 给主页子控件固定好位置 r和父控件保持一直,b和父控件保持一致
slideMainView.layout(0, 0, r, b);
} private float downX; @Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
mGestureDetector.onTouchEvent(event); if (event.getAction() == MotionEvent.ACTION_UP) {
if (countX > -slideMenuView.getMeasuredWidth() / 2) {
countX = 0;
} else if (countX < -slideMenuView.getMeasuredWidth() / 2) {
countX = -slideMenuView.getMeasuredWidth();
} int dx = (int) countX - getScrollX(); // scrollTo((int) countX, getScrollY()); // 这种方式体验过于生硬 mScroller.startScroll(getScrollX(), 0, dx, 0, Math.abs(1000));
invalidate();
} else if (event.getAction() == MotionEvent.ACTION_DOWN) {
downX = event.getX();
}
return true;
} @Override
public void computeScroll() {
super.computeScroll();
if (mScroller.computeScrollOffset()) {
int currX = mScroller.getCurrX();
scrollTo(currX, mScroller.getCurrY());
postInvalidate();
}
}
}

Android-自定义侧滑菜单的更多相关文章

  1. Android SlidingMenu侧滑菜单使用

    把下载的侧滑菜单压缩包打开,会有一个library文件夹,在eclipse中import existing android code into workspace,导入library文件夹,并且选择作 ...

  2. Android之自定义侧滑菜单

    先来上图: 我们把主界面从左向右拉动,可以看到地下有一层菜单页,从透明渐渐变得不透明,从小渐渐变大,感觉上觉得菜单页是从屏幕外面被拉到屏幕中的.下面的代码实现这个DEMO: 首先是自定义控件Slidi ...

  3. Android 自定义View修炼-打造完美的自定义侧滑菜单/侧滑View控件

    一.概述 在App中,经常会出现侧滑菜单,侧滑滑出View等效果,虽然说Android有很多第三方开源库,但是实际上 咱们可以自己也写一个自定义的侧滑View控件,其实不难,主要涉及到以下几个要点: ...

  4. Android带侧滑菜单和ToolBar的BaseActivity

    写Android的时候,可能有多个界面.在风格统一的软件中,写Activity时会有很多重复.例如我所在软工课程小组的项目:Github链接 ,里面的TaskListActivity和TeacherL ...

  5. 【转】android官方侧滑菜单DrawerLayout详解

    原文网址:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/0925/1713.html drawerLayout是Support ...

  6. no drawer view found with gravity RIGHT(Android实现侧滑菜单从右面滑出) 解决办法

    代码如下: <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width ...

  7. android官方侧滑菜单DrawerLayout详解

    drawerLayout是Support Library包中实现了侧滑菜单效果的控件,可以说drawerLayout是因为第三方控件如MenuDrawer等的出现之后,google借鉴而出现的产物.d ...

  8. vue2.X 自定义 侧滑菜单 组件

    1.vue2.0 封装 侧滑菜单组件 Sidebar.vue <!-- 侧滑菜单 组件 --> <template> <div> <transition na ...

  9. Android之侧滑菜单DrawerLayout的使用

    在android support.v4 中有一个抽屉视图控件DrawerLayout.使用这个控件,可以生成通过在屏幕上水平滑动打开或者关闭菜单,能给用户一个不错的体验效果. DrawerLayout ...

  10. Android DrawerLayout侧滑菜单

    本教程已经录制视频,欢迎大家观看我在CSDN学院录制的课程:http://edu.csdn.net/lecturer/944

随机推荐

  1. Bootstrap-CL:标签

    ylbtech-Bootstrap-CL:标签 1.返回顶部 1. Bootstrap 标签 本章将讲解 Bootstrap 标签.标签可用于计数.提示或页面上其他的标记显示.使用 class .la ...

  2. jQuery的文档操作

    1.插入操作 一.父元素.append(子元素) 追加某元素 父元素中添加新的元素 var oli = document.createElement('li'); oli.innerHTML = '哈 ...

  3. 使用sqoop从Oracle或mysql抽取数据到HDFS遇到的报错及解决

    一.参考文档: 1.https://www.rittmanmead.com/blog/2014/03/using-sqoop-for-loading-oracle-data-into-hadoop-o ...

  4. Python多级菜单

    作业2:多级菜单三级菜单可依次选择进入各子菜单所需新知识点:列表.字典 1.流程图 2.登录界面,输入对应索引 #!/usr/bin/env python3 # -*- coding:utf-8 -* ...

  5. FTP和TCP、UDP

    应用:TFTP客户端 1. TFTP协议介绍 TFTP(Trivial File Transfer Protocol,简单文件传输协议) 是TCP/IP协议族中的一个用来在客户端与服务器之间进行简单文 ...

  6. 好记性不如烂笔头-linux学习笔记6keepalived实现主备操作

    Keepalived的作用是检测服务器的状态,如果有一台web服务器宕机,或工作出现故障,Keepalived将检测到,并将有故障的服务器从系统中剔除,同时使用其他服务器代替该服务器的工作,当服务器工 ...

  7. 将一个list分为每份小鱼1000的

    List<LazadaTrackingDataTO> dataSourceList = new ArrayList<LazadaTrackingDataTO>();       ...

  8. 设置VMWARE通过桥接方式使用主机无线网卡上网(转载)

    其它人的评论:好文,使用bridged最简单;桥接也可选择自定义的虚拟网络-->VMnet1,这样可以让虚机的IP于主机不同,与VMnet1相同.将主机的的网络访问共享给VMnet1(这个法子没 ...

  9. C#中使用DLL相关问题

    一,C#调用 C/C++ 库函数 1,UNITY的C# VS工程常常打不开 属性页,右键工程无 [添加引用]项.原因是VS的自带工具[适用于UNITY的工具]导致的. 解决办法:VS-[工具]-[选项 ...

  10. 【Java】JavaIO(一)、基础知识

    一.常用概念介绍 Java的IO,实现输入输出的基础,可以方便的实现数据的输入输出 二.流的分类 1. 按照流向来分: a). 输入流:向应用程序输 b). 输出流:从应用程序中输出 输入输出流是站在 ...