Launcher-自定义实现类似android主界面的滑屏换屏控件
2012-03-31 14:49
671 查看
今天讲一下一个类似android主界面的滑屏控件,这个滑屏在微读的主界面和看书时左右滑平翻页中都有用到,在具体的应用效果如下:
实现思路,刚开始的时候我是用ViewFlipper控件来做非常的简单但是实现不了拖拽移动屏幕的效果,最终放弃决定自定义一个控件实现这样效果。
接下来我详细的解说一下我开发时写的这个实验demo,软件中用的滑屏就是由这样的代码实现的。
首先新建一个控件类TouchPageView并且继承自ViewGroup,左右滑动换屏我的实现是在TouchPageView添加3个子view分别代表看不到的左边屏幕、可以看到的中间屏幕、看不到的右边屏幕,这样在滑屏时候就可以通过不断调整这3个view的位置实现连续不间断滑屏换屏,下面的实验中我分别把3个view设置成红色、绿色、黄色这样切换的时候可以看到明显效果,这3个view在TouchPageView的构造方法中调用init方法进行初始化:
复制代码
复制代码
接下来的实现是关键,重写onLayout方法对3个view的显示位置布局进行控制,通过下面的这个方法,把3个view进行水平一个跟着一个进行布局显示。
复制代码
复制代码
3个view位置放置好之后,接下来的实现实现手指在屏幕拖拽滑动时让3个view跟着手指的位置进行变化显示,这个肯定是在onTouchEvent方法中实现了,分别在MotionEvent.ACTION_DOWN、MotionEvent.ACTION_MOVE、MotionEvent.ACTION_UP三个手指状态中进行控制,在下面的实现中还采用了VelocityTracker的方法对手指的滑动速度进行跟踪,这样根据滑动速度决定屏幕往哪个方向换屏,关键的代码如下:
复制代码
复制代码
完成手指滑的功能后,最后在手指离开屏幕的时候,让3个view滑动到合适的位置,保证当前屏幕只能看到一个完整的view另外2个view不可见,并且在滑动的过程中为了达到比较自然的效果,采用减速滑动的实现,这里是用了Handler进行间隔的减速移动效果,这样滑动起来比较舒服,其实最好的效果应该加入阻尼效果,就是让view一定程度的冲过屏幕边界然后在回弹,经过几次这样的缓减至速度为零然后最终停止,这个可以由各位自己去实现,并不难写。
复制代码
复制代码
整个自定义控件核心的思路和代码就上面这些了。
实现思路,刚开始的时候我是用ViewFlipper控件来做非常的简单但是实现不了拖拽移动屏幕的效果,最终放弃决定自定义一个控件实现这样效果。
接下来我详细的解说一下我开发时写的这个实验demo,软件中用的滑屏就是由这样的代码实现的。
首先新建一个控件类TouchPageView并且继承自ViewGroup,左右滑动换屏我的实现是在TouchPageView添加3个子view分别代表看不到的左边屏幕、可以看到的中间屏幕、看不到的右边屏幕,这样在滑屏时候就可以通过不断调整这3个view的位置实现连续不间断滑屏换屏,下面的实验中我分别把3个view设置成红色、绿色、黄色这样切换的时候可以看到明显效果,这3个view在TouchPageView的构造方法中调用init方法进行初始化:
private void init() { views= new ArrayList<LinearLayout>(); view1=new LinearLayout(context); view1.setBackgroundColor(Color.YELLOW); this.addView(view1); TextView tv=new TextView(context); tv.setText("测试"); view1.addView(tv); views.add(view1); view2=new LinearLayout(context); view2.setBackgroundColor(Color.RED); this.addView(view2); views.add(view2); view3=new LinearLayout(context); view3.setBackgroundColor(Color.GREEN); this.addView(view3); views.add(view3); final ViewConfiguration configuration = ViewConfiguration.get(getContext()); mMaximumVelocity = configuration.getScaledMaximumFlingVelocity(); }
复制代码
复制代码
接下来的实现是关键,重写onLayout方法对3个view的显示位置布局进行控制,通过下面的这个方法,把3个view进行水平一个跟着一个进行布局显示。
@Override protected void onLayout(boolean changed, int l, int t, int r, int b) { int childLeft = -1; final int count = views.size(); //水平从左到右放置 for (int i = 0; i < count; i++) { final View child =views.get(i); if (child.getVisibility() != View.GONE) { final int childWidth = child.getMeasuredWidth(); if(childLeft==-1) { childLeft=-childWidth; } child.layout(childLeft, 0, childLeft + childWidth, child.getMeasuredHeight()); childLeft += childWidth; } } }
复制代码
复制代码
3个view位置放置好之后,接下来的实现实现手指在屏幕拖拽滑动时让3个view跟着手指的位置进行变化显示,这个肯定是在onTouchEvent方法中实现了,分别在MotionEvent.ACTION_DOWN、MotionEvent.ACTION_MOVE、MotionEvent.ACTION_UP三个手指状态中进行控制,在下面的实现中还采用了VelocityTracker的方法对手指的滑动速度进行跟踪,这样根据滑动速度决定屏幕往哪个方向换屏,关键的代码如下:
@Override public boolean onTouchEvent(MotionEvent ev){ if(!lock) { if (mVelocityTracker == null) { mVelocityTracker = VelocityTracker.obtain(); } mVelocityTracker.addMovement(ev); final int action = ev.getAction(); final float x = ev.getX(); final float y = ev.getY(); switch (action) { case MotionEvent.ACTION_DOWN://按下去 if(touchState==TOUCH_STATE_REST) { //记录按下去的的x坐标 lastMotionX = x; touchState=TOUCH_STATE_MOVING; isMoved=false; } break; case MotionEvent.ACTION_MOVE://拖动时 if(touchState==TOUCH_STATE_MOVING) { float offsetX=x-lastMotionX; float offsetY=y-lastMotionY; if(isMoved) { lastMotionX=x; lastMotionY=y; final int count = views.size(); //水平从左到右放置 for (int i = 0; i < count; i++) { final View child =views.get(i); if (child.getVisibility() != View.GONE) { final int childWidth = child.getMeasuredWidth(); int childLeft = child.getLeft()+(int)offsetX; child.layout(childLeft, 0, childLeft + childWidth, child.getMeasuredHeight()); childLeft += childWidth; } } } else if(Math.abs(offsetX)>TOUCH_SLOP||Math.abs(offsetY)>TOUCH_SLOP) { //移动超过阈值,则表示移动了 isMoved=true; removeCallbacks(mLongPressRunnable); } } break; case MotionEvent.ACTION_UP://放开时 //释放了 removeCallbacks(mLongPressRunnable); if(isMoved) { if(touchState==TOUCH_STATE_MOVING) { touchState=TOUCH_STATE_SLOWING; int sign=0; final VelocityTracker velocityTracker = mVelocityTracker; //计算当前速度 velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity); //x方向的速度 int velocityX = (int) velocityTracker.getXVelocity(); if(velocityX > SNAP_VELOCITY)//足够的能力向左 { sign=1; Log.e("enough to move left", "true"); } else if (velocityX < -SNAP_VELOCITY)//足够的能力向右 { sign=-1; Log.e("enough to move right", "right"); } else { sign=0; } moveToFitView(sign); if (mVelocityTracker != null) { mVelocityTracker.recycle(); mVelocityTracker = null; } } } break; } } return true; }
复制代码
复制代码
完成手指滑的功能后,最后在手指离开屏幕的时候,让3个view滑动到合适的位置,保证当前屏幕只能看到一个完整的view另外2个view不可见,并且在滑动的过程中为了达到比较自然的效果,采用减速滑动的实现,这里是用了Handler进行间隔的减速移动效果,这样滑动起来比较舒服,其实最好的效果应该加入阻尼效果,就是让view一定程度的冲过屏幕边界然后在回弹,经过几次这样的缓减至速度为零然后最终停止,这个可以由各位自己去实现,并不难写。
int offset=0; private void moveToFitView(int sign) { boolean b=swapView(sign); if(true) { View view1=views.get(1); int left=view1.getLeft(); //int offset=0; if(left!=0) { offset=-1*left; } moveView(); } } FlipAnimationHandler mAnimationHandler; int ovv=40; private void moveView() { final int count = views.size(); if(offset!=0) { int ov=0; if(offset>0) { ov=ovv; } else { ov=-1*ovv; } ovv=ovv-3; if(ovv<1) { ovv=3; } if(Math.abs(offset)<Math.abs(ov)) { ov=offset; offset=0; } else { offset=offset-ov; } //水平从左到右放置 for (int i = 0; i < count; i++) { final View child =views.get(i); final int childWidth = child.getMeasuredWidth(); int childLeft = child.getLeft()+ov; child.layout(childLeft, 0, childLeft + childWidth, child.getMeasuredHeight()); childLeft += childWidth; } if(mAnimationHandler==null) { mAnimationHandler = new FlipAnimationHandler(); } mAnimationHandler.sleep(1); } else { ovv=40; touchState=TOUCH_STATE_REST; } } class FlipAnimationHandler extends Handler { @Override public void handleMessage(Message msg) { TouchPageView.this.moveView(); } public void sleep(long millis) { this.removeMessages(0); sendMessageDelayed(obtainMessage(0), millis); } }
复制代码
复制代码
整个自定义控件核心的思路和代码就上面这些了。
相关文章推荐
- 自定义实现类似android主界面的滑屏换屏控件
- 自定义实现类似android主界面的滑屏换屏控件
- 自定义实现类似android主界面的滑屏换屏控件
- Android自定义控件之实现类似文件夹顶部的层层显示的横栏效果
- Android自定义View之组合控件实现类似电商app顶部栏
- android 开发零起步学习笔记(十七):自定义android用户控件,使用回调函数实现自定义事件
- 【Android学习】自定义View的实现----以圆形图片控件为例
- Android 自定义底部上拉控件的实现方法
- android 自定义view实现类似圆盘抽奖的效果
- Android中给自定义的控件实现自定义的属性
- Android绘图机制(三)——自定义View的实现方式以及半弧圆新控件
- Android自定义控件之实现listview滑动时渐隐渐现顶部栏
- Android 自定义View 三板斧之三——重写View来实现全新控件
- Android自定义“图片+文字”控件四种实现方法之一--------Gallery原理(提供源码下载)
- Android自定义ImageView实现圆形控件显示
- Android拖拉控件的实现(类似抽屉)
- Android自定义组件之日历控件-精美日历实现(内容、样式可扩展)
- Android滚轮控件,基于ListView实现,可以自定义样式。
- Android自定义View 简单实现多图片选择控件
- Android通过自定义ImageView控件实现图片的缩放和拖动的实现代码