侧滑菜单之ViewGroup

在继承ViewGroup类时,需要重写两个方法,分别是onMeasure和onLayout。

1,在方法onMeasure中调用setMeasuredDimension方法void android.view.View.setMeasuredDimension(int measuredWidth, int measuredHeight)

在onMeasure(int, int)中,必须调用setMeasuredDimension(int width, int height)来存储测量得到的宽度和高度值,如果没有这么去做会触发异常IllegalStateException。

2,在方法onMeasure中调用孩子的measure方法

void android.view.View.measure(int widthMeasureSpec, int heightMeasureSpec)

这个方法用来测量出view的大小。父view使用width参数和height参数来提供constraint信息。实际上,view的测量工作在onMeasure(int, int)方法中完成。因此,只有onMeasure(int, int)方法可以且必须被重写。参数widthMeasureSpec提供view的水平空间的规格说明,参数heightMeasureSpec提供view的垂直空间的规格说明。

3,解析onMeasure(int, int)方法

void android.view.View.onMeasure(int widthMeasureSpec, int heightMeasureSpec)

测量view及其内容来确定view的宽度和高度。这个方法在measure(int, int)中被调用,必须被重写来精确和有效的测量view的内容。

在重写这个方法时,必须调用setMeasuredDimension(int, int)来存储测量得到的宽度和高度值。执行失败会触发一个IllegalStateException异常。调用父view的onMeasure(int, int)是合法有效的用法。

view的基本测量数据默认取其背景尺寸,除非允许更大的尺寸。子view必须重写onMeasure(int, int)来提供其内容更加准确的测量数值。如果被重写,子类确保测量的height和width至少是view的最小高度和宽度(通过getSuggestedMinimumHeight()和getSuggestedMinimumWidth()获取)。

4,解析onLayout(boolean, int, int, int, int)方法

void android.view.ViewGroup.onLayout(boolean changed, int l, int t, int r, int b)

调用场景:在view给其孩子设置尺寸和位置时被调用。子view,包括孩子在内,必须重写onLayout(boolean, int, int, int, int)方法,并且调用各自的layout(int, int, int, int)方法。

参数说明:参数changed表示view有新的尺寸或位置;参数l表示相对于父view的Left位置;参数t表示相对于父view的Top位置;参数r表示相对于父view的Right位置;参数b表示相对于父view的Bottom位置。

5,解析View.MeasureSpec类

android.view.View.MeasureSpec

MeasureSpec对象,封装了layout规格说明,并且从父view传递给子view。每个MeasureSpec对象代表了width或height的规格。

MeasureSpec对象包含一个size和一个mode,其中mode可以取以下三个数值之一:

UNSPECIFIED,1073741824 [0x40000000],未加规定的,表示没有给子view添加任何规定。

EXACTLY,0 [0x0],精确的,表示父view为子view确定精确的尺寸。

AT_MOST,-2147483648 [0x80000000],子view可以在指定的尺寸内尽量大

6,一个MeasureSpec封装了父布局传递给子布局的布局要求,每个MeasureSpec代表了一组宽度和高度的要求。一个MeasureSpec由大小和模式组成。它有三种模式:UNSPECIFIED(未指定),父元素不对子元素施加任何束缚,子元素可以得到任意想要的大小;EXACTLY(完全),父元素决定自元素的确切大小,子元素将被限定在给定的边界里而忽略它本身大小;AT_MOST(至多),子元素至多达到指定大小的值。

  它常用的三个函数:

  1.static int getMode(int measureSpec):根据提供的测量值(格式)提取模式(上述三个模式之一)

  2.static int getSize(int measureSpec):根据提供的测量值(格式)提取大小值(这个大小也就是我们通常所说的大小)

  3.static int makeMeasureSpec(int size,int mode):根据提供的大小值和模式创建一个测量值(格式)

7、技术要点:

a、 onLayout(boolean,int,int,int,int); // 对子view 进行布局,确定子view的位置。

boolean
该view 布局是否发生变化

int,int,int,int
该view相对于其父view,左、上、右、下的位置。

b、对touch事件进行解析,可以自己解析,也可以使用 GestureDetator 进行解析。

c、scrollBy(x,y) //将view的内容移动一定的距离,x,y  是一个距离值,表示多少个像素。x为正值时,视图向左偏移。

scrollTo(x,y) //将view的内容移动到某个点上,x,y是一个具体的坐标值。

