`
z303729470
  • 浏览: 134070 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Android ViewGroup实现页面滑动效果并实现不同的动画效果

 
阅读更多
这应该是自己第一次开始写博客,今天起想要记录下自己工作上学到的一些东西,除了能随时查看自己的曾经学到的东西,也可以跟大家分享一下自己的一些经验。由于自己刚到3g门户去实习,其实有很多技术上东西都不是很懂,也只能慢慢去学了。一进来的实习,带我的那位辅导员就让我实现像Launcher那样的滑动,并且实现滑动过程中的效果~~~这下惨了,自己最薄弱的一环,对一些界面上的东西都很少去碰,只能乖乖的去网上搜搜资料恶补一下了。
  不扯那么多了,直接进入正题吧,其实实现像Launcher那样的滑动效果有几种方法,不过我在这里用继承ViewGroup的方法去实现。要是实现ViewGroup必须重写onLayout()和onMeasure()这两个方法,这个两个方法在创建的时候会自动调用,调用的顺序是onMeasure()-->onLayout()。
onMeasure()方法中是存储在ViewGroup里面每个子View的默认宽度和高度,以下代码就是把每个子View的默认宽度和高度都设置与父类的一样。
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        Log.i("onMeasure", "onMeasure----------");
        super.onMeasure(widthMeasureSpec, heightMeasureSpec); 

        final int width = MeasureSpec.getSize(widthMeasureSpec); //转换宽度
        final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        if (widthMode != MeasureSpec.EXACTLY) { 
            throw new IllegalStateException("ScrollLayout only canmCurScreen run at EXACTLY mode!");
        } 
        final int heightMode = MeasureSpec.getMode(heightMeasureSpec); 
        if (heightMode != MeasureSpec.EXACTLY) { 
            throw new IllegalStateException("ScrollLayout only can run at EXACTLY mode!");
        } 

        // 将所有的子View高度和宽度都定义成和父View一样
        final int count = getChildCount(); 
        for (int i = 0; i < count; i++) { 
            getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec); 
        }
      
        //滑动到默认屏幕
        scrollTo(mCurScreen * width, 0);       
    }
而onLayout()就是设置每个子View在屏幕那个位置来显示出子View,现在在OnLayout()方法里面设置是从左到右横向绘出每个子View,其中onLayout这个方法的实现是在什么地方显示子view,显示的范围是多大,这个方法不能改变每个view原本的大小的
protected void onLayout(boolean changed, int l, int t, int r, int b) {
     Log.i("onLayout", "onLayout----------");
  if(mTouchState == TOUCH_STATE_REST){
   int childLeft = 0;//从坐标0开始绘画
   final int childCount = getChildCount();
  
   for (int i=0; i<childCount; i++) {
    final View childView = getChildAt(i);
    if (childView.getVisibility() != View.GONE) {
     final int childWidth = childView.getMeasuredWidth();   
     //根据left , top ,right,bottom 四个参数,调用子View的layout()方法将其放置在父类中,参照物是父View
     childView.layout(childLeft, 0,
       childLeft+childWidth, childView.getMeasuredHeight());
     childLeft += childWidth;
    }
   }
  }
}
onMeasure和onLayout这个两个方法只是设置子View大小和绘画位置,真正把每个子View绘画出来是在onDispathDraw()方法里(一开始我还以为在onDraw,但是ViewGroup那里是不会调用onDraw方法)实现的,要是实现子view滑动时候的效果就可以再这里实现。
到了这里就把整个页面里的子view都画出来,要实现滑动的效果就需要在onTouchEvent那里做功夫,主要实现滑动动作是在MotionEvent.Action_Move里的scrollBy(x,y),x表示水平滑动的距离,y表示垂直滑动的距离,因为这里只水平方向的滑动,所以y可以设置为0。
如果要像一些桌面应用那样,当手松开后就滑动到某个完整的view的页面,这就需要用Scroller和在MotionEvent.Action_Up上设置,Scroller是可以控制整个页面的滑动,而在MotionEvent.Action_Up上面时判断手指滑动的速度,可以自己定义一个速度的基准,当达到就跨屏滑动,没有达到就判断滑动的位置是否超过当前屏幕的一半,超过就跨屏,否则仍然恢复到当前屏幕,具体还有一些数值需要自己去计算定义自己喜欢效果。代码如下:
public boolean onTouchEvent(MotionEvent event) {
  // TODO Auto-generated method stub
 
  //获得动作捕捉器
  if (mVelocityTracker == null) {
   mVelocityTracker = VelocityTracker.obtain();
  }
  mVelocityTracker.addMovement(event);//开始捕捉动作
 
 
  final int action = event.getAction();
  final float x = event.getX();
  final float y = event.getY();
 
  switch (action) {
  case MotionEvent.ACTION_DOWN:
   if (!mScroller.isFinished()){
    mScroller.abortAnimation();
   }
   mLastMotionX = x;
   break;
  
  case MotionEvent.ACTION_MOVE:
   int deltaX = (int)(mLastMotionX - x);
   mLastMotionX = x;
  
            scrollBy(deltaX, 0);
   break;
  
  case MotionEvent.ACTION_UP://放手后的动作
         
            final VelocityTracker velocityTracker = mVelocityTracker;  
           
            //计算滑动速度,参数1000表示以1000毫秒为单位计算,即以秒为单位
            velocityTracker.computeCurrentVelocity(1000);  
            int velocityX = (int) velocityTracker.getXVelocity();

           
            //如果向左或者向右的滑动速度超过了基础线,则直接切换屏幕;如果没有,则判断滑动的距离是否超过了屏幕一半的距离,也就是View的一半Width
            if (velocityX > SNAP_VELOCITY && mCurScreen > 0) {  
                // Fling enough to move left  

                snapToScreen(mCurScreen - 1);  
            } else if (velocityX < -SNAP_VELOCITY  
                    && mCurScreen < getChildCount() - 1) {  
                // Fling enough to move right  
                snapToScreen(mCurScreen + 1);  
            } else {  
                snapToDestination();  
            } 
            if (mVelocityTracker != null) {  
                mVelocityTracker.recycle();  
                mVelocityTracker = null;  
            }  
            mTouchState = TOUCH_STATE_REST;  
   break;
  
  case MotionEvent.ACTION_CANCEL:
   mTouchState = TOUCH_STATE_REST;
   break;
  }
 
  return true;
}
public void snapToDestination() {
     final int screenWidth = getWidth();
     final int destScreen = (getScrollX()+ screenWidth/2)/screenWidth;
     snapToScreen(destScreen);
    }
public void snapToScreen(int whichScreen) {
     // get the valid layout page
     whichScreen = Math.max(0, Math.min(whichScreen, getChildCount()-1));
     if (getScrollX() != (whichScreen*getWidth())) {
     
      final int delta = whichScreen*getWidth()-getScrollX();
      mScroller.startScroll(getScrollX(), 0,
        delta, 0, Math.abs(delta)*2);
      mCurScreen = whichScreen;
      invalidate();  // Redraw the layout
     }
    }
现在基本算是实现了整个屏幕滑动的效果,要实现滑动的动画就必须要在dispathDraw(Canvas canvas)的canvas来实现了,在ViewGroup里面有一个方法drawChild(),通过这个将每个view都重绘上去,其中的变换不外乎translate,scale这个几种,当然要实现其他比较复杂的效果就需要其他操作了,所以现在要重写dispatchDraw里面的方法,而我现在要实现像Go桌面那样的弹跳效果,这里是通过获取屏幕的左位置和每个子view的左坐标来进行绘画,因为子view的位置是固定的,而屏幕的左坐标却在不断的变化。在这里是用一个判断为基准,就是每个子view的左坐标与屏幕左坐标的距离是否超过一个子view的宽度,超过距离的子view将不做变换。
int dx=Math.abs(getScrollX()-view.getLeft())通过这个获取每个子view的左坐标和屏幕左坐标的距离,这里我是实现弹跳的效果,其实只是对子view的y轴上的位置进行变换,用dx/view.getWidth()来获取滑动距离的比例,通过canvas.translate(0.0f, -(1.0f*dx/view.getWidth())*getHeight())来进行变化,其实当前子view初始化的位置(0.0f,0.0f),也就是这时dx是0,当我进行滑动的时候,dx就递增,当前子view就开始向上移动,而相对隔壁的子view,dx是子view的宽度,dx是递减的,就开始向下移动,这个过程全都是根据每个子view的左坐标的坐标和屏幕左坐标距离进行判断的,就是越接近屏幕左坐标的就向下移动,远离就向上移动,可能我讲得也不大清楚,只要自己用纸画一下应该就会明白的,代码如下:
int saveCount = canvas.save();
        int count = getChildCount();
        int width = getWidth();
        int scrollX=getScrollX();
       
//        for (int i = 0; i < count; i++) {
//            canvas.save();          
//            View view=getChildAt(i);
//            int childLeft=view.getLeft();
//            int dx=Math.abs(scrollX-childLeft);
//            //Log.i("child"+i, x+"-----------");
//            if(dx<=width){
//                canvas.scale(1.0f, 1.0f-(float)0.5*dx/width);
//                canvas.translate(0.0f, (0.5f*dx/width)*getHeight());
//                Log.i("heigh", getHeight()+"----------");
//                drawChild(canvas, view, getDrawingTime());
//                canvas.restore();
//            }else{
//                canvas.scale(1.0f, 0.5f);
//                canvas.translate(0.0f, 0.5f*getHeight());
//                drawChild(canvas, view, getDrawingTime());
//                canvas.restore();
//            }          
//        }
       
        for (int i = 0; i < count; i++) {
            canvas.save();          
            View view=getChildAt(i);
            int childLeft=view.getLeft();
            int dx=Math.abs(scrollX-childLeft);
            //Log.i("child"+i, dx+"-----------");
            if(dx<=width){
                canvas.translate(0.0f, -(1.0f*dx/width)*getHeight());
                Log.i("heigh", getHeight()+"----------");
                drawChild(canvas, view, getDrawingTime());
                canvas.restore();
            }else{
                canvas.translate(0.0f, -1.0f*getHeight());
                drawChild(canvas, view, getDrawingTime());
                canvas.restore();
            }          
        }
        canvas.restoreToCount(saveCount);
在这个过程要注意画布的存储和恢复,不然会出现意外的(奸笑一下),其实这个效果要实现起来也是挺简单的,只是自己做的时候好像走了很多弯路,总之自己学的东西还有很多,继续努力吧!首次写开发的博客,大神们随便喷吧~
分享到:
评论
1 楼 fxiaozj 2014-03-07  
楼主,有没有demo?

相关推荐

    使用ViewGroup实现微信左右滑动切换界面以及界面裂开的效果

    在Android开发中,微信左右滑动切换界面以及界面裂开的效果是通过自定义ViewGroup来实现的,这种效果常见于许多应用中,如微信、支付宝等,为用户提供了一种直观且富有动态感的交互方式。下面我们将深入探讨如何实现...

    android桌面多页面滑动效果

    总的来说,实现"android桌面多页面滑动效果"需要结合Android的基础组件和高级特性,如ViewPager、Adapter、动画和手势识别等。通过对这些知识点的理解和运用,开发者可以构建出功能强大且用户体验良好的多页面滑动...

    Android实现图片左右滑动效果

    在Android开发中,实现图片左右滑动效果是常见的需求,比如在查看相册或轮播图时。这个功能可以通过多种方式实现,其中最常用的是使用ViewPager组件。ViewPager允许用户通过左右滑动手势在多个页面之间切换,非常...

    Android ViewPager多页面滑动切换以及动画效果

    总的来说,`DWinterTabDemo`项目展示了如何在Android应用中使用ViewPager实现多页面滑动,并通过自定义PageTransformer和TabLayout添加动画效果和页面导航。开发者可以根据这个示例学习到如何灵活地控制页面切换的...

    Android 中实现简单的滑动效果

    本教程将聚焦于如何在Android平台上利用ViewPager、Fragment和PagerTabStrip来实现一个简单的页面滑动效果。 **ViewPager组件** ViewPager是Android SDK中的一个强大的控件,用于展示可左右滑动的页面序列。它设计...

    自定义ViewGroup实现ViewPager的滑动效果(附源码下载)

    然而,有时我们需要在更细粒度上控制页面之间的过渡动画或在特定场景下复用类似的滑动效果,这时候通过继承`ViewGroup`来自定义一个具有类似`ViewPager`功能的组件就显得尤为重要。 本文将详细介绍如何通过继承`...

    ViewGroup滑动效果

    总之,自定义ViewGroup的滑动效果是Android开发中的一个重要技能,它要求开发者对触摸事件处理、布局管理、动画有深入理解。通过实践和学习,开发者可以创建出符合项目需求的高效、易用的交互组件。

    ViewGroup实现VIewpager的效果

    在Android开发中,`ViewPager` 是一个非常常用的组件,它允许用户通过左右滑动来切换不同的页面,通常用于实现滑动Tab或者展示一系列相关内容。然而,有时候我们可能需要自定义一个类似`ViewPager`的组件,这通常是...

    android用fragment实现页面滑动

    总结,Fragment在Android应用中提供了强大的UI构建能力,结合ViewPager,我们可以实现流畅的页面滑动效果。在启动页和内部主体页中,Fragment可以帮助我们更好地组织代码,提高代码复用性,同时提供更加动态和交互式...

    android viewpager滑动效果

    本项目“android viewpager滑动效果”专注于实现ViewPager的滑动动态效果,提供了预封装好的接口,使得开发者可以直接使用,无需从头实现复杂的动画逻辑。 ViewPager的滑动效果通常通过PageTransformer来实现,这是...

    安卓动画效果相关-Android实现非常炫酷的滑动动画.rar

    8. **ViewPager与PageTransformer**:`ViewPager`常用于实现页面滑动效果,而`PageTransformer`允许自定义页面在滑动时的变形效果,可以实现很酷的滑动过渡动画。 9. **自定义动画**:除了使用内置的动画API,...

    安卓欢迎界面引导页面viewpager相关-androidSCViewPager欢迎页面滑动效果.rar

    在 `androidSCViewPager 欢迎页面滑动效果.rar` 中,我们可以看到这个库的应用实例。 1. SCViewPager 提供了自定义动画效果,比如平滑的弹性滑动。这可以通过设置 `setPageTransformer` 方法来实现,传入自定义的 `...

    自定义ViewGroup垂直水平滑动解决ViewPager冲突

    首先,我们要明白,ViewPager是Android SDK提供的一种用于展示可滑动页面的控件,通常用于实现类似TabLayout的效果。当ViewGroup和ViewPager在同一界面上时,如果不加以处理,两个组件可能会对用户的滑动手势产生...

    android 页面滑动进入效果

    在Android开发中,实现页面滑动进入的效果是提升用户体验的重要一环。这种效果通常用于页面间的切换、菜单的展开或关闭等场景,给人一种流畅、自然的交互感受。本篇文章将详细探讨如何在Android中实现“页面左右滑动...

    Android 界面滑动效果

    总之,实现“Android 界面滑动效果”涉及了手势识别、滚动视图、滑动布局、事件处理和动画等多个方面。通过深入理解和熟练运用这些技术,开发者可以创造出丰富多样的滑动交互,提升Android应用的用户体验。

    android水平和左右滑动的效果.rar

    2. **ViewPager**:这是Android Support Library中的一个组件,用于实现页面滑动效果,常用于实现如TabLayout下的内容切换。ViewPager可以承载多个Fragment或View,并自动处理滑动手势,提供平滑的页面切换体验。 3...

    android_viewPager左右滑动_实现光标动态滑动效果

    总结起来,实现"android_viewPager左右滑动_实现光标动态滑动效果"的关键在于理解ViewPager的工作原理,创建自定义光标View,并在页面滑动时准确更新光标的位置。通过这样的实践,开发者可以创建出更加交互友好、...

Global site tag (gtag.js) - Google Analytics