使用ViewGroup需要实现onMeasure方法,需要先实现测量才能布局画图
1.在ViewGroup中,让自己内容移动有以下几个方法:
layout(l,t,r,b);
offsetTopAndBottom(offset)和offsetLeftAndRight(offset);
scrollTo和scrollBy方法;
注意:滚动的并不是viewgroup内容本身,而是它的矩形边框 它是瞬间移动,
2.在自定义ViewGroup中一般不需要去实现onMeasure, 我们去实现系统已有的ViewGroup,比如FrameLayout, 它会帮我们区实现onMeasure方法
范例如下
package com.ldw.slide;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
/*
* 自定义布局
*/
public class SlideMenu extends ViewGroup {
private View menuView, WindowView;
private int menuWidth = 0;
public SlideMenu(Context context) {
super(context);
init();
}
public SlideMenu(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
//布局的初始化
private void init(){
}
/**
* 当1级的子view全部加载完调用,可以用初始化子view的引用
* 注意,这里无法获取子view的宽高
*/
@Override
protected void onFinishInflate() {
super.onFinishInflate();
//获取activity_main布局中的第一个子view,layout_menu
menuView = getChildAt(0);
//获取activity_main布局中的第一个子view,layout_window
WindowView = getChildAt(1);
//menu的宽度
menuWidth = menuView.getLayoutParams().width;
}
//测量的方法,参数代表系统测量SlideMenu时传入的参数
//参数测量出的宽高能让SlideMenu充满窗体,其实是正好等于屏幕宽高
//viewGroup需要测量所有子view的宽高
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//测量所有子view的宽高
//通过getLayoutParams方法可以获取到布局文件中指定宽高,menuView中制定了宽高
menuView.measure(menuView.getLayoutParams().width, heightMeasureSpec);
//直接使用SlideMenu的测量参数,因为它的宽高的布局都是充满父窗体
WindowView.measure(widthMeasureSpec, heightMeasureSpec);
}
//测量完成以后需要显示,显示布局的文件
//l: 当前子view的左边在父view的坐标系中的x坐标
//t: 当前子view的顶边在父view的坐标系中的y坐标
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
//menu的l就是宽度的负数
menuView.layout(-menuView.getLayoutParams().width, 0, 0, menuView.getMeasuredHeight());
//主窗体的宽高是屏幕的宽高
WindowView.layout(0, 0, r, b);
}
//获取左边menu移动的距离
private int downX;
//触摸事件
public boolean onTouchEvent(MotionEvent event){
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
downX = (int) event.getX();
break;
case MotionEvent.ACTION_MOVE:
//记录新的坐标
int moveX = (int) event.getX();
//往右移动10
int detaX = (int) (event.getX() - downX);
//根据触摸事件,获取到滚动的x的位移
int newScrollX = getScrollX() - detaX;
//达到了边界
if(newScrollX<-menuWidth) newScrollX = -menuWidth;
if(newScrollX>0)newScrollX = 0;
//改变位置
scrollTo(newScrollX, 0);
//更新x距离
downX = moveX;
break;
case MotionEvent.ACTION_UP:
break;
}
return false;
}
}