自定义控件Android开发之路安卓UI

LayoutManager学习(二)实现一个梯形滑动列表

2019-06-17  本文已影响31人  刘景昌

刚刚LayoutManager实现了一个仿探探的界面 突然感觉LayoutManager好厉害啊感觉有好多的动画效果可以实现
准备在写几个学习一波 这次实现一个回合梯形的滑动列表
先来看看最最终的效果

3s.gif

首先比较一下和上次实现界面的不同
上次实现的探探的界面其实总体的来说 已经失去的一个列表的滑动的特性只是使用ItemTouch来添加的一些列的变形效果个这次的列表并不是和上次相同的这次只是一个滚动的效果没有上次的ItemTouch效果。虽然是啷个不同的控件但是我们可以使用后相同的实现思路
我们这次的试下流程是
1.继承RecyclerView.LayoutManager
2.重写onLayoutChildren来添加子View 完成一个列表的静态界面
3.重写scrollVerticallyBy来实现竖向滚动 是列表可以滚动
第一步非常的简单所以不多说了 直接开始第二步

创建一个条目类

首先我们分析一下每个条目创建所需要的属性然后使用一个类标识条目

public class ItemViewInfo {
    //scaleXY:每个条目具体的缩放比
    private float scaleXY;
    //top:每个条目具体页面顶部的距离
    private int top;
}

重写onLayoutChildren实现一个静态不可滑动的列表界面

准备工作完成进图正题
1.完成和静态界面
(1)初始化一些必须的参数

    @Override
    public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
        //在这里重新绘制View
        if (state.getItemCount() == 0 || state.isPreLayout()) return;
        removeAndRecycleAllViews(recycler);
        initItemView();
        layoutChildView(recycler);
    }

 //初始化信息
    private void initItemView() {
        mItemViewWidth = (int) (getHorizontalSpace() * mProportion_w);//item的宽
        mItemViewHeight = (int) (mItemViewWidth * mProportion_h_w);//item的高
        mItemCount = getItemCount();
    }

(2)生成所需要的list

    for (int i = bottomItemPosition - 1, j = 1; i >= 0; i--, j++) {
            //配置每一条的偏移量 偏移量为第一条剩余高度 * 偏移系数的第几条次方
            double maxOffset = (getVerticalSpace() - mItemViewHeight) / 2 * Math.pow(mTranslateY, j);
            int top = remainSpace;
            //配置每一条缩放 系数的第几条次方
            float scaleXY = (float) (Math.pow(mScale, j - 1));
            ItemViewInfo info = new ItemViewInfo(top, scaleXY);
            viewInfoArrayList.add(0, info);
            remainSpace = (int) (remainSpace - maxOffset);
            if (remainSpace <= 0) {
                info.setTop((int) (remainSpace + maxOffset));
                break;
            }
        }

(3)根据已生成的list绘制View

       detachAndScrapAttachedViews(recycler);
       for (int i = 0; i < layoutCount; i++) {
            View view = recycler.getViewForPosition(startPos + i);
           ItemViewInfo layoutInfo = viewInfoArrayList.get(i);
           addView(view);
           measureChildWithExactlySize(view);
           int left = (getHorizontalSpace() - mItemViewWidth) / 2;
           layoutDecoratedWithMargins(view, left, layoutInfo.getTop(), left + mItemViewWidth, layoutInfo.getTop() + mItemViewHeight);
           view.setPivotX(view.getWidth() / 2);
           view.setPivotY(0);
           view.setScaleX(layoutInfo.getScaleXY());000000000000
           view.setScaleY(layoutInfo.getScaleXY());
       }
到现在就实现了静态的梯形列表 看下静态的实现效果 test1.png

静态效果实现完了 我们就可以进行下一步

为实现效果添加滚动

在这里面添加滑动就比较简单了
首先重写这个方法是列表可以滑动

   @Override
   public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state) {
       int pendingScrollOffset = mScrollOffset + dy;
       mScrollOffset = Math.min(Math.max(mItemViewHeight, mScrollOffset + dy), mItemCount * mItemViewHeight);
       layoutChildView(recycler);
       return mScrollOffset - pendingScrollOffset + dy;
   }
  @Override
   public boolean canScrollVertically() {
       return true;
   }

然后让我们设置的top 和scaleXY 与mScrollOffset产生关联就行了

           int bottomItemPosition = (int) Math.floor(mScrollOffset / mItemViewHeight);
           int bottomItemVisibleHeight = mScrollOffset % mItemViewHeight;
           double maxOffset = (getVerticalSpace() - mItemViewHeight) / 2 * Math.pow(0.9, j);
           int top = (int) (remainSpace - offsetPercentRelativeToItemView * maxOffset);
           float scaleXY = (float) (Math.pow(mScale, j - 1) * (1 - offsetPercentRelativeToItemView * (1 - mScale)));
           ItemViewInfo info = new ItemViewInfo(top, scaleXY);

这样就可以让滚动和条目的缩放关联

遇到的问题

1.当显示条目较少的时候滑动会有闪烁现象

   private void addEmptyView(int bottomItemPosition,int bottomItemVisibleHeight,List viewInfoArrayList) {
       if (bottomItemPosition < mItemCount) {
           final int start = getVerticalSpace() - bottomItemVisibleHeight;
           ItemViewInfo itemViewInfo = new ItemViewInfo(start,
                   1.0f);
           viewInfoArrayList.add(itemViewInfo);
       } else {
           bottomItemPosition = bottomItemPosition - 1;
       }
   }

我们在它的后面添加一个空的View 这样是它在滑动的时候可以正常的显示了

demo Github地址 :https://github.com/525642022/LayoutManagerTest

上一篇下一篇

猜你喜欢

热点阅读