Skip to content

Commit

Permalink
Drag to refresh (#7)
Browse files Browse the repository at this point in the history
* Feat: DragRefresh

* Feat: Improved demo

* Add demo gifs

* Update README.md

* Bump version
  • Loading branch information
wingio authored Dec 14, 2023
1 parent 3ee9fb7 commit 758486f
Show file tree
Hide file tree
Showing 16 changed files with 452 additions and 64 deletions.
Binary file added .github/images/dragrefresh-flipped.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added .github/images/dragrefresh.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added .github/images/pullrefresh-flipped.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added .github/images/pullrefresh.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
45 changes: 44 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,14 @@ materii-pullrefresh = { group = "dev.materii.pullrefresh", name = "pullrefresh",
```

### Basic setup
> See the [demo project](https://github.com/MateriiApps/pullrefresh/blob/main/demo/src/main/java/dev/materii/pullrefresh/demo/MainActivity.kt).

#### Pull to refresh
> See the [sample](https://github.com/MateriiApps/pullrefresh/blob/main/demo/src/main/java/dev/materii/pullrefresh/demo/sample/PullRefreshSample.kt).
| Default | Flipped |
| ------- | ------- |
| <img src="/.github/images/pullrefresh.gif" alt="Pull refresh demo" width="200px"> | <img src="/.github/images/pullrefresh-flipped.gif" alt="Flipped pull refresh demo" width="200px"> |

```kt
@Composable
fun Test() {
Expand Down Expand Up @@ -53,6 +60,42 @@ fun Test() {
}
```

#### Drag to refresh
> See the [sample](https://github.com/MateriiApps/pullrefresh/blob/main/demo/src/main/java/dev/materii/pullrefresh/demo/sample/DragRefreshSample.kt).

| Default | Flipped |
| ------- | ------- |
| <img src="/.github/images/dragrefresh.gif" alt="Drag refresh demo" width="200px"> | <img src="/.github/images/dragrefresh-flipped.gif" alt="Flipped drag refresh demo" width="200px"> |

```kt
@Composable
fun Test() {
var isRefreshing by remember {
mutableStateOf(false)
}
var pullRefreshState = rememberPullRefreshState(refreshing = isRefreshing, onRefresh = { /* Refresh some data here */ })

Scaffold(
modifier = Modifier.pullRefresh(pullRefreshState)
) {
DragRefreshLayout(
state = pullRefreshState
modifier = modifier
.padding(it)
.fillMaxSize()
) {
Box(
contentAlignment = Alignment.Center,
modifier = Modifier
.fillMaxSize()
.verticalScroll(rememberScrollState())
) {
Text("Some content")
}
}
}
```

## Notice
All of the included components come directly from the official Jetpack Compose Material library, with only the bare minimum required.

Expand Down
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ plugins {

allprojects {
group = "dev.materii.pullrefresh"
version = "1.1.0"
version = "1.2.0"

repositories {
repositories {
Expand Down
1 change: 1 addition & 0 deletions demo/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ dependencies {
implementation(libs.lifecycle.runtime.ktx)
implementation(libs.activity.compose)
implementation(libs.material3)
implementation(libs.material.icons.extended)

implementation(project(":pullrefresh"))
}
124 changes: 90 additions & 34 deletions demo/src/main/java/dev/materii/pullrefresh/demo/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,22 @@ package dev.materii.pullrefresh.demo
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Flip
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButtonDefaults
import androidx.compose.material3.IconToggleButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.PrimaryTabRow
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Tab
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
Expand All @@ -20,69 +28,117 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.core.view.WindowCompat
import dev.materii.pullrefresh.PullRefreshIndicator
import dev.materii.pullrefresh.demo.sample.DragRefreshSample
import dev.materii.pullrefresh.demo.sample.PullRefreshSample
import dev.materii.pullrefresh.demo.theme.SwipeRefreshTheme
import dev.materii.pullrefresh.demo.theme.applyTonalElevation
import dev.materii.pullrefresh.rememberPullRefreshState
import dev.materii.pullrefresh.pullRefresh
import dev.materii.pullrefresh.rememberPullRefreshState
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

class MainActivity : ComponentActivity() {
@OptIn(ExperimentalMaterial3Api::class)
@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
WindowCompat.setDecorFitsSystemWindows(window, false)

setContent {
var flipped by remember { mutableStateOf(false) }
val pagerState = rememberPagerState { 2 }
val scope = rememberCoroutineScope()
var isRefreshing by remember {
mutableStateOf(false)
}
val pullRefreshState = rememberPullRefreshState(refreshing = isRefreshing, onRefresh = {
scope.launch {
isRefreshing = true
delay(3_000)
isRefreshing = false
val pullRefreshState = rememberPullRefreshState(
refreshing = isRefreshing,
onRefresh = {
scope.launch {
isRefreshing = true
delay(3_000)
isRefreshing = false
}
}
})
)

SwipeRefreshTheme {
Scaffold(
topBar = {
TopAppBar(
title = { Text(stringResource(R.string.app_name)) },
colors = TopAppBarDefaults.topAppBarColors(
containerColor = MaterialTheme.colorScheme.applyTonalElevation(
backgroundColor = MaterialTheme.colorScheme.surface,
elevation = 3.dp
)
)
containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation(3.dp)
),
actions = {
IconToggleButton(
checked = flipped,
onCheckedChange = { checked -> flipped = checked },
colors = IconButtonDefaults.iconToggleButtonColors(
checkedContainerColor = MaterialTheme.colorScheme.primaryContainer.copy(
alpha = 0.5f
)
)
) {
Icon(
imageVector = Icons.Filled.Flip,
contentDescription = "Flip"
)
}
}
)
},
modifier = Modifier.pullRefresh(pullRefreshState)
modifier = Modifier
.pullRefresh(pullRefreshState, inverse = flipped)
) {
Box(
contentAlignment = Alignment.Center,
modifier = Modifier
.padding(it)
.fillMaxSize()
.verticalScroll(rememberScrollState())
Column(
modifier = Modifier.padding(it)
) {
Text(text = "Pull down to refresh")
PrimaryTabRow(
selectedTabIndex = pagerState.currentPage,
containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation(3.dp),
divider = {}
) {
Tab(
text = { Text("Pull to refresh") },
selected = pagerState.currentPage == 0,
onClick = {
scope.launch {
pagerState.animateScrollToPage(0)
}
}
)

PullRefreshIndicator(
refreshing = isRefreshing,
state = pullRefreshState,
backgroundColor = MaterialTheme.colorScheme.surfaceColorAtElevation(3.dp),
contentColor = MaterialTheme.colorScheme.primary,
modifier = Modifier.align(Alignment.TopCenter)
)
Tab(
text = { Text("Drag to refresh") },
selected = pagerState.currentPage == 1,
onClick = {
scope.launch {
pagerState.animateScrollToPage(1)
}
}
)
}

HorizontalPager(
state = pagerState,
modifier = Modifier.fillMaxSize()
) { page ->
when (page) {
0 -> PullRefreshSample(
flipped = flipped,
pullRefreshState = pullRefreshState,
isRefreshing = isRefreshing
)

1 -> DragRefreshSample(
flipped = flipped,
pullRefreshState = pullRefreshState
)
}
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package dev.materii.pullrefresh.demo.sample

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import dev.materii.pullrefresh.DragRefreshLayout
import dev.materii.pullrefresh.PullRefreshState

@Composable
fun DragRefreshSample(
flipped: Boolean,
pullRefreshState: PullRefreshState,
modifier: Modifier = Modifier
) {
DragRefreshLayout(
state = pullRefreshState,
flipped = flipped,
modifier = modifier
.fillMaxSize()
) {
Box(
contentAlignment = Alignment.Center,
modifier = modifier
.fillMaxSize()
.verticalScroll(rememberScrollState())
) {
Text(text = "Pull ${if (flipped) "up" else "down"} to refresh")
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package dev.materii.pullrefresh.demo.sample

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.surfaceColorAtElevation
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import dev.materii.pullrefresh.PullRefreshIndicator
import dev.materii.pullrefresh.PullRefreshState

@Composable
fun PullRefreshSample(
flipped: Boolean,
pullRefreshState: PullRefreshState,
isRefreshing: Boolean,
modifier: Modifier = Modifier
) {
Box(
contentAlignment = Alignment.Center,
modifier = modifier
.fillMaxSize()
.verticalScroll(rememberScrollState())
) {
Text(text = "Pull ${if (flipped) "up" else "down"} to refresh")

PullRefreshIndicator(
refreshing = isRefreshing,
state = pullRefreshState,
flipped = flipped,
backgroundColor = MaterialTheme.colorScheme.surfaceColorAtElevation(3.dp),
contentColor = MaterialTheme.colorScheme.primary,
modifier = Modifier
.align(
if (flipped) Alignment.BottomCenter else Alignment.TopCenter
)
)
}
}
14 changes: 0 additions & 14 deletions demo/src/main/java/dev/materii/pullrefresh/demo/theme/Color.kt

This file was deleted.

1 change: 1 addition & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "core-ktx
lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version = "2.6.2" }
activity-compose = { group = "androidx.activity", name = "activity-compose", version = "1.8.0" }
material3 = { group = "androidx.compose.material3", name = "material3", version = "1.2.0-alpha09" }
material-icons-extended = { group = "androidx.compose.material", name = "material-icons-extended", version = "1.5.4" }

[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package dev.materii.pullrefresh

import androidx.compose.foundation.shape.CircleShape
import androidx.compose.ui.unit.dp

internal const val CrossfadeDurationMs = 100
internal const val MaxProgressArc = 0.8f

internal val IndicatorSize = 40.dp
internal val SpinnerShape = CircleShape
internal val ArcRadius = 7.5.dp
internal val StrokeWidth = 2.5.dp
internal val ArrowWidth = 10.dp
internal val ArrowHeight = 5.dp
internal val Elevation = 6.dp
Loading

0 comments on commit 758486f

Please sign in to comment.