d、invaliteDate  刷新页面,会导致一系列的方法执行  -- ViewGroup.drawChild()  -- View.draw(canvas,panent,longTime) --  computeScroll()

最终会执行 computeScroll()方法 。

e、scroller 的使用。scroller 是一个工程师,专用于位移、速度 等数据变化 的计算。

scroller.startScroll(startX,startY,disX,disY,duration);
//开始进行新的位移,

scroller.computeScrollOffset();
//计算当前的位移情况,将结果付给scroller.curX和curY。如果返回false,证明,位移结束。

f、touch 事件的传递机制。

主要就是ViewGroup中的几个方法:

dispatchTouchEvent()
//分发事件

onInterceptTouchEvent()
//是否中断事件的传递,返回true 中断。默认返回false

onTouchEvent()
//处理事件、返回true,消费事件。

g、 onMeasure(int,int); // 系统测量控件大小时调用该方法

measure //方法是计算子view的宽度高度

<span style="font-family:Comic Sans MS;">public class MySlideView extends ViewGroup{

	private View content;

	private View menu;

	private boolean isMenuShow = false;

	public MySlideView(Context context, AttributeSet attrs) {
		super(context, attrs);
		scroller = new Scroller(context);
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		menu = getChildAt(0);
		content = getChildAt(1);
		//根据提供的大小值和模式创建测量值,并计算menu的位置
		menu.measure(MeasureSpec.makeMeasureSpec(menu.getLayoutParams().width, MeasureSpec.EXACTLY)
				, heightMeasureSpec);

		content.measure(widthMeasureSpec, heightMeasureSpec);
	}

	/**
	 * 设置view的位置
	 */
	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		System.out.println("layout:::"+getChildCount());

		menu.layout(0-menu.getMeasuredWidth(), 0, 0, b);

		content.layout(0, 0, r, b);
	}

	private int firstX;

	private int lastX;

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		super.onTouchEvent(event);

		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			firstX = lastX = (int) event.getX();
			break;
		case MotionEvent.ACTION_MOVE:
			int disX = (int) (lastX - event.getX());
			lastX = (int) event.getX();
			int nextScrollX = getScrollX()+disX; // 可能的,下一个 mScrollX 的值
			if( nextScrollX >= -menu.getWidth() && nextScrollX <=0){
				scrollBy(disX, 0);
			}

			break;
		case MotionEvent.ACTION_UP:
			int curScrollX = getScrollX();
			if(curScrollX > -menu.getWidth()/2){
				isMenuShow = false;
			}else{
				isMenuShow = true;
			}
			flushState();
			break;
		}
		return true;
	}

	private void flushState() {
		int distance = 0;
		if(!isMenuShow){
//			scrollTo(0,0);
			distance = 0-getScrollX();
		}else{
//			scrollTo(-menu.getWidth(),0);
			distance = -menu.getWidth()-getScrollX();
		}
		scroller.startScroll(getScrollX(), 0, distance, 0);
		invalidate();

	}
	/**
	 * 滚动,子View滚动
	 */
	@Override
	public void computeScroll() {
		if(scroller.computeScrollOffset()){
			scrollTo(scroller.getCurrX(),0);
			invalidate();
		}
	}
	private Scroller scroller ;

	/**
	 * 切换状态
	 */
	public void changeState() {
		isMenuShow = !isMenuShow;
		flushState();
	}

}
</span>

布局文件

<span style="font-family:Comic Sans MS;"><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=".MainActivity" >

    <com.example.MySlideView
        android:id="@+id/msv"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

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

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

    </com.example.MySlideView>

</RelativeLayout></span>

调用changeState()方法即可

时间: 2024-10-28 11:43:22

侧滑菜单之ViewGroup的相关文章

5.触摸事件、侧滑菜单

触摸事件 侧滑菜单--- github-SlidingMenu 1.在ViewGroup中,让自己内容移动有以下三个方法个方法: layout(l,t,r,b); offsetTopAndBottom(offset)和offsetLeftAndRight(offset); scrollTo和scrollBy方法; 注意:滚动的并不是viewgroup内容本身,而是它的矩形边框 它是瞬间移动的 2.在自定义ViewGroup中一般不需要去实现onMeasure, 我们去实现系统已有的ViewGro

【案例分享】仿QQ5.0侧滑菜单ResideMenu

