LibGdx滑动渐变的实现

目标

实现如下图所示的切换效果

实现效果.gif

功能分析

  • 需要一个透明度参数,下一个场景慢慢出现,上一个场景慢慢消失
  • 滑动前需要知道左右场景的weatherId,才能完成向下一场景的切换。weatherId可以通过不同天气fragment的天气数据得到,我的做法是在viewpager中得到fragment再从fragment中得到天气数据,再得到weatherId。
  • 根据滑动方向和当前fragmentviewpager中的itemId来确定下一个场景的weatherId

层次结构




    
    
    

    



如上面布局所示,底层是一个framelayout用来存放LibGdx中自定义的AndroidFragmentApplication。上层是一个viewpager,用来存放多个fragment,左右滑动时可以切换不同的fragment

监听ViewPager滑动

获取稳定的1~0参数
  • onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
    在这个方法中监听到的,当向左滑动时positionOffset是从1~0。
    当向右滑动时positionOffset是从010。
  • 产生的问题:
0-1-0参数.gif

通过监听知道:当向右滑动时在onPageScrolled方法中执行以下操作可以得到0~1的参数。

     if(lastPosition!=position) {
         posit = 1;
         lastPosition = position;
      }

如果当左滑动时取posit,当向右滑动时1-posit就得到了稳定的1~0参数。

  • 当需要参数变化有速度上的变化可以参照AndroidInterpolator的算法。例如,先慢后快的参数变化:
 posit = (float)(Math.cos((posit + 1) * Math.PI) / 2.0f) + 0.5f;

接下来需要得到下一个场景的weatherId。

