效果图:

需要继承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. PAT 甲级 1011 World Cup Betting (20)(20 分)(水题,不用特别在乎精度)

    1011 World Cup Betting (20)(20 分) With the 2010 FIFA World Cup running, football fans the world over ...

  2. Bootstrap-Plugin:下拉菜单(Dropdown)插件

    ylbtech-Bootstrap-Plugin:下拉菜单(Dropdown)插件 1.返回顶部 1. Bootstrap 下拉菜单(Dropdown)插件 Bootstrap 下拉菜单 这一章讲解了 ...

  3. 6.1课堂笔记—DML(数据操作语言),DQL查询语句

    一.DML(数据操作语言) InnoDB MyISAM 支持事务 不支持事务 不支持全文索引 支持全文索引 支持外键约束 不支持 命令查看默认存储引擎 show variables like '%st ...

  4. leetcode119

    public class Solution { public IList<int> GetRow(int rowIndex) { List<List<int>> l ...

  5. 决策树与树集成模型(bootstrap, 决策树(信息熵,信息增益, 信息增益率, 基尼系数),回归树, Bagging, 随机森林, Boosting, Adaboost, GBDT, XGboost)

    1.bootstrap   在原始数据的范围内作有放回的再抽样M个, 样本容量仍为n,原始数据中每个观察单位每次被抽到的概率相等, 为1/n , 所得样本称为Bootstrap样本.于是可得到参数θ的 ...

  6. c# 将json数据转为键值对

    string json = "{\"orderId\":\"000001\",\"haha\":\"001\" ...

  7. Radial Blur

    [Radial Blur] 核心代码如下: v2f vert (appdata_img v) { v2f o; o.pos = mul(UNITY_MATRIX_MVP, v.vertex); o.u ...

  8. S EAI 客户主数据导入_test(detail)

    一. 客户主数据模板导出 客户主数据和新联系人导入 Account_Config.ini文件 [Public] ConnectString=host="siebel://10.10.1.15 ...

  9. java并发特性:原子性、可见性、有序性

    要想并发程序正确地执行,必须要保证原子性.可见性以及有序性.只要有一个没有被保证,就有可能会导致程序运行不正确. 1.原子性(Atomicity) 原子性是指在一个操作中就是cpu不可以在中途暂停然后 ...

  10. 自己制作winhex的模板

    winhex有很多的官方模板,可以在网上下载(后缀tpl)并放至它的安装目录,即可使用.不过要是自己能自己制作,这才好玩,不是么?! 打开模板管理器,可以选中其中一个模板,下面有应用,有编辑,你点开编 ...