(已经更新了,请看另外一篇)
一.前提
好久没玩安卓了,把上下切换view的源码跟大家分享,方法为原创,没有参考别人的作品,
可能不是最优的,但效果是一样的,原理跟SlideMenu是相似的,核心代码就是viewgroup
的重构,所以只贴出该核心的代码,及讲解,因为本人已返回去开发arm了,以前觉得简单
没有过多的解析,现在补充上...(核心代码,木有经过润泽,几十行简洁)
二.源码
//往这个viewgroup里add两个view就可以了
public class ViewMore extends ViewGroup {
private Scroller scroller;
private static float lX,lY,bX,bY,lYY;
private static boolean Menushowflag,Menuflag=true;
public ViewMore(Context context) {super(context);scroller = new Scroller(context);}
public ViewMore(Context context, AttributeSet attrs) {super(context, attrs);}
public ViewMore(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);}
//1.子view的布局
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int viewCount = getChildCount(); //得到viewgroup的子view,该viewgroup有上下两个view
for(int count=0;count<viewCount;count++){
View child = getChildAt(count);
int height = child.getMeasuredHeight();
int width = child.getMeasuredWidth();
child.layout(0, 0, width, height);
}
}
public int displaynView(boolean flag){ //显示不同的view
return flag? 1:0;
}
//2.布局时提供参数,经测试不重写无法正常给子类view布局()
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(width, height);
Log.i("MainActivity", "--->>getChildCount:"+getChildCount());
for (int i = 0; i < getChildCount(); i++) {
getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec);
}
}
//3.重写computeScroll(),处理scroller.startScroll扔过来的数据,(这个才是滑动view的关键方法)
@Override
public void computeScroll() {
if(scroller.computeScrollOffset()){ //判断上次是否划完了(因为我们是把滑动view的动作分解成n个事件来处理的)
getChildAt(displaynView(true)).layout(0, scroller.getCurrY(), getWidth(), scroller.getCurrY()+getHeight());
getChildAt(displaynView(false)).layout(0, -getHeight()+scroller.getCurrY(), getWidth(), scroller.getCurrY());
Log.i("Mainactivity", "CountL_"+scroller.getCurrY()+"---"+(scroller.getCurrY()+getHeight()));
postInvalidate();
}
super.computeScroll();
}
public void ShowViewSroll(float currN,float currY){
//4.给computeScroll提供数据,这段代码区要简洁,不然会卡屏,因为我们要使用这个方法n次
scroller.startScroll(0,(int)currN,0,(int)currY-(int)currN);
invalidate();
Menushowflag = true;
}
public void CloseViewSroll(float currN){//关闭menu
scroller.startScroll(0,(int)currN,0,-(int)currN);
invalidate();
Menushowflag = false;
Menuflag = true;//第一页
}
public void DissViewSroll(float currN){//关闭menu
scroller.startScroll(0,(int)currN,0,getHeight()-(int)currN);
invalidate();
Menushowflag = false;
Menuflag = false;//第二页
}
//5.核心的方法,用dispatchTouchEvent捕捉触屏事件,该方法原本是用来分发触屏事件的,经测试后用我的方法
(实现上下view动态切换时,只有该方法才能捕捉到正确的x,y坐标,不知道问题出在哪里,当初觉得可以用此方
法,所以就没去调试问题出在哪里了)
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
Log.i("Mainactivity", "dispatchTouchEvent"+event.getY());
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
lYY = event.getY();//捕捉到触屏动作,开始记录y坐标(因为我们要实现上下滑动,所以只捕捉y),初始化时使用
break;
case MotionEvent.ACTION_MOVE:
if(lYY<=40&&Menuflag){ // 判断开始触屏的位置是不是顶部且尚未滑动上下view
bY = event.getY(); // (before y简称by )得到真正可以滑动view时的启示y
ShowViewSroll(bY,lY); // 开始滑动一小小段(量变到质变),by等变量要为静态的,因为我们要反复使用这些捕捉到的数据
lY = event.getY(); //记录n毫秒后的y坐标,实现ly-by的差距,然后才能交给scroller的startScroll去滑动
}else if(((int)getHeight()-40)<lYY&&!Menuflag){
bY = event.getY(); //处理当上面的view滑下来后的把view滑上去事件
ShowViewSroll(bY,lY);
lY = event.getY();
}
break;
case MotionEvent.ACTION_UP:
bY = 0;
if(Menushowflag&&(event.getY()<getHeight()/2)){ //当手指提起时判断是要划回去还是划回来
CloseViewSroll(event.getY());
}else if(Menushowflag&&event.getY()>=getHeight()/2){
DissViewSroll(event.getY());
}
break;
default:
break;
}
return super.dispatchTouchEvent(event); //把触屏事件分发回给各个组件
}
}