mirror of
https://github.com/leaf-wai/StackLayoutManager.git
synced 2026-03-14 08:42:50 +08:00
1.迁移到AndroidX
2.修改支持无限循环滑动
This commit is contained in:
3
.idea/misc.xml
generated
3
.idea/misc.xml
generated
@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="NullableNotNullManager">
|
||||
<option name="myDefaultNullable" value="android.support.annotation.Nullable" />
|
||||
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
|
||||
@ -25,7 +26,7 @@
|
||||
</value>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
|
||||
10
.idea/modules.xml
generated
10
.idea/modules.xml
generated
@ -1,10 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/StackLayoutManager.iml" filepath="$PROJECT_DIR$/StackLayoutManager.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/StackLayoutManager/StackLayoutManager-StackLayoutManager.iml" filepath="$PROJECT_DIR$/StackLayoutManager/StackLayoutManager-StackLayoutManager.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/sample/sample.iml" filepath="$PROJECT_DIR$/sample/sample.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
12
.idea/runConfigurations.xml
generated
12
.idea/runConfigurations.xml
generated
@ -1,12 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RunConfigurationProducerService">
|
||||
<option name="ignoredProducers">
|
||||
<set>
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
|
||||
</set>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
@ -3,15 +3,15 @@ apply plugin: 'kotlin-android'
|
||||
apply plugin: 'com.novoda.bintray-release'
|
||||
|
||||
android {
|
||||
compileSdkVersion 27
|
||||
compileSdkVersion 31
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 14
|
||||
targetSdkVersion 27
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 31
|
||||
versionCode 6
|
||||
versionName "1.0.5"
|
||||
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
|
||||
|
||||
}
|
||||
|
||||
@ -30,7 +30,7 @@ android {
|
||||
dependencies {
|
||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
implementation 'com.android.support:recyclerview-v7:27.1.1'
|
||||
implementation 'androidx.recyclerview:recyclerview:1.2.1'
|
||||
}
|
||||
repositories {
|
||||
mavenCentral()
|
||||
|
||||
@ -2,6 +2,7 @@ package com.littlemango.stacklayoutmanager
|
||||
|
||||
import android.view.View
|
||||
import com.littlemango.stacklayoutmanager.StackLayoutManager.ScrollOrientation
|
||||
import kotlin.math.pow
|
||||
|
||||
class DefaultAnimation(scrollOrientation: ScrollOrientation, visibleCount: Int) : StackAnimation(scrollOrientation, visibleCount) {
|
||||
|
||||
@ -72,8 +73,8 @@ class DefaultAnimation(scrollOrientation: ScrollOrientation, visibleCount: Int)
|
||||
scale = 1 - ((1 - mOutScale) * firstMovePercent)
|
||||
rotation = mOutRotation * firstMovePercent
|
||||
} else {
|
||||
val minScale = (Math.pow(mScale.toDouble(), position.toDouble())).toFloat()
|
||||
val maxScale = (Math.pow(mScale.toDouble(), (position - 1).toDouble())).toFloat()
|
||||
val minScale = (mScale.toDouble().pow(position.toDouble())).toFloat()
|
||||
val maxScale = (mScale.toDouble().pow((position - 1).toDouble())).toFloat()
|
||||
scale = minScale + (maxScale - minScale) * firstMovePercent
|
||||
//只对最后一个 item 做透明度变化
|
||||
if (position == mVisibleCount) {
|
||||
|
||||
@ -47,12 +47,18 @@ class DefaultLayout(scrollOrientation: StackLayoutManager.ScrollOrientation,
|
||||
|
||||
private fun getFirstVisibleItemLeft(): Int {
|
||||
return when(mScrollOrientation) {
|
||||
StackLayoutManager.ScrollOrientation.RIGHT_TO_LEFT -> mStartMargin - mScrollOffset % mWidth
|
||||
StackLayoutManager.ScrollOrientation.RIGHT_TO_LEFT -> {
|
||||
var offset = mScrollOffset % mWidth
|
||||
if (offset < 0) offset += mWidth
|
||||
mStartMargin - offset
|
||||
}
|
||||
StackLayoutManager.ScrollOrientation.LEFT_TO_RIGHT -> {
|
||||
return if (mScrollOffset % mWidth == 0) {
|
||||
mStartMargin
|
||||
} else {
|
||||
mStartMargin + (mWidth - mScrollOffset % mWidth)
|
||||
var offset = mScrollOffset % mWidth
|
||||
if (offset < 0) offset += mWidth
|
||||
mStartMargin + (mWidth - offset)
|
||||
}
|
||||
}
|
||||
else -> mWidthSpace / 2
|
||||
@ -61,12 +67,18 @@ class DefaultLayout(scrollOrientation: StackLayoutManager.ScrollOrientation,
|
||||
|
||||
private fun getFirstVisibleItemTop(): Int {
|
||||
return when(mScrollOrientation) {
|
||||
StackLayoutManager.ScrollOrientation.BOTTOM_TO_TOP -> mStartMargin - mScrollOffset % mHeight
|
||||
StackLayoutManager.ScrollOrientation.BOTTOM_TO_TOP -> {
|
||||
var offset = mScrollOffset % mHeight
|
||||
if (offset < 0) offset += mHeight
|
||||
mStartMargin - offset
|
||||
}
|
||||
StackLayoutManager.ScrollOrientation.TOP_TO_BOTTOM -> {
|
||||
return if (mScrollOffset % mHeight == 0) {
|
||||
mStartMargin
|
||||
} else {
|
||||
mStartMargin + (mHeight - mScrollOffset % mHeight)
|
||||
var offset = mScrollOffset % mHeight
|
||||
if (offset < 0) offset += mHeight
|
||||
mStartMargin + (mHeight - offset)
|
||||
}
|
||||
}
|
||||
else -> mHeightSpace / 2
|
||||
|
||||
@ -1,19 +1,23 @@
|
||||
package com.littlemango.stacklayoutmanager
|
||||
|
||||
import android.support.annotation.IntRange
|
||||
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 androidx.annotation.IntRange
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.recyclerview.widget.RecyclerView.SCROLL_STATE_DRAGGING
|
||||
import androidx.recyclerview.widget.RecyclerView.SCROLL_STATE_IDLE
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import kotlin.math.ceil
|
||||
import kotlin.math.floor
|
||||
|
||||
class StackLayoutManager(scrollOrientation: ScrollOrientation,
|
||||
visibleCount: Int,
|
||||
animation: Class<out StackAnimation>,
|
||||
layout: Class<out StackLayout>) : RecyclerView.LayoutManager() {
|
||||
private enum class FlingOrientation{NONE, LEFT_TO_RIGHT, RIGHT_TO_LEFT, TOP_TO_BOTTOM, BOTTOM_TO_TOP}
|
||||
class StackLayoutManager(
|
||||
scrollOrientation: ScrollOrientation,
|
||||
visibleCount: Int,
|
||||
animation: Class<out StackAnimation>,
|
||||
layout: Class<out StackLayout>
|
||||
) : 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
|
||||
|
||||
@ -26,6 +30,7 @@ class StackLayoutManager(scrollOrientation: ScrollOrientation,
|
||||
|
||||
//做动画的组件,支持自定义
|
||||
private var mAnimation: StackAnimation? = null
|
||||
|
||||
//做布局的组件,支持自定义
|
||||
private var mLayout: StackLayout? = null
|
||||
|
||||
@ -78,7 +83,7 @@ class StackLayoutManager(scrollOrientation: ScrollOrientation,
|
||||
* @param velocity 默认值是2000.
|
||||
*/
|
||||
fun setPagerFlingVelocity(@IntRange(from = 0, to = Int.MAX_VALUE.toLong()) velocity: Int) {
|
||||
mPagerFlingVelocity = Math.min(Int.MAX_VALUE, Math.max(0, velocity))
|
||||
mPagerFlingVelocity = Int.MAX_VALUE.coerceAtMost(0.coerceAtLeast(velocity))
|
||||
}
|
||||
|
||||
/**
|
||||
@ -92,8 +97,8 @@ class StackLayoutManager(scrollOrientation: ScrollOrientation,
|
||||
* 设置recyclerView 静止时候可见的itemView 个数.
|
||||
* @param count 可见 itemView,默认为3
|
||||
*/
|
||||
fun setVisibleItemCount(@IntRange(from = 1, to = Long.MAX_VALUE)count: Int) {
|
||||
mVisibleItemCount = Math.min(itemCount - 1, Math.max(1, count))
|
||||
fun setVisibleItemCount(@IntRange(from = 1, to = Long.MAX_VALUE) count: Int) {
|
||||
mVisibleItemCount = (itemCount - 1).coerceAtMost(1.coerceAtLeast(count))
|
||||
mAnimation?.setVisibleCount(mVisibleItemCount)
|
||||
}
|
||||
|
||||
@ -157,11 +162,11 @@ class StackLayoutManager(scrollOrientation: ScrollOrientation,
|
||||
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()
|
||||
ScrollOrientation.TOP_TO_BOTTOM -> itemCount - 1 - Math.ceil((mScrollOffset * 1.0 / height)).toInt()
|
||||
return when (mScrollOrientation) {
|
||||
ScrollOrientation.RIGHT_TO_LEFT -> floor((mScrollOffset * 1.0 / width)).toInt()
|
||||
ScrollOrientation.LEFT_TO_RIGHT -> itemCount - 1 - ceil((mScrollOffset * 1.0 / width)).toInt()
|
||||
ScrollOrientation.BOTTOM_TO_TOP -> floor((mScrollOffset * 1.0 / height)).toInt()
|
||||
ScrollOrientation.TOP_TO_BOTTOM -> itemCount - 1 - ceil((mScrollOffset * 1.0 / height)).toInt()
|
||||
}
|
||||
}
|
||||
|
||||
@ -179,14 +184,17 @@ 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
|
||||
}
|
||||
|
||||
if (StackAnimation::class.java.isAssignableFrom(animation)) {
|
||||
try {
|
||||
val cla = animation.getDeclaredConstructor(ScrollOrientation::class.java, Int::class.javaPrimitiveType)
|
||||
val cla = animation.getDeclaredConstructor(
|
||||
ScrollOrientation::class.java,
|
||||
Int::class.javaPrimitiveType
|
||||
)
|
||||
mAnimation = cla.newInstance(scrollOrientation, visibleCount) as StackAnimation
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
@ -194,7 +202,11 @@ class StackLayoutManager(scrollOrientation: ScrollOrientation,
|
||||
}
|
||||
if (StackLayout::class.java.isAssignableFrom(layout)) {
|
||||
try {
|
||||
val cla = layout.getDeclaredConstructor(ScrollOrientation::class.java, Int::class.javaPrimitiveType, Int::class.javaPrimitiveType)
|
||||
val cla = layout.getDeclaredConstructor(
|
||||
ScrollOrientation::class.java,
|
||||
Int::class.javaPrimitiveType,
|
||||
Int::class.javaPrimitiveType
|
||||
)
|
||||
mLayout = cla.newInstance(scrollOrientation, visibleCount, 30) as StackLayout
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
@ -203,8 +215,10 @@ class StackLayoutManager(scrollOrientation: ScrollOrientation,
|
||||
}
|
||||
|
||||
override fun generateDefaultLayoutParams(): RecyclerView.LayoutParams {
|
||||
return RecyclerView.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
return RecyclerView.LayoutParams(
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
)
|
||||
}
|
||||
|
||||
override fun onAttachedToWindow(view: RecyclerView) {
|
||||
@ -212,7 +226,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
|
||||
@ -299,11 +313,19 @@ class StackLayoutManager(scrollOrientation: ScrollOrientation,
|
||||
}
|
||||
}
|
||||
|
||||
override fun scrollHorizontallyBy(dx: Int, recycler: RecyclerView.Recycler, state: RecyclerView.State): Int {
|
||||
override fun scrollHorizontallyBy(
|
||||
dx: Int,
|
||||
recycler: RecyclerView.Recycler,
|
||||
state: RecyclerView.State
|
||||
): Int {
|
||||
return handleScrollBy(dx, recycler)
|
||||
}
|
||||
|
||||
override fun scrollVerticallyBy(dy: Int, recycler: RecyclerView.Recycler, state: RecyclerView.State?): Int {
|
||||
override fun scrollVerticallyBy(
|
||||
dy: Int,
|
||||
recycler: RecyclerView.Recycler,
|
||||
state: RecyclerView.State?
|
||||
): Int {
|
||||
return handleScrollBy(dy, recycler)
|
||||
}
|
||||
|
||||
@ -315,7 +337,11 @@ class StackLayoutManager(scrollOrientation: ScrollOrientation,
|
||||
requestLayout()
|
||||
}
|
||||
|
||||
override fun smoothScrollToPosition(recyclerView: RecyclerView, state: RecyclerView.State?, position: Int) {
|
||||
override fun smoothScrollToPosition(
|
||||
recyclerView: RecyclerView,
|
||||
state: RecyclerView.State?,
|
||||
position: Int
|
||||
) {
|
||||
if (position < 0 || position >= itemCount) {
|
||||
throw ArrayIndexOutOfBoundsException("$position is out of bound [0..$itemCount-1]")
|
||||
}
|
||||
@ -337,59 +363,51 @@ class StackLayoutManager(scrollOrientation: ScrollOrientation,
|
||||
}
|
||||
|
||||
private fun handleScrollBy(offset: Int, recycler: RecyclerView.Recycler): Int {
|
||||
//期望值,不得超过最大最小值,所以期望值不一定等于实际值
|
||||
val expectOffset = mScrollOffset + offset
|
||||
|
||||
//实际值
|
||||
mScrollOffset = getValidOffset(expectOffset)
|
||||
|
||||
//实际偏移,超过最大最小值之后的偏移都应该是0,该值作为返回值,否则在极限位置进行滚动的时候不会出现弹性阴影
|
||||
val exactMove = mScrollOffset - expectOffset + offset
|
||||
|
||||
if (exactMove == 0) {
|
||||
//itemViews 位置都不会改变,直接 return
|
||||
return 0
|
||||
}
|
||||
|
||||
mScrollOffset += offset
|
||||
detachAndScrapAttachedViews(recycler)
|
||||
|
||||
loadItemView(recycler)
|
||||
return exactMove
|
||||
|
||||
return offset
|
||||
}
|
||||
|
||||
private fun loadItemView(recycler: RecyclerView.Recycler) {
|
||||
val firstVisiblePosition = getFirstVisibleItemPosition()
|
||||
val lastVisiblePosition = getLastVisibleItemPosition()
|
||||
|
||||
val lastVisiblePosition = getFirstVisibleItemPosition() + mVisibleItemCount - 1
|
||||
//位移百分比
|
||||
val movePercent = getFirstVisibleItemMovePercent()
|
||||
var movePercent = getFirstVisibleItemMovePercent()
|
||||
if (movePercent < 0) movePercent += 1
|
||||
|
||||
for (i in lastVisiblePosition downTo firstVisiblePosition) {
|
||||
val view = recycler.getViewForPosition(i)
|
||||
for (i in (mVisibleItemCount - 1) downTo 0) {
|
||||
var position = (firstVisiblePosition + i) % itemCount
|
||||
if (position < 0) {
|
||||
position += itemCount
|
||||
}
|
||||
val view = recycler.getViewForPosition(position)
|
||||
//添加到recycleView 中
|
||||
addView(view)
|
||||
//测量
|
||||
measureChild(view, 0, 0)
|
||||
//布局
|
||||
mLayout?.doLayout(this, mScrollOffset, movePercent, view, i - firstVisiblePosition)
|
||||
mLayout?.doLayout(this, mScrollOffset, movePercent, view, i)
|
||||
//做动画
|
||||
mAnimation?.doAnimation(movePercent, view, i - firstVisiblePosition)
|
||||
mAnimation?.doAnimation(movePercent, view, i)
|
||||
}
|
||||
|
||||
//尝试更新当前item的位置并通知外界
|
||||
updatePositionRecordAndNotify(firstVisiblePosition)
|
||||
|
||||
//重用
|
||||
if (firstVisiblePosition - 1 >= 0) {
|
||||
val view = recycler.getViewForPosition(firstVisiblePosition - 1)
|
||||
resetViewAnimateProperty(view)
|
||||
removeAndRecycleView(view, recycler)
|
||||
}
|
||||
if (lastVisiblePosition + 1 < itemCount) {
|
||||
val view = recycler.getViewForPosition(lastVisiblePosition + 1)
|
||||
resetViewAnimateProperty(view)
|
||||
removeAndRecycleView(view, recycler)
|
||||
}
|
||||
val lastPosition = firstVisiblePosition - 1
|
||||
val lastView =
|
||||
recycler.getViewForPosition(if (lastPosition >= 0 || lastPosition % itemCount == 0) lastPosition % itemCount else lastPosition % itemCount + itemCount)
|
||||
resetViewAnimateProperty(lastView)
|
||||
removeAndRecycleView(lastView, recycler)
|
||||
|
||||
val nextPosition = lastVisiblePosition + 1
|
||||
val nextView =
|
||||
recycler.getViewForPosition(if (nextPosition >= 0 || nextPosition % itemCount == 0) nextPosition % itemCount else nextPosition % itemCount + itemCount)
|
||||
resetViewAnimateProperty(nextView)
|
||||
removeAndRecycleView(nextView, recycler)
|
||||
}
|
||||
|
||||
private fun resetViewAnimateProperty(view: View) {
|
||||
@ -405,9 +423,13 @@ class StackLayoutManager(scrollOrientation: ScrollOrientation,
|
||||
scrollToCenter(targetPosition, view, true)
|
||||
}
|
||||
|
||||
private fun scrollToCenter(targetPosition: Int, recyclerView: RecyclerView, animation: Boolean) {
|
||||
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)
|
||||
@ -426,14 +448,15 @@ class StackLayoutManager(scrollOrientation: ScrollOrientation,
|
||||
}
|
||||
|
||||
private fun getValidOffset(expectOffset: Int): Int {
|
||||
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)
|
||||
return when (mScrollOrientation) {
|
||||
ScrollOrientation.RIGHT_TO_LEFT, ScrollOrientation.LEFT_TO_RIGHT ->
|
||||
(width * (itemCount - 1)).coerceAtMost(expectOffset).coerceAtLeast(0)
|
||||
else -> (height * (itemCount - 1)).coerceAtMost(expectOffset).coerceAtLeast(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
|
||||
@ -441,15 +464,6 @@ class StackLayoutManager(scrollOrientation: ScrollOrientation,
|
||||
}
|
||||
}
|
||||
|
||||
private fun getLastVisibleItemPosition(): Int {
|
||||
val firstVisiblePosition = getFirstVisibleItemPosition()
|
||||
return if (firstVisiblePosition + mVisibleItemCount > itemCount - 1) {
|
||||
itemCount - 1
|
||||
} else {
|
||||
firstVisiblePosition + mVisibleItemCount
|
||||
}
|
||||
}
|
||||
|
||||
private fun getFirstVisibleItemMovePercent(): Float {
|
||||
if (width == 0 || height == 0) {
|
||||
return 0f
|
||||
@ -480,7 +494,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
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.2.60'
|
||||
ext.kotlin_version = '1.6.10'
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.1.4'
|
||||
classpath 'com.android.tools.build:gradle:4.2.2'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
classpath 'com.novoda:bintray-release:0.8.1'
|
||||
}
|
||||
@ -29,4 +29,4 @@ allprojects {
|
||||
task clean(type: Delete) {
|
||||
delete rootProject.buildDir
|
||||
}
|
||||
tasks.getByPath(":StackLayoutManager:releaseAndroidJavadocs").enabled = false
|
||||
//tasks.getByPath(":StackLayoutManager:releaseAndroidJavadocs").enabled = false
|
||||
|
||||
@ -6,6 +6,8 @@
|
||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
android.enableJetifier=true
|
||||
android.useAndroidX=true
|
||||
org.gradle.jvmargs=-Xmx1536m
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. More details, visit
|
||||
|
||||
6
gradle/wrapper/gradle-wrapper.properties
vendored
6
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,6 +1,6 @@
|
||||
#Thu Jun 28 17:28:50 CST 2018
|
||||
#Thu Feb 17 14:43:36 CST 2022
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
@ -5,14 +5,14 @@ apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
|
||||
android {
|
||||
compileSdkVersion 27
|
||||
compileSdkVersion 31
|
||||
defaultConfig {
|
||||
applicationId "com.littlemango.stacklayoutmanagermaster"
|
||||
minSdkVersion 19
|
||||
targetSdkVersion 27
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 31
|
||||
versionCode 6
|
||||
versionName "1.0.5"
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
@ -22,19 +22,19 @@ android {
|
||||
}
|
||||
}
|
||||
|
||||
ext.kotlin_version = '1.2.60'
|
||||
ext.kotlin_version = '1.6.10'
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
implementation 'com.android.support:appcompat-v7:27.1.1'
|
||||
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
|
||||
testImplementation 'junit:junit:4.12'
|
||||
androidTestImplementation 'com.android.support.test:runner:1.0.2'
|
||||
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
|
||||
implementation 'com.android.support:recyclerview-v7:27.1.1'
|
||||
implementation 'com.android.support:cardview-v7:27.1.1'
|
||||
implementation 'androidx.appcompat:appcompat:1.4.1'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
||||
implementation 'androidx.recyclerview:recyclerview:1.2.1'
|
||||
implementation 'androidx.cardview:cardview:1.0.0'
|
||||
implementation project(':StackLayoutManager')
|
||||
implementation 'com.afollestad.material-dialogs:core:0.9.6.0'
|
||||
implementation 'com.android.support:design:27.1.1'
|
||||
implementation 'com.google.android.material:material:1.5.0'
|
||||
}
|
||||
|
||||
@ -1,13 +1,11 @@
|
||||
package com.littlemango.stacklayoutmanagermaster
|
||||
|
||||
import android.support.test.InstrumentationRegistry
|
||||
import android.support.test.runner.AndroidJUnit4
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
import org.junit.Assert.*
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
@ -18,7 +16,7 @@ class ExampleInstrumentedTest {
|
||||
@Test
|
||||
fun useAppContext() {
|
||||
// Context of the app under test.
|
||||
val appContext = InstrumentationRegistry.getTargetContext()
|
||||
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
||||
assertEquals("com.littlemango.stacklayoutmanagermaster", appContext.packageName)
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,7 +9,8 @@
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme">
|
||||
<activity android:name=".MainActivity">
|
||||
<activity android:name=".MainActivity"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
package com.littlemango.stacklayoutmanagermaster;
|
||||
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.view.View;
|
||||
|
||||
import com.littlemango.stacklayoutmanager.StackAnimation;
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
package com.littlemango.stacklayoutmanagermaster;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.util.Log;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
@ -15,7 +15,7 @@ import android.widget.Toast;
|
||||
|
||||
import com.afollestad.materialdialogs.MaterialDialog;
|
||||
import com.littlemango.stacklayoutmanager.StackLayoutManager;
|
||||
import com.littlemango.stacklayoutmanager.StackLayoutManager.ScrollOrientation;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
@ -66,22 +66,22 @@ public class MainActivity extends AppCompatActivity {
|
||||
resetRandom();
|
||||
break;
|
||||
case 2:
|
||||
mStackLayoutManager = new StackLayoutManager(ScrollOrientation.LEFT_TO_RIGHT);
|
||||
mStackLayoutManager = new StackLayoutManager(StackLayoutManager.ScrollOrientation.LEFT_TO_RIGHT);
|
||||
mRecyclerView.setLayoutManager(mStackLayoutManager);
|
||||
getSupportActionBar().setTitle("Picture 0");
|
||||
break;
|
||||
case 3:
|
||||
mStackLayoutManager = new StackLayoutManager(ScrollOrientation.RIGHT_TO_LEFT);
|
||||
mStackLayoutManager = new StackLayoutManager(StackLayoutManager.ScrollOrientation.RIGHT_TO_LEFT);
|
||||
mRecyclerView.setLayoutManager(mStackLayoutManager);
|
||||
getSupportActionBar().setTitle("Picture 0");
|
||||
break;
|
||||
case 4:
|
||||
mStackLayoutManager = new StackLayoutManager(ScrollOrientation.TOP_TO_BOTTOM);
|
||||
mStackLayoutManager = new StackLayoutManager(StackLayoutManager.ScrollOrientation.TOP_TO_BOTTOM);
|
||||
mRecyclerView.setLayoutManager(mStackLayoutManager);
|
||||
getSupportActionBar().setTitle("Picture 0");
|
||||
break;
|
||||
case 5:
|
||||
mStackLayoutManager = new StackLayoutManager(ScrollOrientation.BOTTOM_TO_TOP);
|
||||
mStackLayoutManager = new StackLayoutManager(StackLayoutManager.ScrollOrientation.BOTTOM_TO_TOP);
|
||||
mRecyclerView.setLayoutManager(mStackLayoutManager);
|
||||
getSupportActionBar().setTitle("Picture 0");
|
||||
break;
|
||||
|
||||
@ -1,17 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".MainActivity">
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycleView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
|
||||
<android.support.design.widget.FloatingActionButton
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/floatButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
@ -22,4 +22,4 @@
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="270dp"
|
||||
android:layout_height="400dp"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
@ -17,4 +17,4 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:textSize="50sp"/>
|
||||
</android.support.v7.widget.CardView>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
Reference in New Issue
Block a user