Skip to content

Commit

Permalink
Merge pull request #70 from ltttttttttttt/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
ltttttttttttt authored Oct 10, 2023
2 parents ab2c1df + 42f5b64 commit 94da35f
Show file tree
Hide file tree
Showing 10 changed files with 123 additions and 40 deletions.
2 changes: 1 addition & 1 deletion ComposeViews/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ plugins {
group = "io.github.ltttttttttttt"
//上传到mavenCentral命令: ./gradlew publishAllPublicationsToSonatypeRepository
//mavenCentral后台: https://s01.oss.sonatype.org/#stagingRepositories
version = "$composeVersion.3"
version = "$composeVersion.4"

kotlin {
androidTarget {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.Dp
import com.lt.compose_views.chain_scrollable_component.mode.ChainAfterContentNestedScrollConnection
import com.lt.compose_views.chain_scrollable_component.mode.ChainContentFirstNestedScrollConnection
import com.lt.compose_views.chain_scrollable_component.mode.ChainMode
import com.lt.compose_views.chain_scrollable_component.mode.ContentFirstNestedScrollConnection
import com.lt.compose_views.util.ComposePosition

/**
Expand All @@ -42,8 +46,8 @@ import com.lt.compose_views.util.ComposePosition
* @param chainContent 链式(联动)滚动的compose组件,scrollOffset: 滚动位置(位于最小和最大之间)
* Content of chain
* @param modifier 修饰
* @param onScrollStop 停止滚动时回调
* Callback of scroll stop event
* @param onScrollStop 停止滚动时回调,返回true会拦截后续fling操作
* Callback of scroll stop event, return true will intercept subsequent flying operations
* @param composePosition 设置bar布局所在的位置,并且间接指定了滑动方向
* Set the position of the top bar layout
* @param chainMode 联动方式
Expand All @@ -58,7 +62,7 @@ fun ChainScrollableComponent(
maxScrollPosition: Dp,
chainContent: @Composable (state: ChainScrollableComponentState) -> Unit,
modifier: Modifier = Modifier,
onScrollStop: ((state: ChainScrollableComponentState) -> Unit)? = null,
onScrollStop: ((state: ChainScrollableComponentState, delta: Float) -> Boolean)? = null,
composePosition: ComposePosition = ComposePosition.Top,
chainMode: ChainMode = ChainMode.ChainContentFirst,
content: @Composable BoxScope.(state: ChainScrollableComponentState) -> Unit,
Expand Down Expand Up @@ -99,6 +103,7 @@ fun ChainScrollableComponent(
when (chainMode) {
ChainMode.ContentFirst -> ContentFirstNestedScrollConnection(state)
ChainMode.ChainContentFirst -> ChainContentFirstNestedScrollConnection(state)
ChainMode.ChainAfterContent -> ChainAfterContentNestedScrollConnection(state)
}
}
Box(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class ChainScrollableComponentState internal constructor(
val maxPx: Float,
val composePosition: ComposePosition,
val coroutineScope: CoroutineScope,
private val onScrollStop: ((state: ChainScrollableComponentState) -> Unit)?,
private val onScrollStop: ((state: ChainScrollableComponentState, delta: Float) -> Boolean)?,
) {
val orientationIsHorizontal = composePosition.isHorizontal()

Expand Down Expand Up @@ -84,7 +84,7 @@ class ChainScrollableComponentState internal constructor(
}

//调用[onScrollStop],触发停止滚动时的回调
internal fun callOnScrollStop() {
onScrollStop?.invoke(this)
internal fun callOnScrollStop(delta: Float): Boolean {
return onScrollStop?.invoke(this, delta) == true
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Copyright lt 2023
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.lt.compose_views.chain_scrollable_component.mode

import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
import androidx.compose.ui.input.nestedscroll.NestedScrollSource
import androidx.compose.ui.unit.Velocity
import com.lt.compose_views.chain_scrollable_component.ChainScrollableComponentState
import com.lt.compose_views.util.midOf

/**
* creator: lt 2022/9/29 [email protected]
* effect : 对应[ChainMode.ChainAfterContent]的[NestedScrollConnection]
* warning:
*/
internal class ChainAfterContentNestedScrollConnection(
val state: ChainScrollableComponentState,
) : NestedScrollConnection {

override fun onPostScroll(
consumed: Offset,
available: Offset,
source: NestedScrollSource
): Offset {
val delta = if (state.orientationIsHorizontal) available.x else available.y
val newOffset = state.getScrollPositionValue() + delta
state.setScrollPosition(midOf(state.minPx, newOffset, state.maxPx))
return Offset.Zero
}

override suspend fun onPostFling(consumed: Velocity, available: Velocity): Velocity {
val delta = if (state.orientationIsHorizontal) available.x else available.y
if (state.callOnScrollStop(delta)) return super.onPostFling(consumed, available)
val newOffset = state.getScrollPositionValue() + delta
state.animateToScrollPosition(midOf(state.minPx, newOffset, state.maxPx))
return super.onPostFling(consumed, available)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@
* limitations under the License.
*/

package com.lt.compose_views.chain_scrollable_component
package com.lt.compose_views.chain_scrollable_component.mode

import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
import androidx.compose.ui.input.nestedscroll.NestedScrollSource
import androidx.compose.ui.unit.Velocity
import com.lt.compose_views.chain_scrollable_component.ChainScrollableComponentState
import com.lt.compose_views.util.midOf

/**
Expand All @@ -43,7 +44,8 @@ internal class ChainContentFirstNestedScrollConnection(
}

override suspend fun onPostFling(consumed: Velocity, available: Velocity): Velocity {
state.callOnScrollStop()
val delta = if (state.orientationIsHorizontal) available.x else available.y
state.callOnScrollStop(delta)
return super.onPostFling(consumed, available)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@
* limitations under the License.
*/

package com.lt.compose_views.chain_scrollable_component

import androidx.compose.foundation.ExperimentalFoundationApi
package com.lt.compose_views.chain_scrollable_component.mode

/**
* creator: lt 2022/9/29 [email protected]
Expand All @@ -29,12 +27,17 @@ enum class ChainMode {
* 内容区域优先
* Content first
*/
@ExperimentalFoundationApi//todo 暂时有问题,先不放开
ContentFirst,

/**
* 联动区域优先
* Chain content first
*/
ChainContentFirst,

/**
* 内容区域无法滑动后联动区域再滑动
* Chain after content
*/
ChainAfterContent,
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@
* limitations under the License.
*/

package com.lt.compose_views.chain_scrollable_component
package com.lt.compose_views.chain_scrollable_component.mode

import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
import androidx.compose.ui.input.nestedscroll.NestedScrollSource
import androidx.compose.ui.unit.Velocity
import com.lt.compose_views.chain_scrollable_component.ChainScrollableComponentState
import com.lt.compose_views.util.ComposePosition
import com.lt.compose_views.util.midOf

Expand Down Expand Up @@ -63,11 +64,11 @@ internal class ContentFirstNestedScrollConnection(

override suspend fun onPostFling(consumed: Velocity, available: Velocity): Velocity {
val delta = if (state.orientationIsHorizontal) available.x else available.y
if (state.callOnScrollStop(delta)) return super.onPostFling(consumed, available)
val newOffset = state.getScrollPositionValue() + delta
if (delta < 0f) {
state.animateToScrollPosition(midOf(state.minPx, newOffset, state.maxPx))
}
state.callOnScrollStop()
return super.onPostFling(consumed, available)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.lt.compose_views.chain_scrollable_component.ChainMode
import com.lt.compose_views.chain_scrollable_component.ChainScrollableComponent
import com.lt.compose_views.chain_scrollable_component.ChainScrollableComponentState
import com.lt.compose_views.chain_scrollable_component.mode.ChainMode
import com.lt.compose_views.util.ComposePosition
import kotlin.math.roundToInt

Expand All @@ -64,14 +64,14 @@ import kotlin.math.roundToInt
* @param background 背景图片
* Background of top bar
* @param modifier 修饰
* @param onScrollStop 停止滚动时回调
* Callback of scroll stop event
* @param navigationIcon 顶部导航栏图标,默认为返回键
* Icon of top bar
* @param minScrollPosition 最小滚动位置(距离指定方向的顶点)
* Minimum scroll position
* @param maxScrollPosition 最大滚动位置(距离指定方向的顶点)
* Maximum scroll position
* @param navigationIcon 顶部导航栏图标,默认为返回键
* Icon of top bar
* @param onScrollStop 停止滚动时回调,返回true会拦截后续fling操作
* Callback of scroll stop event, return true will intercept subsequent flying operations
* @param composePosition 设置bar布局所在的位置,并且间接指定了滑动方向
* Set the position of the top bar layout
* @param chainMode 联动方式
Expand All @@ -97,7 +97,7 @@ fun ScrollableAppBar(
},
minScrollPosition: Dp = 56.dp,
maxScrollPosition: Dp = 200.dp,
onScrollStop: ((state: ChainScrollableComponentState) -> Unit)? = null,
onScrollStop: ((state: ChainScrollableComponentState, delta: Float) -> Boolean)? = null,
composePosition: ComposePosition = ComposePosition.Top,
chainMode: ChainMode = ChainMode.ChainContentFirst,
content: @Composable BoxScope.(state: ChainScrollableComponentState) -> Unit,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,24 @@ import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.ScrollState
import androidx.compose.foundation.gestures.animateScrollBy
import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.IntrinsicSize
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.IntOffset
import com.lt.compose_views.chain_scrollable_component.ChainScrollableComponent
import com.lt.compose_views.chain_scrollable_component.ChainScrollableComponentState
import com.lt.compose_views.chain_scrollable_component.mode.ChainMode
import com.lt.compose_views.util.ComposePosition
import kotlinx.coroutines.launch
import kotlin.math.abs
import kotlin.math.roundToInt

/**
Expand Down Expand Up @@ -81,6 +89,7 @@ fun SwipeToDismiss(
modifier = modifier.height(IntrinsicSize.Min),
onScrollStop = scrollStop(scrollState),
composePosition = ComposePosition.End,
chainMode = ChainMode.ChainAfterContent,
content = { state ->
Row(
modifier = Modifier
Expand All @@ -105,13 +114,14 @@ fun SwipeToDismiss(
}

//停止拖动时,使appbar归位
private fun scrollStop(scrollState: ScrollState): (ChainScrollableComponentState) -> Unit =
function@{ state ->
private fun scrollStop(scrollState: ScrollState): (ChainScrollableComponentState, Float) -> Boolean =
function@{ state, delta ->
val percentage = state.getScrollPositionPercentage()
if (percentage == 1f || percentage == 0f)
return@function
return@function true
state.coroutineScope.launch {
val startPositionValue = state.getScrollPositionValue()
val startPositionValue =
abs((state.getScrollPositionValue() + delta) / (state.maxPx - state.minPx))
if (percentage > 0.5f) {
state.setScrollPositionWithAnimate(state.maxPx)
scrollState.animateScrollBy(startPositionValue - state.minPx)
Expand All @@ -120,4 +130,5 @@ private fun scrollStop(scrollState: ScrollState): (ChainScrollableComponentState
scrollState.animateScrollBy(startPositionValue)
}
}
true
}
Loading

0 comments on commit 94da35f

Please sign in to comment.