这是我的第一篇博客,总算有个契机开始写博客了,就从自定义LayoutManager开始吧。
前段时间看到一个项目(android-pile-layout),效果特别不错,这是效果图:
效果确实不错,我看了下实现,是用的自定义的ViewGroup实现的,计算什么还搞的挺复杂的,具体的没细看。作者说也尝试过用LayoutManager实现,但是没找到合适的数学模型,好吧,看到数学模型我感觉好特么高端。不过当时我觉得这个肯定是可以用LayoutManager实现的嘛,不过不知道用LayoutManager应该从哪里入手,默默考虑了两天,昨天一口气写的差不多了,写完一看,其实也没写什么,中间遇到了一些问题,总以为解决不了,不过最后也完美解决,感觉美滋滋。
这是我实现的效果,感觉图片很糊,如果有合适的video转gif的软件可以推荐给我,这个gif搞了好久,这应该是质量最好的一张了:
现在来想想怎么实现吧,先不管LayoutManager相关的具体细节,单单就说怎么去建立“数学模型”。其实我看到这个效果的第一眼就觉得是一个函数的问题。这是我做的一张示意图,方便大家理解
这是初始状态下的一张截图。其中第一张图片距离第二张图片的距离是一个固定值,暂且叫space,第一张图片距离左边的距离是4个space(这个距离是可以配置的)。我们把第一张图片的位置叫做基准位置,很多计算都和这个位置有关系。并且这个LayoutManager的前提是每个Item都是一样的尺寸。当滚动距离是一个Item宽度和space之和时,那么就会切换到下一个item,像下面这张图所示的这样:
第一张图片后面的图片都会小一点,并且依次间隔距离都是space。那么在这个模型中,我们要知道的其实就是,在滚动给定距离的情况下,计算所有应该显示出来item 的左边距,透明度和缩放应该是多少,并且把这些Item摆放在正确的位置,那么就变成一个很普通的找这些距离,透明度,缩放和滚动距离之间的对应关系的问题,就是所谓的“数学模型”,哈哈,感觉也很简单嘛。
不过在做这些之前建议大家先看一下LayoutManager相关的知识,不过我也没完全弄明白,看懂了大概就开始屁颠屁颠的写那些函数了。
首先是继承LayoutManager,这个没的说,为了让自定LayoutManager能够接收到水平滚动事件,必须重写canScrollHorizontally方法,返回true,表示告诉RecyclerView,水平滚动事件我都要了。
@Override public boolean canScrollHorizontally() { return true; }
这样还不够,每次滚动的距离要传递过来吧,所以还要重写scrollHorizontallyBy方法,用于接收滚动的距离,根据滚动的距离做计算和调整
@Override public int scrollHorizontallyBy(int dx, RecyclerView.Recycler recycler, RecyclerView.State state) { return fill(recycler, dx); }
另外我们还定义一些变量用于记录关键的值
//the space unit for the stacked item int mSpace = 60; //the offset unit,deciding current position(the sum of one child's width and one space) int mUnit; //the counting variable ,save the total offset int mTotalOffset; ObjectAnimator animator; private int animateValue; private int duration = 300; private RecyclerView.Recycler recycler; private int lastAnimateValue; private int maxStackCount = 4;//the max stacked item count; private int initialStackCount = 4;//initial stacked item private float