根据滑动方向得到下一个场景的天气Id
    if (right) {//滑不动的时候,是不再滑的。
            String integer = null;
            try {
                 integer = weatherIdses.get(currentPosition + 1);
                } catch (Exception e) {
                     e.printStackTrace();
               }
                if (integer != null) {
                   MJSceneManager.getInstance().switchScreen(integer, posit);
                 }
            } else {
                    String integer = null;
                    try {
                        integer = weatherIdses.get(currentPosition - 1);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    if (integer != null) {
                        MJSceneManager.getInstance().switchScreen(integer, posit);
                    }
            }

判断滑动方向得到下一个场景的weatherId切换到下一个场景。

�判断滑动方向
  • 判断的第一步
onPageScrolled(int position, float positionOffset, int positionOffsetPixels){
    currentPosition = mViewPager.getCurrentItem();
    if(position >= currentPosition) {
       right = true;
       left = false;
    } else {
       right = false;
       left = true;
    }
 }

当向右滑动时position=currentPosition。当向左滑动并没滑动到尽头时position。但是当向左滑动并且滑动到尽头时position=currentPosition。判断结果是向右滑动,因为场景会发生变化。

  • 判断第二步

出现的问题:

判断第二步.gif

问题原因: 当向左滑动时滑动到尽头时方向判断是错的。

解决方法:判断左边滑动到尽头

onPageScrolled(int position, float positionOffset, int positionOffsetPixels){
    currentPosition = mViewPager.getCurrentItem();
    if(position >= currentPosition) {
       right = true;
       left = false;
    } else {
       right = false;
       left = true;
    }
   if(currentPosition == 0&&isScrolling&&positionOffset == 0) {//左边滑动的时候,判断是不是滑动到了头。
        right = false;
        left = false;
    }
 }

加上下面的这个判断可以判断是否是向左滑动到头,这时也要判断即不是向左边滑动也不是向右边滑动。
其中isScrolling的标志是判断viewPager是否正在滑动,判断方法如下:

  public void onPageScrollStateChanged(int state,ScrollCallBack callBack) {
        //stage=1表示正在滑动
        //stage=2表示滑动完毕了
        //stage=0表示什么都没做
        if(state == 1) {
            isScrolling = true;
        } else {
            isScrolling = false;//当连续缓慢滑动时没有调用滑动完毕,只调用
        }
  • 判断第三步

出现的问题:如下图

判断第三步.gif

问题原因:当左右滑动时,滑动到一半松手后自动滑动到下一页时,上面的方向判断就会出错,mViewPager.getCurrentItem()该方法在滑动到一半时松手,值会发生变化。具体表现如下图:

解决方法:

onPageScrolled(int position, float positionOffset, int positionOffsetPixels){
   if(first) {
       currentPosition = mViewPager.getCurrentItem();
       if(position >= currentPosition) {
          right = true;
          left = false;
       } else {
          right = false;
          left = true;
       }
      if(currentPosition == 0&&isScrolling&&positionOffset == 0) {//左边滑动   的时候,判断是不是滑动到了头。
           right = false;
           left = false;
       }
    }
   isFirst = false;
  }

加上以上判断可以解决滑动方向的判断。isFirst什么时候还原呢?

public void onPageScrollStateChanged(int state,ScrollCallBack callBack) {
        //stage=1表示正在滑动
        //stage=2表示滑动完毕了
        //stage=0表示什么都没做
        if(state == 0) {
            isFirst = true;
        } 
  • 判断第四步

出现的问题:如下图所示

判断第四步.gif

问题原因:左右滑动到尽头时,转变方向时,isFirst没有被重置,方向判断错误。场景不发生变化。

解决方法:判断左右滑动到尽头,并转变方向时,重新计算滑动的方向。

onPageScrolled(int position, float positionOffset, int positionOffsetPixels){
        if(scrollStage == 1&&position == mViewPager.getCurrentItem()&&positionOffsetPixels == 0) {
                mIsEnd = true;
         } else {
                mIsEnd = false;
         }

        if(lastEnd&&!mIsEnd) {
            isFirst = true;
        }
      if(first) {
         currentPosition = mViewPager.getCurrentItem();
         if(position >= currentPosition) {
          right = true;
          left = false;
         } else {
          right = false;
          left = true;
         }
        if(currentPosition == 0&&isScrolling&&positionOffset == 0) {//左边滑动   的时候,判断是不是滑动到了头。
           right = false;
           left = false;
         }
        isFirst = false;
      }

     lastEnd = mIsEnd;
  }

下面这个方法判断左边和右边滑动到头。其中scrollState=1表明正在滑动。

    if(scrollState == 1&&position == mViewPager.getCurrentItem()&&positionOffsetPixels == 0) {
                mIsEnd = true;
         } else {
                mIsEnd = false;
         }

判断左边和右边滑动到头后,突然转变方向,则是下面这个方法来判断。

 if(lastEnd&&!mIsEnd) {
          isFirst = true;
      }
  • 判断第五步
    出现的问题:如下图所示
判断第五步.gif

问题原因: 当手指粘着屏幕左右滑动时,isFirst没有更新,导致方向判断错误。
解决方法:判断手指粘着屏幕滑动。重置isFirst参数

 public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels,ScrollCallBack callBack) {
            if(scrollStage == 1&&lastPixels!=0&&Math.abs(lastPixels - positionOffsetPixels) >500) {
              isFirst = true;
                1、MJSceneManager.getInstance().setPageSelect(currentPosition - position);
            }

     if(scrollStage == 1&&position == mViewPager.getCurrentItem()&&positionOffsetPixels == 0) {
                mIsEnd = true;
         } else {
                mIsEnd = false;
         }

        if(lastEnd&&!mIsEnd) {
            isFirst = true;
        }
      if(first) {
         currentPosition = mViewPager.getCurrentItem();
         if(position >= currentPosition) {
          right = true;
          left = false;
         } else {
          right = false;
          left = true;
         }
        if(currentPosition == 0&&isScrolling&&positionOffset == 0) {//左边滑动   的时候,判断是不是滑动到了头。
           right = false;
           left = false;
         }
        isFirst = false;
      }

     lastEnd = mIsEnd;
}

  • 判断第六步

出现的问题:当快速滑动时场景会出现以下问题:

判断第六步.gif

问题的原因:是下一个场景在快速滑动时没有赋值给当前场景, 当前场景一直没有改为,出现场景重叠。
解决方法:快速滑动时把下一个场景赋值给当前场景,并把下一个场景置为空。

MJSceneManager.getInstance().setPageSelect(currentPosition - position);

具体代码如下:

 public void setPageSelect(int diff) {//触摸不松手滑动到ViewPager中item变化的时候
        hasInitStage = false;
        pageSelect = true;

        if(diff == 0||diff == 1) {//左右粘着滑动,
        } else if(diff == 2||diff == -1){ //左右快速滑动
            alpha = 1.0f;
            useAlpha = 1.0f;
            isSwitch = false;
            mIsScroll = false;
            pageSelect = false;
            if(mNextStage != null) {
                mCurrentStage = mNextStage;
            }
            mNextStage = null;
        }
    }
  • 判断第七步

出现的问题:如下图所示

判断第七步.gif

问题原因:在左右粘着滑动时,当前场景一直没有变化,而上一个步骤把当前场景给置空了,因此需要判断粘着滑动不作任何处理。

解决方法:区分粘着滑动和快速滑动。方法public void setPageSelect(int diff)的参数是为了区分快速滑动和左右粘着滑动。

 public void setPageSelect(int diff) {//触摸不松手滑动到ViewPager中item变化的时候
        hasInitStage = false;
        pageSelect = true;

        if(diff == 0||diff == 1) {//左右粘着滑动,
        } else if(diff == 2||diff == -1){ //左右快速滑动
            alpha = 1.0f;
            useAlpha = 1.0f;
            isSwitch = false;
            mIsScroll = false;
            pageSelect = false;
            if(mNextStage != null) {
                mCurrentStage = mNextStage;
            }
            mNextStage = null;
        }
    }

至此,LigGdx滑动渐变的实现过程分析完毕,下一次会分析一下粒子和骨骼动画的融合。

你可能感兴趣的:(LibGdx滑动渐变的实现)