Giter Site home page Giter Site logo

kevinnzou / compose-paginglist Goto Github PK

View Code? Open in Web Editor NEW
17.0 3.0 5.0 2.94 MB

A library that provides several functionalities to make it easy to write a list with Jetpack Paging3

License: Apache License 2.0

Kotlin 100.00%
android jetpack-compose jetpack-paging3 lazycolumn loading-screen lazyverticalgrid

compose-paginglist's Introduction

Compose Paging List for Jetpack Compose

A library that provides several functionalities to make it easy to write a list with paging data

  1. It defines methods to config Google's Jetpack Paging Library easily.
  2. It provides default layouts for different paging loading status.
  3. It provides some composable layouts that can be used to form a paging list easily.

Usage

To start using this library, apps need to define pager data and provide it to the list

Pager Data

Apps can define the pager data for list in the ViewModel in several ways

  1. The simplest way is to use the easyPager. It requires the apps wrap the data in PagingListWrapper which need the data list and the hasMore sign.
@HiltViewModel
class MainViewModel @Inject constructor() : ViewModel() {
    val pager = easyPager {
        loadData(it)
    }

    private suspend fun loadData(page: Int): PagingListWrapper<String> {
        delay(2000)
        val data = mutableListOf("Page $page")
        repeat(20) {
            data.add("Item $it")
        }
        return PagingListWrapper(data, page < 3)
    }
}
  1. However, the first method is only suitable for the simple data model. If you have a complex model, then you can use the easyPager2
val pager2 = easyPager2(initialKey = 0){
    return@easyPager2 loadData2(it)
}

private suspend fun loadData2(page: Int): PageListVO {
    delay(1500)
    val data = mutableListOf("Page $page")
    repeat(20) {
        data.add("Item $it")
    }
    return PageListVO(page, data, page < 2)
}

It requires the data model to implement the interface IHasMoreListVO to provide the list data, hasMore sign, preKey and the nextKey.

data class PageListVO(var page: Int, var items: MutableList<String>, var hasMore: Boolean) : IHasMoreListVO<Int,String> {
    override fun hasMore(): Boolean {
        return hasMore
    }

    override fun getList(): List<String> {
        return items
    }

    override fun getPreKey(): Int? {
        return if (page - 1 < 0) null else page - 1
    }

    override fun getNextKey(): Int? {
        return page + 1
    }
}
  1. Lastly, the library provides the pager which allows the apps to map their own defined Http Result to Kotlin Standard Result. Then it will map it to PagingSource.LoadResult automatically.
pager(pagerConfig, initialKey) { key ->
    when (val result = loadData(key)) {
        is HttpResult.Error.BusinessError -> {
            return@pager Result.failure(Exception("${result.code} - ${result.message}"))
        }
        is HttpResult.Error.NetworkError -> {
            return@pager Result.failure(result.error)
        }
        is HttpResult.Success -> {
            return@pager Result.success(result.response)
        }
        else -> {
            return@pager Result.failure(Exception("Other Exception"))
        }
    }
}

List

This library provides several ways to write a paging list

  1. The easiest way is to use PagingLazyColumn directly
@Composable
fun EasyPagingListScreen(viewModel: MainViewModel = hiltViewModel()) {
    val pagerData = viewModel.pager.collectAsLazyPagingItems()
    PagingLazyColumn(pagingData = pagerData) { _, value ->
        Text(value)
    }
}
  1. However, the method above restricts the things that apps must use a lazyColumn and cannot add header. Thus, we can use the method below to compose the list you want which also has the same funtionality
@Composable
fun RawPagingListScreen(viewModel: MainViewModel = hiltViewModel()) {
    val pagerData = viewModel.pager.collectAsLazyPagingItems()
    // show first loading status
    PagingListContainer(pagingData = pagerData) {
        LazyRow {
            item {
                Text(
                    text = "Raw PagingList",
                    modifier = Modifier
                        .height(40.dp)
                        .fillParentMaxWidth()
                        .padding(top = 15.dp),
                    textAlign = TextAlign.Center
                )
            }
            itemsIndexed(pagerData) { _, value ->
                PagingContent(value)
            }
            // show load more status
            itemPaging(pagerData)
        }
    }
}
  1. The second method Wrap the LazyRow with PagingListContainer which provides the first loading status, if you want to control it by yourself, you can directly use the LazyList with itemPaging
