側拉菜单
一:是一个组合控件,用viewgroup 关心,onmesure和onlayout方法
步骤:
1.自定义控件的类继承自viewgroup,实现onlayout方法
2.布局---viewgroup(第一个添加的索引是0)
2.1.菜单布局(scrollview)和主界面布局
2.2.引入布局,用关键字
3.在onMeasure 方法中测量菜单和主界面的宽和高MeasureSpec.getsize(),getmode();创建规格makemeasureSpec();[1,EXACTY;2,AT_MOST].
3.1测量菜单 getchildAt(0);measure(getlayoutParams(),width,height);
3.2测量主界面
getchildAt(1);//获得对象
4,在onlayout方法中给菜单和主界面设置位置
4.1 主界面的位置放置在屏幕的左上角:mainView.layout(0,0,r,b);
4.2 菜单的位置放置在窗体的左边:menuView.layout(-getmeasuredWidth(),t,0,b);
5, onTouchEvent()
5.1 scrollto和scrollby
5.2 获取已经移动的增量
6,处理触摸事件的内容
6.1,获取当前按下的位置getX();
在move过程中,设置增量值,dx = downX - moveX;
判断dx的大小,如果num=getSrollX()+dx<-侧边菜单的宽度.
SrcollTo();如果大于0,进入主界面 ,运用scrollTo();
否则scrollBy(dx,0); downX = moveX;
case MotionEvent.ACTION_MOVE:
int moveX = (int) event.getX();
int diff = downX - moveX;
scrollX = getScrollX() + diff;
if (scrollX < -getChildAt(0).getMeasuredWidth()) {
scrollTo(-getChildAt(0).getMeasuredWidth(), 0);
} else if (scrollX > 0) {
scrollTo(0, 0);
} else {
scrollBy(diff, 0);
}
downX = moveX;
break;
在手指离开后进行判断up:
int centerposition = -getChildAt(0).getMeasuredWidth() / 2;
if (scrollX > centerposition) {//回到主界面
// scrollTo(0,0);
SCREEN_STATUS = MAIN_VIEW;
} else if (scrollX < centerposition) {//回到菜单界面
// scrollTo(-getChildAt(0).getMeasuredWidth(),0);
SCREEN_STATUS = MEUM_VIEW;
}
switchScreen();
break;
方法:
private void switchScreen() {
int startX = getScrollX();//获取当前位置
int addX = 0;//增量值
if (SCREEN_STATUS==MAIN_VIEW) {
addX = 0-startX;
}else if (SCREEN_STATUS==MEUM_VIEW) {
addX = -getChildAt(0).getMeasuredWidth() - startX;
}
scroller.startScroll(startX,0,addX,0,Math.abs(addX)*5);
invalidate();
}
回调
public void computeScroll() {
if (scroller.computeScrollOffset()) {
int currX = scroller.getCurrX();//获取模拟的当前位置
scrollTo(currX,0);
invalidate();//回调
}
}
事件分发处理:
scaledTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
/**
解决事件分发问题
@param ev
-
@return
*/
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_MOVE:
int moveX = (int) ev.getX();
int moveY = (int) ev.getY();int slopX = Math.abs(downX-moveX); int slopY = Math.abs(downY-moveY); if (slopX>scaledTouchSlop&& slopX>slopY) { return true; } break; case MotionEvent.ACTION_DOWN: downX = (int) ev.getX(); downY = (int) ev.getY(); break;
}
return super.onInterceptTouchEvent(ev);
}
注意事项:
getWidth & getMeasuredWidth(Height同理)
从获取的时机和值的计算方式两个方面来说。
getMeasuredWidth
获取的时机: measure流程走完以后就可以获取到值
值的计算方式: 就是你在onMeasure方法里面给它设置的值
该方法获取的是在代码里测量出来的宽度。
getWidth
获取的时机:layout流程走完以后才可以获取到值,
值的计算方式:right - left(也就是onLayout方法的right参数减去left参数得到的值)
次方法获取的是最终显示到界面上的宽度。
通常情况下,如果这两个方法都能获取到值的话,这两个值是一样的,但是,如果当前的自定义控件是一个2B程序员写的,在layout流程里没有根据
测量的宽高来设置控件的显示位置,这两个值可能不一样。
更改主题:
AS里面的两种方式
1.在清单文件中的APPTHEM 里面,修改Theme.AppCompat.Light.DarkActionBar为Theme.AppCompat.Light.NoActionBar
2.在main里面配置
ActionBar supportActionBar = getSupportActionBar();
if (supportActionBar != null) {
getSupportActionBar().hide();
}