Avoid divide by zero

This commit is contained in:
Christophe Smet
2018-10-30 14:27:56 +01:00
parent da9fbb3106
commit 5740def0f9

View File

@@ -2,17 +2,18 @@ package com.littlemango.stacklayoutmanager
import android.support.annotation.IntRange import android.support.annotation.IntRange
import android.support.v7.widget.RecyclerView 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.View
import android.view.ViewGroup import android.view.ViewGroup
class StackLayoutManager(scrollOrientation: ScrollOrientation, class StackLayoutManager(scrollOrientation: ScrollOrientation,
visibleCount: Int, visibleCount: Int,
animation: Class<out StackAnimation>, animation: Class<out StackAnimation>,
layout: Class<out StackLayout>) : RecyclerView.LayoutManager() { layout: Class<out StackLayout>) : RecyclerView.LayoutManager() {
private enum class FlingOrientation{NONE, LEFT_TO_RIGHT, RIGHT_TO_LEFT, TOP_TO_BOTTOM, BOTTOM_TO_TOP} 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 private var mVisibleItemCount = visibleCount
@@ -91,7 +92,7 @@ class StackLayoutManager(scrollOrientation: ScrollOrientation,
* 设置recyclerView 静止时候可见的itemView 个数. * 设置recyclerView 静止时候可见的itemView 个数.
* @param count 可见 itemView默认为3 * @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)) mVisibleItemCount = Math.min(itemCount - 1, Math.max(1, count))
mAnimation?.setVisibleCount(mVisibleItemCount) mAnimation?.setVisibleCount(mVisibleItemCount)
} }
@@ -153,7 +154,10 @@ class StackLayoutManager(scrollOrientation: ScrollOrientation,
* @return 返回第一个可见 itemView 的位置. * @return 返回第一个可见 itemView 的位置.
*/ */
fun getFirstVisibleItemPosition(): Int { 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.RIGHT_TO_LEFT -> Math.floor((mScrollOffset * 1.0 / width)).toInt()
ScrollOrientation.LEFT_TO_RIGHT -> itemCount - 1 - Math.ceil((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() 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) constructor() : this(ScrollOrientation.RIGHT_TO_LEFT)
init { init {
mScrollOffset = when(mScrollOrientation) { mScrollOffset = when (mScrollOrientation) {
ScrollOrientation.RIGHT_TO_LEFT, ScrollOrientation.BOTTOM_TO_TOP -> 0 ScrollOrientation.RIGHT_TO_LEFT, ScrollOrientation.BOTTOM_TO_TOP -> 0
else -> Int.MAX_VALUE else -> Int.MAX_VALUE
} }
@@ -208,7 +212,7 @@ class StackLayoutManager(scrollOrientation: ScrollOrientation,
mOnFlingListener = object : RecyclerView.OnFlingListener() { mOnFlingListener = object : RecyclerView.OnFlingListener() {
override fun onFling(velocityX: Int, velocityY: Int): Boolean { override fun onFling(velocityX: Int, velocityY: Int): Boolean {
if (mPagerMode) { if (mPagerMode) {
when(mScrollOrientation) { when (mScrollOrientation) {
ScrollOrientation.RIGHT_TO_LEFT, ScrollOrientation.LEFT_TO_RIGHT -> { ScrollOrientation.RIGHT_TO_LEFT, ScrollOrientation.LEFT_TO_RIGHT -> {
mFlingOrientation = when { mFlingOrientation = when {
velocityX > mPagerFlingVelocity -> FlingOrientation.RIGHT_TO_LEFT velocityX > mPagerFlingVelocity -> FlingOrientation.RIGHT_TO_LEFT
@@ -264,27 +268,35 @@ class StackLayoutManager(scrollOrientation: ScrollOrientation,
} }
override fun canScrollHorizontally(): Boolean { override fun canScrollHorizontally(): Boolean {
return when(mScrollOrientation) { if (itemCount == 0) {
return false
}
return when (mScrollOrientation) {
ScrollOrientation.LEFT_TO_RIGHT, ScrollOrientation.RIGHT_TO_LEFT -> true ScrollOrientation.LEFT_TO_RIGHT, ScrollOrientation.RIGHT_TO_LEFT -> true
else -> false else -> false
} }
} }
override fun canScrollVertically(): Boolean { override fun canScrollVertically(): Boolean {
return when(mScrollOrientation) { if (itemCount == 0) {
return false
}
return when (mScrollOrientation) {
ScrollOrientation.TOP_TO_BOTTOM, ScrollOrientation.BOTTOM_TO_TOP -> true ScrollOrientation.TOP_TO_BOTTOM, ScrollOrientation.BOTTOM_TO_TOP -> true
else -> false else -> false
} }
} }
override fun onLayoutChildren(recycler: RecyclerView.Recycler, state: RecyclerView.State) { override fun onLayoutChildren(recycler: RecyclerView.Recycler, state: RecyclerView.State) {
mLayout?.requestLayout() mLayout?.requestLayout()
removeAndRecycleAllViews(recycler) removeAndRecycleAllViews(recycler)
mScrollOffset = getValidOffset(mScrollOffset) if (itemCount > 0) {
mScrollOffset = getValidOffset(mScrollOffset)
loadItemView(recycler) loadItemView(recycler)
}
} }
override fun scrollHorizontallyBy(dx: Int, recycler: RecyclerView.Recycler, state: RecyclerView.State): Int { 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) { private fun scrollToCenter(targetPosition: Int, recyclerView: RecyclerView, animation: Boolean) {
val targetOffset = getPositionOffset(targetPosition) val targetOffset = getPositionOffset(targetPosition)
when(mScrollOrientation) { when (mScrollOrientation) {
ScrollOrientation.LEFT_TO_RIGHT, ScrollOrientation.RIGHT_TO_LEFT -> { ScrollOrientation.LEFT_TO_RIGHT, ScrollOrientation.RIGHT_TO_LEFT -> {
if (animation) { if (animation) {
recyclerView.smoothScrollBy(targetOffset - mScrollOffset, 0) recyclerView.smoothScrollBy(targetOffset - mScrollOffset, 0)
@@ -414,14 +426,14 @@ class StackLayoutManager(scrollOrientation: ScrollOrientation,
} }
private fun getValidOffset(expectOffset: Int): Int { 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) 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) else -> Math.max(Math.min(height * (itemCount - 1), expectOffset), 0)
} }
} }
private fun getPositionOffset(position: Int): Int { private fun getPositionOffset(position: Int): Int {
return when(mScrollOrientation) { return when (mScrollOrientation) {
ScrollOrientation.RIGHT_TO_LEFT -> position * width ScrollOrientation.RIGHT_TO_LEFT -> position * width
ScrollOrientation.LEFT_TO_RIGHT -> (itemCount - 1 - position) * width ScrollOrientation.LEFT_TO_RIGHT -> (itemCount - 1 - position) * width
ScrollOrientation.BOTTOM_TO_TOP -> position * height ScrollOrientation.BOTTOM_TO_TOP -> position * height
@@ -439,6 +451,9 @@ class StackLayoutManager(scrollOrientation: ScrollOrientation,
} }
private fun getFirstVisibleItemMovePercent(): Float { private fun getFirstVisibleItemMovePercent(): Float {
if (width == 0 || height == 0) {
return 0f
}
return when (mScrollOrientation) { return when (mScrollOrientation) {
ScrollOrientation.RIGHT_TO_LEFT -> (mScrollOffset % width) * 1.0f / width ScrollOrientation.RIGHT_TO_LEFT -> (mScrollOffset % width) * 1.0f / width
ScrollOrientation.LEFT_TO_RIGHT -> { ScrollOrientation.LEFT_TO_RIGHT -> {
@@ -465,7 +480,7 @@ class StackLayoutManager(scrollOrientation: ScrollOrientation,
//当是 Fling 触发的时候 //当是 Fling 触发的时候
val triggerOrientation = mFlingOrientation val triggerOrientation = mFlingOrientation
mFlingOrientation = FlingOrientation.NONE mFlingOrientation = FlingOrientation.NONE
when(mScrollOrientation) { when (mScrollOrientation) {
ScrollOrientation.RIGHT_TO_LEFT -> { ScrollOrientation.RIGHT_TO_LEFT -> {
if (triggerOrientation == FlingOrientation.RIGHT_TO_LEFT) { if (triggerOrientation == FlingOrientation.RIGHT_TO_LEFT) {
return position + 1 return position + 1
@@ -506,4 +521,4 @@ class StackLayoutManager(scrollOrientation: ScrollOrientation,
position + 1 position + 1
} }
} }
} }