From 5740def0f9215569dec4af5bc01f1193c89e83e6 Mon Sep 17 00:00:00 2001 From: Christophe Smet Date: Tue, 30 Oct 2018 14:27:56 +0100 Subject: [PATCH] Avoid divide by zero --- .../stacklayoutmanager/StackLayoutManager.kt | 55 ++++++++++++------- 1 file changed, 35 insertions(+), 20 deletions(-) diff --git a/StackLayoutManager/src/main/java/com/littlemango/stacklayoutmanager/StackLayoutManager.kt b/StackLayoutManager/src/main/java/com/littlemango/stacklayoutmanager/StackLayoutManager.kt index 8fd1e73..a72351a 100644 --- a/StackLayoutManager/src/main/java/com/littlemango/stacklayoutmanager/StackLayoutManager.kt +++ b/StackLayoutManager/src/main/java/com/littlemango/stacklayoutmanager/StackLayoutManager.kt @@ -2,17 +2,18 @@ package com.littlemango.stacklayoutmanager import android.support.annotation.IntRange import android.support.v7.widget.RecyclerView -import android.support.v7.widget.RecyclerView.* +import android.support.v7.widget.RecyclerView.SCROLL_STATE_DRAGGING +import android.support.v7.widget.RecyclerView.SCROLL_STATE_IDLE import android.view.View import android.view.ViewGroup class StackLayoutManager(scrollOrientation: ScrollOrientation, - visibleCount: Int, - animation: Class, - layout: Class) : RecyclerView.LayoutManager() { - private enum class FlingOrientation{NONE, LEFT_TO_RIGHT, RIGHT_TO_LEFT, TOP_TO_BOTTOM, BOTTOM_TO_TOP} + visibleCount: Int, + animation: Class, + layout: Class) : RecyclerView.LayoutManager() { + private enum class FlingOrientation { NONE, LEFT_TO_RIGHT, RIGHT_TO_LEFT, TOP_TO_BOTTOM, BOTTOM_TO_TOP } - enum class ScrollOrientation{LEFT_TO_RIGHT, RIGHT_TO_LEFT, TOP_TO_BOTTOM, BOTTOM_TO_TOP} + enum class ScrollOrientation { LEFT_TO_RIGHT, RIGHT_TO_LEFT, TOP_TO_BOTTOM, BOTTOM_TO_TOP } private var mVisibleItemCount = visibleCount @@ -91,7 +92,7 @@ class StackLayoutManager(scrollOrientation: ScrollOrientation, * 设置recyclerView 静止时候可见的itemView 个数. * @param count 可见 itemView,默认为3 */ - fun setVisibleItemCount(@IntRange(from = 1, to = Long.MAX_VALUE)count: Int) { + fun setVisibleItemCount(@IntRange(from = 1, to = Long.MAX_VALUE) count: Int) { mVisibleItemCount = Math.min(itemCount - 1, Math.max(1, count)) mAnimation?.setVisibleCount(mVisibleItemCount) } @@ -153,7 +154,10 @@ class StackLayoutManager(scrollOrientation: ScrollOrientation, * @return 返回第一个可见 itemView 的位置. */ fun getFirstVisibleItemPosition(): Int { - return when(mScrollOrientation) { + if (width == 0 || height == 0) { + return 0 + } + return when (mScrollOrientation) { ScrollOrientation.RIGHT_TO_LEFT -> Math.floor((mScrollOffset * 1.0 / width)).toInt() ScrollOrientation.LEFT_TO_RIGHT -> itemCount - 1 - Math.ceil((mScrollOffset * 1.0 / width)).toInt() ScrollOrientation.BOTTOM_TO_TOP -> Math.floor((mScrollOffset * 1.0 / height)).toInt() @@ -175,7 +179,7 @@ class StackLayoutManager(scrollOrientation: ScrollOrientation, constructor() : this(ScrollOrientation.RIGHT_TO_LEFT) init { - mScrollOffset = when(mScrollOrientation) { + mScrollOffset = when (mScrollOrientation) { ScrollOrientation.RIGHT_TO_LEFT, ScrollOrientation.BOTTOM_TO_TOP -> 0 else -> Int.MAX_VALUE } @@ -208,7 +212,7 @@ class StackLayoutManager(scrollOrientation: ScrollOrientation, mOnFlingListener = object : RecyclerView.OnFlingListener() { override fun onFling(velocityX: Int, velocityY: Int): Boolean { if (mPagerMode) { - when(mScrollOrientation) { + when (mScrollOrientation) { ScrollOrientation.RIGHT_TO_LEFT, ScrollOrientation.LEFT_TO_RIGHT -> { mFlingOrientation = when { velocityX > mPagerFlingVelocity -> FlingOrientation.RIGHT_TO_LEFT @@ -264,27 +268,35 @@ class StackLayoutManager(scrollOrientation: ScrollOrientation, } override fun canScrollHorizontally(): Boolean { - return when(mScrollOrientation) { + if (itemCount == 0) { + return false + } + return when (mScrollOrientation) { ScrollOrientation.LEFT_TO_RIGHT, ScrollOrientation.RIGHT_TO_LEFT -> true else -> false } } override fun canScrollVertically(): Boolean { - return when(mScrollOrientation) { + if (itemCount == 0) { + return false + } + return when (mScrollOrientation) { ScrollOrientation.TOP_TO_BOTTOM, ScrollOrientation.BOTTOM_TO_TOP -> true else -> false } } override fun onLayoutChildren(recycler: RecyclerView.Recycler, state: RecyclerView.State) { + mLayout?.requestLayout() removeAndRecycleAllViews(recycler) - mScrollOffset = getValidOffset(mScrollOffset) - - loadItemView(recycler) + if (itemCount > 0) { + mScrollOffset = getValidOffset(mScrollOffset) + loadItemView(recycler) + } } override fun scrollHorizontallyBy(dx: Int, recycler: RecyclerView.Recycler, state: RecyclerView.State): Int { @@ -395,7 +407,7 @@ class StackLayoutManager(scrollOrientation: ScrollOrientation, private fun scrollToCenter(targetPosition: Int, recyclerView: RecyclerView, animation: Boolean) { val targetOffset = getPositionOffset(targetPosition) - when(mScrollOrientation) { + when (mScrollOrientation) { ScrollOrientation.LEFT_TO_RIGHT, ScrollOrientation.RIGHT_TO_LEFT -> { if (animation) { recyclerView.smoothScrollBy(targetOffset - mScrollOffset, 0) @@ -414,14 +426,14 @@ class StackLayoutManager(scrollOrientation: ScrollOrientation, } private fun getValidOffset(expectOffset: Int): Int { - return when(mScrollOrientation) { + return when (mScrollOrientation) { ScrollOrientation.RIGHT_TO_LEFT, ScrollOrientation.LEFT_TO_RIGHT -> Math.max(Math.min(width * (itemCount - 1), expectOffset), 0) else -> Math.max(Math.min(height * (itemCount - 1), expectOffset), 0) } } private fun getPositionOffset(position: Int): Int { - return when(mScrollOrientation) { + return when (mScrollOrientation) { ScrollOrientation.RIGHT_TO_LEFT -> position * width ScrollOrientation.LEFT_TO_RIGHT -> (itemCount - 1 - position) * width ScrollOrientation.BOTTOM_TO_TOP -> position * height @@ -439,6 +451,9 @@ class StackLayoutManager(scrollOrientation: ScrollOrientation, } private fun getFirstVisibleItemMovePercent(): Float { + if (width == 0 || height == 0) { + return 0f + } return when (mScrollOrientation) { ScrollOrientation.RIGHT_TO_LEFT -> (mScrollOffset % width) * 1.0f / width ScrollOrientation.LEFT_TO_RIGHT -> { @@ -465,7 +480,7 @@ class StackLayoutManager(scrollOrientation: ScrollOrientation, //当是 Fling 触发的时候 val triggerOrientation = mFlingOrientation mFlingOrientation = FlingOrientation.NONE - when(mScrollOrientation) { + when (mScrollOrientation) { ScrollOrientation.RIGHT_TO_LEFT -> { if (triggerOrientation == FlingOrientation.RIGHT_TO_LEFT) { return position + 1 @@ -506,4 +521,4 @@ class StackLayoutManager(scrollOrientation: ScrollOrientation, position + 1 } } -} \ No newline at end of file +}