All Projects → Ahmad-Hamwi → TabSync

Ahmad-Hamwi / TabSync

Licence: Apache-2.0 license
A lightweight synchronizer between Android's Tabs and Lists. Available on the View system and Jetpack Compose.

Programming Languages

kotlin
9241 projects

Projects that are alternatives of or similar to TabSync

Ffsubsync
Automagically synchronize subtitles with video.
Stars: ✭ 5,167 (+5172.45%)
Mutual labels:  sync, synchronization
Syncthing Macos
Frugal and native macOS Syncthing application bundle
Stars: ✭ 1,096 (+1018.37%)
Mutual labels:  sync, synchronization
Monstache
a go daemon that syncs MongoDB to Elasticsearch in realtime
Stars: ✭ 736 (+651.02%)
Mutual labels:  sync, synchronization
S4
🔄 Fast and cheap synchronisation of files using Amazon S3
Stars: ✭ 69 (-29.59%)
Mutual labels:  sync, synchronization
Rats
Movie Ratings Synchronization with Python
Stars: ✭ 156 (+59.18%)
Mutual labels:  sync, synchronization
Kinto.js
An Offline-First JavaScript Client for Kinto.
Stars: ✭ 268 (+173.47%)
Mutual labels:  sync, synchronization
Ron Cxx
RON2.1 C++ implementation
Stars: ✭ 33 (-66.33%)
Mutual labels:  sync, synchronization
synchly
Automate database backups with customizable recurring schedules.
Stars: ✭ 27 (-72.45%)
Mutual labels:  sync, synchronization
Gitconverter
Синхронизация хранилища конфигурации "1С:Предприятия" с репозиторием Git и последующим переходом на разработку в 1C:Enterprise Development Tools (1C:EDT) с сохранением истории
Stars: ✭ 149 (+52.04%)
Mutual labels:  sync, synchronization
Cloudcore
Framework that enables syncing between iCloud (CloudKit) and Core Data
Stars: ✭ 146 (+48.98%)
Mutual labels:  sync, synchronization
node-v
🔒 Secure ❄️ Synchronized ⚡️ Realtime ☁️ Cloud 🌈 Native JavaScript Variables & Events
Stars: ✭ 27 (-72.45%)
Mutual labels:  sync, synchronization
Llvs
Low-Level Versioned Store
Stars: ✭ 193 (+96.94%)
Mutual labels:  sync, synchronization
locize-cli
locize cli to import / export locales, add / edit / remove sync segments
Stars: ✭ 44 (-55.1%)
Mutual labels:  sync, synchronization
Dotmim.sync
A brand new database synchronization framework, multi platform, multi databases, developed on top of .Net Standard 2.0. https://dotmimsync.readthedocs.io/
Stars: ✭ 406 (+314.29%)
Mutual labels:  sync, synchronization
code-sync
Collaborative cloud platform for students, teachers, and professionals.
Stars: ✭ 28 (-71.43%)
Mutual labels:  sync, synchronization
Ipfs Sync
Live IPFS directory synchronization.
Stars: ✭ 16 (-83.67%)
Mutual labels:  sync, synchronization
Tabscrollattacher
Attach TabLayout and RecyclerView. Useful for categorizing RecyclerView items.
Stars: ✭ 196 (+100%)
Mutual labels:  recyclerview, tablayout
DeviceSync-for-OS-X
Calendar synchronization between iOS and OS X using USB
Stars: ✭ 12 (-87.76%)
Mutual labels:  sync, synchronization
Outlookgooglecalendarsync
Sync your Outlook and Google calendars
Stars: ✭ 1,113 (+1035.71%)
Mutual labels:  sync, synchronization
Remotestorage.js
⬡ JavaScript client library for integrating remoteStorage in apps
Stars: ✭ 2,155 (+2098.98%)
Mutual labels:  sync, synchronization

TabSync

A lightweight synchronizer between Android's Tabs and Lists!

Available on the View System & Jetpack Compose

  • On Android's View system, synchronization is made between TabLayout and RecyclerView
  • Android's Jetpack Compose, the synchronization is made between any LazeListState-based Composable (e.g. LazyColumn) and an index-based Composable (e.g. ScrollableTabRow).

Behaviour expected

As you scroll through items, the corresponding tabs will be selected automatically, and vice-versa; selecting tabs by hand will correspond to a scroll of the list to the corresponding item.

Mediator attached Mediator attached with smooth scroll

Articles

  • RecyclerView and TabLayout: Here's a Medium Article demonstrating the example in this repo step-by-step.
  • Jetpack compose: Coming soon.

Setup for the View system

Get the latest version via Maven Central:

Maven Central

Add Maven Central repository to your root build.gradle at the end of repositories:

allprojects {
    repositories {
        ...
        mavenCentral()
    }
}

Then add the dependency

dependencies {
    implementation 'io.github.ahmad-hamwi:tabsync:1.0.1'
}

Usage

Here is a non-comprehensive guide to TabSync:

Create a TabbedListMediator, and pass a RecyclerView, a TabLayout, and a list of RecyclerView's items indices that you wish to sync the tabs with.