本文由孙国威 原创.如需转载,请注明出处! 为了后续对这个项目进行优化,比如透明度动画.背景图的位移动画,以及性能上的优化. 我把这个项目上传到github上面,请大家随时关注. github地址https://github.com/sunguowei 最近项目要做一个QQ5.0的侧滑菜单效果,和传统的侧滑菜单存在着一些差异.想必大家都已经见识过了. 为了不重复发明轮子,先去github上面搜索了一番. 发现了几个类似的,但是还是有一些不同. 下面是搜索到的类似的开源项目. RESideMenu

android官方侧滑菜单DrawerLayout详解

drawerLayout是Support Library包中实现了侧滑菜单效果的控件,可以说drawerLayout是因为第三方控件如MenuDrawer等的出现之后,google借鉴而出现的产物.drawerLayout分为侧边菜单和主内容区两部分,侧边菜单可以根据手势展开与隐藏(drawerLayout自身特性),主内容区的内容可以随着菜单的点击而变化(这需要使用者自己实现). drawerLayout的使用很方便,使用drawerLayout的要点如下: 1.drawerLayout其实是

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

原文网址:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/0925/1713.html drawerLayout是Support Library包中实现了侧滑菜单效果的控件,可以说drawerLayout是因为第三方控件如MenuDrawer等的出现之后,google借鉴而出现的产物.drawerLayout分为侧边菜单和主内容区两部分,侧边菜单可以根据手势展开与隐藏(drawerLayout自身特性),主内容区的内容可以随着

Xamarin.Android中使用ResideMenu实现侧滑菜单

上次使用Xamarin.Android实现了一个比较常用的功能PullToRefresh,详情见:Xamarin. Android实现下拉刷新功能 这次将实现另外一个手机App中比较常用的功能:侧滑菜单.通过搜索,发现有很多侧滑菜单,有仿手机QQ的侧滑菜单,有折叠的侧滑菜单,有SlidingMenu等,不过我还是比较喜欢 ResideMenu实现的效果,所以想通过Xamarin.Android的绑定实现该效果.这次实现该菜单遇到的问题比较多,花的时间也较多,花了三四个晚上才解决所有的问题.下面是

Android 实现形态各异的双向侧滑菜单 自定义控件来袭

1.概述 关于自定义控件侧滑已经写了两篇了~~今天决定把之前的单向改成双向,当然了,单纯的改动之前的代码也没意思,今天不仅 会把之前的单向改为双向,还会多添加一种侧滑效果,给大家带来若干种形态各异的双向侧滑菜单,不过请放心,代码会很简单~~然后根据这若干种,只要你喜 欢,相信你可以打造任何绚(bian)丽(tai)效果的双向侧滑菜单~~ 首先回顾一下,之前写过的各种侧滑菜单,为了不占据篇幅,就不贴图片了: 1.最普通的侧滑效果,请参考:Android 自定义控件打造史上最简单的侧滑菜单 2.仿Q

自定义侧滑菜单

类似于QQ侧滑菜单的效果,这个最重要的就是改变摆放方式,从而达到自己想要的效果,首先先弄明白onLayout方法里的参数 这个自定义里最主要的就是通过touch事件来移动显示的范围,移动viewgroup主要有几个方法,onLayout offsetTopAndBottom(offset)和offsetLeftAndRight(offset); scrollTo和scrollBy方法; 注意:滚动的并不是viewgroup内容本身,而是它的矩形边框 它是瞬间移动, 这里我们用的是scrollTo

Android 高仿 QQ5.0 侧滑菜单效果 自定义控件来袭【学习鸿洋_视频博客笔记总结】

学习鸿洋博客:http://blog.csdn.net/lmj623565791/article/details/39257409 学习鸿洋视频:慕课网视频 看看Android 高仿 QQ5.0 侧滑菜单效果 自定义控件实现效果: 技术上,继承HorizontalScrollView 加上自定义ViewGroup来实现: 1.onMeasure:决定内部View(子View)的宽和高,以及自己的宽和高 2.onLayout:决定子View的放置位置 3.onTouchEvent[监听动作] 自定

【转】仿QQ5.0侧滑菜单ResideMenu

本文由孙国威 原创.如需转载,请注明出处! 原文:http://blog.csdn.net/manoel/article/details/39013095 为了后续对这个项目进行优化,比如透明度动画.背景图的位移动画,以及性能上的优化. 我把这个项目上传到github上面,请大家随时关注. github地址https://github.com/sunguowei 最近项目要做一个QQ5.0的侧滑菜单效果,和传统的侧滑菜单存在着一些差异.想必大家都已经见识过了. 为了不重复发明轮子,先去githu