zoukankan      html  css  js  c++  java
  • “京东金融”主页效果 RecyclerView联动

    先上效果图吧:

    第一个想到的实现方式是上面使用horizontalScrollview,下面使用Viewpager,经过尝试之后发现二者API有限,不能达到理想效果。几经折腾,最后上下都使用了自定义的RecyclerView。效果图如下

    现在来分析技术点,首先是上下联动,思路是在Recycleview的onScrolled回调方法中操作另一个Recycleview的滑动。

    1 @Override
    2 public void onScrolled(int dx, int dy) {
    3     super.onScrolled(dx, dy);
    4     sx = sx +dx;
    5     if (scrollViewListener != null && isMark) {
    6         scrollViewListener.onScrollChanged(this, sx, 0);
    7     }
    8 }

    其中onScrollChanged方法在主页面中实现

     1 @Override
     2 public void onScrollChanged(Object scrollView, int x, int y) {
     3     int width1 = CommonUtil.getScreenWidth(this) - DensityUtils.dip2px(this, 60);
     4     int width2 = CommonUtil.getScreenWidth(this);
     5     if (scrollView == rvHead) {
     6         rvFoot.setmark(false);
     7         rvFoot.scrollTo(x * width2 / width1, y);
     8     } else if (scrollView == rvFoot) {
     9         rvHead.setmark(false);
    10         rvHead.scrollTo(x * width1 / width2, y);
    11     }
    12     rvHead.setmark(true);
    13     rvFoot.setmark(true);
    14 }

    上下View的滑动速率差即为上下RecyclerView中item的宽度差,上面view中item的宽度为屏幕宽度-60dp,详见对应的adapter。

     

    由于RecyclerView中scrollTo方法没有实现,所以直接想到的是用scroolBy代替,但由于滑动回调返回的是Int值,经过速率差处理后精度丢失,得不到准确值,导致联动效果达不到,痛定思痛,最后还是自己来重写scrollTo方法:

    1 @Override
    2 public void scrollTo(int x, int y) {
    3     scrollBy(x-sx,0);
    4 }

    sx为自己在onScrolled方法中记录,具体见文末给出的源码。

     

    滑动之后,还要进行回调处理,以达到像viewPager那样的回弹效果,具体逻辑在自定义的RecyclerView中的回调方法onScrollStateChanged中实现:

     1 public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
     2         super.onScrollStateChanged(recyclerView, newState);
     3         if (newState == RecyclerView.SCROLL_STATE_IDLE) {
     4             int mmSelected;
     5             //当控件停止滚动时,获取可视范围第一个item的位置,滚动调整控件以使选中的item刚好处于正中间
     6             int firstVisiblePos = mLayoutManager.findFirstVisibleItemPosition();
     7             if (firstVisiblePos == RecyclerView.NO_POSITION) {
     8                 return;
     9             }
    10             Rect rect = new Rect();
    11             mLayoutManager.findViewByPosition(firstVisiblePos).getHitRect(rect);
    12             if (Math.abs(rect.left) > mItemWidth / 2) {
    13                 smoothScrollBy(rect.right, 0);
    14                 mmSelected = firstVisiblePos + 1;
    15             } else {
    16                 smoothScrollBy(rect.left, 0);
    17                 mmSelected = firstVisiblePos;
    18             }
    19             if (Math.abs(rect.left) == 0 && mOnSelectListener != null && mmSelected != mSelected) {
    20                 mSelected = mmSelected;
    21                 mOnSelectListener.onSelect(mSelected);
    22             }
    23         }
    24     }
    25 }

    为了让滑动效果更为自然且支持fling效果,本项目还重写了RecyclerView的fling方法,使得每次fling都恰好能滑动整数个item,大致思路为调整fling初始速率,代码如下:

     1 @Override
     2 public boolean fling(int velocityX, int velocityY) {
     3     int v;
     4     int touchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
     5     if (Math.abs(velocityX) <= 3*touchSlop) {
     6         return false;
     7     }
     8     mPhysicalCoeff = SensorManager.GRAVITY_EARTH   // g (m/s^2)
     9             * 39.37f               // inch/meter
    10             * getContext().getResources().getDisplayMetrics().density * 160.0f                 // pixels per inch
    11             * 0.84f;
    12     int firstVisiblePos = mLayoutManager.findFirstVisibleItemPosition();
    13     if (firstVisiblePos == RecyclerView.NO_POSITION) {
    14         return false;
    15     }
    16     Rect rect = new Rect();
    17     mLayoutManager.findViewByPosition(firstVisiblePos).getHitRect(rect);
    18     double n = getSplineFlingDistance(velocityX) / mItemWidth;
    19     int num = Double.valueOf(n).intValue();
    20     if (velocityX > 0)
    21         v = Double.valueOf(getVelocityByDistance(num * mItemWidth + Math.abs(rect.right)- DensityUtils.dip2px(getContext(), 20))).intValue();
    22     else
    23         v = Double.valueOf(getVelocityByDistance(num * mItemWidth + Math.abs(rect.left)+ DensityUtils.dip2px(getContext(), 20))).intValue();
    24     if (velocityX < 0) {
    25         v = -v;
    26     } 
    27     return super.fling(v, velocityY);
    28 }
  • 相关阅读:
    编程语言最终的目标
    浅谈编程语言的类型系统
    编程语言的五大系统
    Java Array、List、Set互相转化
    java 集合类 列表
    Java检查异常、非检查异常、运行时异常、非运行时异常的区别
    java 的枚举变量只能使用枚举常量来初始化--带有关联数据的枚举
    观察与思考

    种田与投资
  • 原文地址:https://www.cnblogs.com/huolongluo/p/9102682.html
Copyright © 2011-2022 走看看