val mediator = TabbedListMediator(
    recyclerView,
    tabLayout,
    categories.indices.toList()
)

Make sure that RecyclerView and the TabLayout are instantiated with their data (adapter with its data for RecyclerView, and tabs for the TabLayout) and call the attach method. Note that the tabs' count must not be less than the number of the passed indices.

method.attach()

To make the RecycerView smooth scrolls when pressing on a tab, you can pass a smooth scroll flag to the mediator:

val mediator = TabbedListMediator(
    recyclerView,
    tabLayout,
    categories.indices.toList(),
    true
)

To stop syncing between the RecyclerView and the TabLayout, call the detach method:

mediator.detach()

In case of refreshing the mediator (like data set has been changed), call the reAttach method:

mediator.reAttach()

To get the smooth scroll flag, call the getter isSmoothScroll()

val isSmoothScrolling = mediator.isSmoothScroll()

NOTE: You don't have to pass the full indices of the list provided as shown in the previous example. You may want to provide a couple of indices from your recyclerview's items to sync the tabs with:

 val mediator = TabbedListMediator(
   recyclerView,
   tabLayout,
   // Syncing the first tab with the item of index 0, the second one with the item of
   // index 2, and the third with the item of index 4
   mutableListOf(0, 2, 4) 
 )

Setup for Jetpack Compose

Get the latest version via Maven Central:

Maven Central

Add Maven Central repository to your root build.gradle at the end of repositories:

allprojects {
    repositories {
        ...
        mavenCentral()
    }
}

Then add the dependency

dependencies {
    implementation 'io.github.ahmad-hamwi:tabsync-compose:1.0.0'
}

Usage

Here is a non-comprehensive guide to TabSync Compose:

Call lazyListTabSync composable, and pass the indices of your list that you wish to sync the tabs with, and assign the result to a destructuring declaration like so:

@Composable
fun MyComposable(items: List<Item>) {

    val (selectedTabIndex, setSelectedTabIndex, syncedListState) = lazyListTabSync(items.indices.toList())

}

Make sure that whenever you call lazyListTabSync, the indices and the list's data are ready (above we're passing the state as a parameter).

Note that the tabs' count must not be less than the number of the passed indices.

  • The selectedTabIndex is the state of a ScrollableTabRow that we're going to sync with.
  • The setSelectedTabIndex is a function that we should call whenever the state of the ScrollableTabRow changes directly, for example by pressing the tab.
    ScrollableTabRow(selectedTabIndex) {
        categories.forEachIndexed { index, category ->
            Tab(
                selected = index == selectedTabIndex,
                onClick = { setSelectedTabIndex(index) },
            )
        }
    }
  • The listState is a LazyListState which should be attached to a scrollable that accepts it, for example a LazyColumn.
    LazyColumn(state = syncedListState) {
        ...
    }

Combined:

(Full example can be found under compose-app)

@Composable
fun MyComposable(categories: List<Category>) {
    val (selectedTabIndex, setSelectedTabIndex, syncedListState) = lazyListTabSync(categories.indices.toList())

    Column {
        ScrollableTabRow(selectedTabIndex) {
            categories.forEachIndexed { index, category ->
                Tab(
                    selected = index == selectedTabIndex,
                    onClick = { setSelectedTabIndex(index) },
                    ...
                )
            }
        }

        LazyColumn(state = syncedListState) {
            ...
        }
    }
}

NOTE: You don't have to pass the full indices of the list provided as shown in the previous example. You may want to provide a couple of indices from your list's items to sync the tabs with:

   // Syncing the first tab with the item of index 0, the second one with the item of
   // index 2, and the third with the item of index 4
   val (selectedTabIndex, setSelectedTabIndex, syncedListState) = lazyListTabSync(mutableListOf(0, 2, 4))

Additional arguments

  • By default, the list smooth scrolls when the selected tab changes, if you would like to stop the smooth scrolling, you can pass an optional smoothScroll flag:
  • tabsCount can be used to check for the viability of the synchronization with the tabs, the optimal case is that the number of tabs that we're syncing with is the same as the number of indices provided. (You cannot have a number of tabs lower than the number of indices provided, use tabsCount to make sure you're not doing that).
  • lazyListState can be used if you would like to provide your own state, the one coming from the destructuring declaration is going to be the same.
@Composable
fun MyComposable(items: List<Item>) {

    val (selectedTabIndex, setSelectedTabIndex, listState) = tabSyncMediator(
        mutableListOf(0, 2, 4), //Mandatory. The indices of lazy list items to sync the tabs with
        tabsCount = 3, //Optional. To check for viability of the synchronization with the tabs. Optimal when equals the count of syncedIndices.
        lazyListState = rememberLazyListState(), //Optional. To provide your own LazyListState. Defaults to rememberLazyListState().
        smoothScroll = true, // Optional. To make the auto scroll smooth or not when clicking tabs. Defaults to true
    )

}

Contributing

This library is made to help other developers out in their app developments, feel free to contribute by suggesting ideas and creating issues and PRs that would make this repository more helpful.

License

Copyright (C) 2023 Ahmad Hamwi

Licensed under the Apache License, Version 2.0

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].