@Composable
fun RawPagingListScreen(viewModel: MainViewModel = hiltViewModel()) {
    val pagerData = viewModel.pager.collectAsLazyPagingItems()
    // show first loading status
    LazyRow {
        item {
            Text(
                text = "Raw PagingList",
                modifier = Modifier
                    .height(40.dp)
                    .fillParentMaxWidth()
                    .padding(top = 15.dp),
                textAlign = TextAlign.Center
            )
        }
        itemsIndexed(pagerData) { _, value ->
            PagingContent(value)
        }
        // show load more status
        itemPaging(pagerData)
    }
}

GridList

This library also add support for the GridList, you can use it like this:

@Composable
fun PagingGridScreen(viewModel: MainViewModel = hiltViewModel()) {
    val pagerData = viewModel.pager.collectAsLazyPagingItems()
    PagingListContainer(pagingData = pagerData) {
        LazyVerticalGrid(
            columns = GridCells.Fixed(2),
            verticalArrangement = Arrangement.spacedBy(10.dp),
            horizontalArrangement = Arrangement.spacedBy(10.dp),
            contentPadding = PaddingValues(10.dp)
        ) {
            itemsIndexed(pagerData) { index, value ->
                Box(
                    Modifier
                        .background(if (index.rem(2) == 0) Color.Yellow else Color.Magenta)
                        .height(128.dp),
                    contentAlignment = Alignment.Center
                ) {
                    Text(text = value.toString())
                }
            }
            if (pagerData.itemCount.rem(2) != 0) {
                item { Spacer(Modifier.background(Color.White)) }
            }
            itemPaging(pagerData, 2)
        }
    }
}

Customization

Apps can customize the loading, no more, error content and so on.

@Composable
fun <T : Any> PagingLazyColumn(
    modifier: Modifier = Modifier,
    pagingData: LazyPagingItems<T>,
    loadingContent: @Composable (() -> Unit)? = { DefaultLoadingContent() },
    noMoreContent: @Composable (() -> Unit)? = { DefaultNoMoreContent() },
    errorContent: @Composable ((retry: (() -> Unit)?) -> Unit)? = { retry ->
        DefaultErrorContent(
            retry
        )
    },
    refreshingContent: @Composable (() -> Unit)? = { DefaultRefreshingContent() },
    firstLoadErrorContent: @Composable ((retry: (() -> Unit)?) -> Unit)? = { retry ->
        DefaultFirstLoadErrorContent(
            retry
        )
    },
    emptyListContent: @Composable (() -> Unit)? = { DefaultEmptyListContent() },
    pagingItemContent: @Composable (index: Int, value: T?) -> Unit,
)
@Composable
fun CustomLoadMoreScreen(viewModel: MainViewModel = hiltViewModel()) {
    val pagerData = viewModel.pager.collectAsLazyPagingItems()
    PagingLazyColumn(
        pagingData = pagerData,
        loadingContent = { CustomLoadMoreContent() },
        refreshingContent = { CustomRefreshingContent() }) { _, value ->
        PagingContent(value)
    }
}

@Composable
fun CustomLoadMoreContent() {
    Row(
        modifier = Modifier
            .fillMaxWidth()
            .height(40.dp),
        horizontalArrangement = Arrangement.Center,
        verticalAlignment = Alignment.CenterVertically
    ) {
        LinearProgressIndicator(
            color = Color.Red,
            modifier = Modifier
                .width(100.dp)
                .height(2.dp),
        )
    }
}

@Composable
fun CustomRefreshingContent() {
    Column(
        modifier = Modifier.fillMaxSize(),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        CustomLoadMoreContent()
    }
}

Download

The Current Release Version is 1.1.0. For future release, please refer to the release session of the github repository.

repositories {
    mavenCentral()
}

dependencies {
    implementation("io.github.kevinnzou:compose-paginglist:<version>")
}

License

Compose PagingList is distributed under the terms of the Apache License (Version 2.0). See the license for more information.

compose-paginglist's People

Contributors

kevinnzou avatar mcxinyu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

compose-paginglist's Issues

请教调用网络接口的时候怎么传参呢?

image

如图

这里是调用 val areaDevices = viewModel.areaDevices.collectAsLazyPagingItems(),怎么动态传参给 getAreaDevices 函数呢?

我现在是通过在函数外面维护一个变量实现,但是这样就不是函数编程了。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.