• Stars
    star
    1,876
  • Rank 23,731 (Top 0.5 %)
  • Language
    Kotlin
  • License
    Apache License 2.0
  • Created over 3 years ago
  • Updated about 2 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

๐ŸŒป A pluggable, highly optimized Jetpack Compose and Kotlin Multiplatform image loading library that fetches and displays network images with Glide, Coil, and Fresco.

landscapist

Google
License API Build Status Android Weekly Medium Profile

๐ŸŒป Landscapist is a highly optimized, pluggable Jetpack Compose image loading solution that fetches and displays network images with Glide, Coil, and Fresco. This library supports tracing image loading states, composing custom implementations, and some valuable animations, such as crossfades, blur transformation, and circular reveals. You can also configure and attach image-loading behaviors easily and fast with image plugins.

Who's using Landscapist?

๐Ÿ‘‰ Check out who's using Landscapist.

Landscapist hits +300,000 downloads every month around the globe! ๐Ÿš€

globe

Why Landscapist?

Landscapist is built with a lot of consideration to improve the performance of image loadings in Jetpack Compose. Most composable functions of Landscapist are Restartable and Skippable, which indicates fairly improved recomposition performance according to the Compose compiler metrics. Also, the library performance was improved with Baseline Profiles and it supports many pluggable features, such as ImageOptions, listening image state changes, custom composables, preview on Android Studio, ImageComponent and ImagePlugin, placeholder, animations (circular reveal, crossfade), transformation (blur), and palette.

See the Compose compiler metrics for Landscapist

metrics

Demo projects

You can see the use cases of this library in the repositories below:

  • google/modernstorage: ModernStorage is a group of libraries that provide an abstraction layer over storage on Android to simplify its interactions.
  • GetStream/WhatsApp-Clone-Compose: ๐Ÿ“ฑ WhatsApp clone project demonstrates modern Android development built with Jetpack Compose and Stream Chat SDK for Compose.
  • android/storage-samples: Multiple samples showing the best practices in storage APIs on Android.
  • skydoves/DisneyCompose: ๐Ÿงธ A demo Disney app using Jetpack Compose and Hilt based on modern Android tech-stacks and MVVM architecture.
  • skydoves/MovieCompose: ๐ŸŽž A demo movie app using Jetpack Compose and Hilt based on modern Android tech stacks.

SNAPSHOT

See how to import the snapshot

Including the SNAPSHOT

Landscapist
Snapshots of the current development version of Landscapist are available, which track the latest versions.

To import snapshot versions on your project, add the code snippet below on your gradle file:

repositories {
   maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
}

Next, add the dependency below to your module's build.gradle file:

dependencies {
    implementation "com.github.skydoves:landscapist-glide:2.2.2-SNAPSHOT"
}
Glide

Glide

Maven Central

Add the codes below to your root build.gradle file (not your module-level build.gradle file):

allprojects {
    repositories {
        mavenCentral()
    }
}

Next, add the dependency below to your module's build.gradle file:

dependencies {
    implementation "com.github.skydoves:landscapist-glide:2.2.1"
}

Note: Landscapist-Glide includes version 4.15.1 of Glide internally. So please make sure your project is using the same Glide version or exclude the Glide dependency to adapt yours. Also, please make sure the Jetpack Compose version on the release page.

GlideImage

You can load images simply by using GlideImage composable function as the following example below:

GlideImage(
  imageModel = { imageUrl }, // loading a network image using an URL.
  imageOptions = ImageOptions(
    contentScale = ContentScale.Crop,
    alignment = Alignment.Center
  )
)

More Details for GlideImage

๐Ÿ‘‰ Read further for more details

Custom RequestOptions and TransitionOptions

You can customize your request-options with your own RequestOptions and TransitionOptions for applying caching strategies, loading transformations like below:

GlideImage(
  imageModel = { imageUrl },
  requestOptions = {
    RequestOptions()
        .override(256, 256)
        .diskCacheStrategy(DiskCacheStrategy.ALL)
        .centerCrop()
  }
)

Custom RequestBuilder

You can request image with your own RequestBuilder, which is the backbone of the request in Glide and is responsible for bringing your options together with your requested url or model to start a new load.

GlideImage(
  imageModel = { imageUrl },
  requestBuilder = { Glide.with(LocalContext.current.applicationContext).asDrawable() },
  modifier = Modifier.constrainAs(image) {
    centerHorizontallyTo(parent)
    top.linkTo(parent.top)
  }.aspectRatio(0.8f)
)

Custom RequestListener

You can register your own RequestListener, which allows you to trace the status of a request while images load.

GlideImage(
  imageModel = { imageUrl },
  requestListener = object: RequestListener<Drawable> {
    override fun onLoadFailed(
      e: GlideException?,
      model: Any?,
      target: Target<Drawable>?,
      isFirstResource: Boolean
    ): Boolean {
      // do something
      return false
    }

    override fun onResourceReady(
      resource: Drawable?,
      model: Any?,
      target: Target<Drawable>?,
      dataSource: DataSource?,
      isFirstResource: Boolean
    ): Boolean {
      // do something
      return true
    }
  }
)

LocalGlideRequestOptions

You can pass the same instance of your RequestOptions down through the Composition in your composable hierarchy as following the example below:

val requestOptions = RequestOptions()
    .override(300, 300)
    .circleCrop()

CompositionLocalProvider(LocalGlideRequestOptions provides requestOptions) {
  // Loads images with the custom `requestOptions` without explicit defines.
  GlideImage(
    imageModel = ...
  )
}
Fresco

Coil

Maven Central
Add the dependency below to your module's build.gradle file:

dependencies {
    implementation "com.github.skydoves:landscapist-coil:$version"
}

Note: Please make sure your project uses the same Jetpack Compose version on the release page.

CoilImage

You can load images by using the CoilImage composable function as the following example below:

CoilImage(
  imageModel = { imageUrl }, // loading a network image or local resource using an URL.
  imageOptions = ImageOptions(
    contentScale = ContentScale.Crop,
    alignment = Alignment.Center
  )
)

More Details for CoilImage

๐Ÿ‘‰ Read further for more details

Custom ImageRequest and ImageLoader

You can load images with your own ImageRequest and ImageLoader, which provides all the necessary information for loading images like caching strategies and transformations.

CoilImage(
  imageRequest = {
      ImageRequest.Builder(LocalContext.current)
        .data(poster.poster)
        .crossfade(true)
        .build() },
  imageLoader = {
      ImageLoader.Builder(LocalContext.current)
        .availableMemoryPercentage(0.25)
        .crossfade(true)
        .build() },
  modifier = modifier,
)

LocalCoilImageLoader

You can pass the same instance of your ImageLoader down through the Composition in your composable hierarchy as following the example below:

val imageLoader = ImageLoader.Builder(context).build()
CompositionLocalProvider(LocalCoilImageLoader provides imageLoader) {
 
  // This will automatically use the value of current imageLoader in the hierarchy.
  CoilImage(
    imageModel = ...
  )
}

Animated Image Supports (GIF, Webp)

You can load animated GIFs and WebP Images with your ImageLoader.

val context = LocalContext.current
val imageLoader = ImageLoader.Builder(context)
  .componentRegistry {
    if (SDK_INT >= 28) {
      add(ImageDecoderDecoder(context))
    } else {
      add(GifDecoder())
    }
  }
  .build()

CoilImage(
    imageModel = { poster.gif }, // URL of an animated image.
    imageLoader = { imageLoader },
    shimmerParams = ShimmerParams(
      baseColor = background800,
      highlightColor = shimmerHighLight
    ),
    modifier = Modifier
      .fillMaxWidth()
      .padding(8.dp)
      .height(500.dp)
      .clip(RoundedCornerShape(8.dp))
  )
Fresco

Fresco

Maven Central

Add the dependency below to your module's build.gradle file:

dependencies {
    implementation "com.github.skydoves:landscapist-fresco:$version"
}

Note: Landscapist-Fresco includes version 2.6.0 of Fresco. So please make sure your project is using the same Fresco version or exclude the Fresco dependency to adapt yours. Also, please make sure the Jetpack Compose version on the release page.

Setup

To get started, you should set up Fresco with ImagePipelineConfig in your Application class. Generally, it's recommended initializing with OkHttpImagePipelineConfigFactory. Also, you can customize caching, networking, and thread pool strategies with your own ImagePipelineConfig. For more details, you can check out Using Other Network Layers.

class App : Application() {

  override fun onCreate() {
    super.onCreate()

    val pipelineConfig =
      OkHttpImagePipelineConfigFactory
        .newBuilder(this, OkHttpClient.Builder().build())
        .setDiskCacheEnabled(true)
        .setDownsampleEnabled(true)
        .setResizeAndRotateEnabledForNetwork(true)
        .build()

    Fresco.initialize(this, pipelineConfig)
  }
}

FrescoImage

You can load images by using the FrescoImage composable function as the following example below:

FrescoImage(
  imageUrl = stringImageUrl, // loading a network image using an URL.
  imageOptions = ImageOptions(
    contentScale = ContentScale.Crop,
    alignment = Alignment.Center
  )
)

More Details for FrescoImage

๐Ÿ‘‰ Read further for more details

Custom ImageRequest

You can load images with your own ImageRequest, which provides some necessary information for loading images like decoding strategies and resizing.

val imageRequest = ImageRequestBuilder
  .newBuilderWithSource(uri)
  .setImageDecodeOptions(decodeOptions)
  .setLocalThumbnailPreviewsEnabled(true)
  .setLowestPermittedRequestLevel(RequestLevel.FULL_FETCH)
  .setProgressiveRenderingEnabled(false)
  .setResizeOptions(ResizeOptions(width, height))
  .build()

FrescoImage(
  imageUrl = stringImageUrl,
  imageRequest = { imageRequest }
)

LocalFrescoImageRequest

You can pass the same instance of your imageRequestBuilder down through the Composition in your composable hierarchy as following the example below:

// customize the ImageRequest as needed
val imageRequestBuilder = ImageRequestBuilder
  .newBuilderWithSource(uri)
  .setImageDecodeOptions(decodeOptions)
  .setLocalThumbnailPreviewsEnabled(true)
  .setLowestPermittedRequestLevel(RequestLevel.FULL_FETCH)
  .setProgressiveRenderingEnabled(false)
  .setResizeOptions(ResizeOptions(width, height))

CompositionLocalProvider(LocalFrescoImageRequest provides imageRequestBuilder) {
  // This will automatically use the value of current ImageRequest in the hierarchy.
  FrescoImage(
    imageUrl = ...
  )
}

Fresco Animated Image Support (GIF, Webp)

Maven Central

Add the below dependency to your module's build.gradle file.

dependencies {
  implementation "com.github.skydoves:landscapist-fresco-websupport:$version"
}

You can load animated GIFs and WebP Images with FrescoWebImage composable function. You should pass the AbstractDraweeController like the following example below:

FrescoWebImage(
  controllerBuilder = {
      Fresco.newDraweeControllerBuilder()
          .setUri(poster.gif) // GIF or Webp image url.
          .setAutoPlayAnimations(true)
  },
  modifier = Modifier
    .fillMaxWidth()
    .height(300.dp)
)

For more details, check out DraweeController, and Supported URIs for setting URI addresses. Also, you can load general images (jpeg, png, etc) which can be loaded with FrescoImage by using FrescoWebImage and your custom controller.

ImageOptions

You can give image options to your image composable functions by passing ImageOptions instance like the below:

GlideImage(
  ..
  imageOptions = ImageOptions(
      contentScale = ContentScale.Crop,
      alignment = Alignment.Center,
      contentDescription = "main image",
      colorFilter = null,
      alpha = 1f
    )
)

RequestSize

You can set the request size of your image by giving requestSize property as seen in the below:

GlideImage(
  ..
  imageOptions = ImageOptions(requestSize = IntSize(800, 600)),
)

Listening image state changes

You can listen the image state changes by giving onImageStateChanged parameter to your image composable functions like the below:

GlideImage(
  ..
  onImageStateChanged = {
    when (it) {
      GlideImageState.None -> ..
      GlideImageState.Loading -> ..
      is GlideImageState.Success -> ..
      is GlideImageState.Failure -> ..
    }
  }
)

Note: You can use CoilImageState for CoilImage and FrescoImageState for FrescoImage.

DataSource

For the success state, you can trace the origin of the image with the DataSource parameter. DataSource represents the following source origins below:

  • Memory: Represents an in-memory data source or cache (e.g. bitmap, ByteBuffer).
  • Disk: Represents a disk-based data source (e.g. drawable resource, or File).
  • Network: Represents a network-based data source.
  • Unknown: Represents an unknown data source.

Custom Composables

You can execute your own composable functions depending on the three request states below:

  • loading: Executed while loading an image.
  • success: Executed if loading an image successfully.
  • failure: Executed if fails to load an image (e.g. network error, wrong destination).
GlideImage( // CoilImage, FrescoImage
  imageModel = { imageUrl },
  modifier = modifier,
  // shows an indicator while loading an image.
  loading = {
    Box(modifier = Modifier.matchParentSize()) {
      CircularProgressIndicator(
        modifier = Modifier.align(Alignment.Center)
      )
    }
  },
  // shows an error text if fail to load an image.
  failure = {
    Text(text = "image request failed.")
  }
)

Also, you can customize the image content with our own composable function like the example below:

GlideImage( // CoilImage, FrescoImage
  imageModel = { imageUrl },
  // draw a resized image.
  success = { imageState ->
    imageState.imageBitmap?.let {
      Image(
        bitmap = it,
        modifier = Modifier.size(128.dp)
      )
    }
  },
  loading = { 
    // do something 
  }
)

Note: You can also use the custom Composables for CoilImage and FrescoImage.

Preview on Android Studio

Landscapist supports preview mode for each image library; Glide, Coil, and Fresco. You can show the preview image on your editor with a previewPlaceholder parameter as following:

GlideImage(
  imageModel = { imageUrl },
  modifier = Modifier.aspectRatio(0.8f),
  previewPlaceholder = R.drawable.poster
)

Note: You can also use the the previewPlaceholder parameter for CoilImage and FrescoImage.

ImageComponent and ImagePlugin

You can compose supported image plugins by Landscapist or you can create your own image plugin that will be composed following the image loading state. ImagePlugin is a pluggable compose interface that will be executed for loading images. ImagePlugin provides following types below:

  • PainterPlugin: A pinter plugin interface to be composed with the given Painter.
  • LoadingStatePlugin: A pluggable state plugin that will be composed while the state is ImageLoadState.Loading.
  • SuccessStatePlugin: A pluggable state plugin that will be composed when the state is ImageLoadState.Success.
  • FailureStatePlugin: A pluggable state plugin that will be composed when the state is ImageLoadState.Failure.

For example, you can implement your own LoadingStatePlugin that will be composed while loading an image like the below:

data class LoadingPlugin(val source: Any?) : ImagePlugin.LoadingStatePlugin {

  @Composable
  override fun compose(
    modifier: Modifier,
    imageOptions: ImageOptions?
  ): ImagePlugin = apply {
    if (source != null && imageOptions != null) {
      ImageBySource(
        source = source,
        modifier = modifier,
        alignment = imageOptions.alignment,
        contentDescription = imageOptions.contentDescription,
        contentScale = imageOptions.contentScale,
        colorFilter = imageOptions.colorFilter,
        alpha = imageOptions.alpha
      )
    }
  }
}

Next, you can compose plugins by adding them in the rememberImageComponent like the below:

GlideImage(
  imageModel = { poster.image },
  component = rememberImageComponent {
    add(CircularRevealPlugin())
    add(LoadingPlugin(source))
  },
)

or you can just add plugins by using the + expression like the below:

GlideImage(
  imageModel = { poster.image },
  component = rememberImageComponent {
    +CircularRevealPlugin()
    +LoadingPlugin(source)
  },
)

LocalImageComponent

You can provide the same ImageComponent instance in the composable hierarchy by using imageComponent extension and LocalImageComponent like the below:

val component = imageComponent {
  +CrossfadePlugin()
  +PalettePlugin()
}

CompositionLocalProvider(LocalImageComponent provides component) {
  ..
}

Placeholder

Maven Central

The landscapist-placeholder package provides useful image plugins, such as loading & failure placeholder supports and shimmering animation. To use placeholder supports, add the dependency below:

dependencies {
    implementation "com.github.skydoves:landscapist-placeholder:$version"
}

ShimmerPlugin

You can implement a shimmering effect while loading an image by using the ShimmerPlugin as following the example below:

GlideImage( // CoilImage, FrescoImage
  imageModel = { imageUrl },
  modifier = modifier,
  component = rememberImageComponent {
    // shows a shimmering effect when loading an image.
    +ShimmerPlugin(
      baseColor = background800,
      highlightColor = shimmerHighLight
    )
  },
  // shows an error text message when request failed.
  failure = {
    Text(text = "image request failed.")
  }
)

Note: You can also use the Shimmer effect for CoilImage and FrescoImage.

PlaceholderPlugin

You can show your own placeholder while loading an image or when fails to load an image with PlaceholderPlugin.Loading and PlaceholderPlugin.Failure.

GlideImage(
  ..
  component = rememberImageComponent {
      +PlaceholderPlugin.Loading(painterResource(id = R.drawable.placeholder_loading))
      +PlaceholderPlugin.Failure(painterResource(id = R.drawable.placeholder_failure))
    },
)

Note: The source should be one of ImageBitmap, ImageVector, or Painter.

ThumbnailPlugin

Landscapist supports the thumbnail feature, which pre-loads and displays small sizes of images while loading the original image. So you can make users feel images loading faster and give images a nature loading effect while displaying an original image. To show thumbnail, add the image plugin into your image component like the example below:

GlideImage(
  ..,
  component = rememberImageComponent {
      +ThumbnailPlugin() 
  },
)

You can also adjust the request sizes by giving the requestSize parameter:

component = rememberImageComponent {
    +ThumbnailPlugin(IntSize(30 ,30)) 
},

Note: It's highly recommended to use a small size of the request size on the thumbnail plugin to load the pre-load images process faster.

Animation

Maven Central

The landscapist-animation package provides useful image plugins related to animations, such as crossfade and circular reveal animation. To use animation supports, add the dependency below:

dependencies {
    implementation "com.github.skydoves:landscapist-animation:$version"
}

Preview

Circular Reveal Crossfade

Crossfade Animation

You can implement the crossfade animation while drawing images with CrossfadePlugin as the following:

GlideImage(
  imageModel = { poster.image },
  component = rememberImageComponent {
    +CrossfadePlugin(
      duration = 550
    )
  }
)

Note: You can also use the crossfade animation for CoilImage and FrescoImage.

Circular Reveal Animation

You can implement the circular reveal animation while drawing images with CircularRevealplugin as the following:

GlideImage(
  imageModel = { poster.image },
  component = rememberImageComponent {
    +CircularRevealPlugin(
      duration = 350
    )
  }
)

Note: You can also use the Circular Reveal animation for CoilImage and FrescoImage.

Transformation

Maven Central

The landscapist-transformation package provides useful image transformation plugins, such as the blur effect. To use transformation supports, add the dependency below:

dependencies {
    implementation "com.github.skydoves:landscapist-transformation:$version"
}

BlurTransformationPlugin

You can implement the blur effect with BlurTransformationPlugin as the following:

GlideImage( // CoilImage, FrescoImage also can be used.
  imageModel = { poster.image },
  component = rememberImageComponent {
      +BlurTransformationPlugin(radius = 10) // between 0 to Int.MAX_VALUE.
  }
)

Note: Landscapist's blur transformation falls back onto a CPU-based implementation to support older API levels. So you don't need to worry about API compatibilities and performance issues.

Palette

Maven Central

The landscapist-palette package provides useful image plugins related to palette, such as extracting primary color sets. To use palette supports, add the dependency below:

dependencies {
    implementation "com.github.skydoves:landscapist-palette:$version"
}

You can extract primary (theme) color profiles with PalettePlugin. You can check out Extract color profiles to see what kinds of colors can be extracted.

var palette by remember { mutableStateOf<Palette?>(null) }

GlideImage( // CoilImage, FrescoImage also can be used.
  imageModel = { poster.image },
  component = rememberImageComponent {
      +PalettePlugin { palette = it }
  }
)

Crossfade(
  targetState = palette,
  modifier = Modifier
    .padding(horizontal = 8.dp)
    .size(45.dp)
) {
  Box(
    modifier = Modifier
      .background(color = Color(it?.lightVibrantSwatch?.rgb ?: 0))
      .fillMaxSize()
  )
}

Also, you can customize attributes of PalettePlugin like the example below:

var palette by remember { mutableStateOf<Palette?>(null) }

GlideImage( // CoilImage, FrescoImage also can be used.
  imageModel = { poster.image },
  component = rememberImageComponent {
    +PalettePlugin(
      imageModel = poster.image,
      useCache = true, // use cache strategies for the same image model.
      interceptor = {
        it.addFilter { rgb, hsl ->
          // here edit to add the filter colors.
          false
        }
      },
      paletteLoadedListener = {
        palette = it
      }
    )
  }
)

Note: You can also use the Palette for CoilImage and FrescoImage.

BOM

Maven Central

The landscapist Bill of Materials (BOM) lets you manage all of your landscapist library versions by specifying only the BOMโ€™s version.

dependencies {
   // Import the landscapist BOM
   implementation "com.github.skydoves:landscapist-bom:$version"

   // Import landscapist libraries
   implementation "com.github.skydoves:landscapist-glide" // fresco or coil
   implementation "com.github.skydoves:landscapist-placeholder"
   implementation "com.github.skydoves:landscapist-palette"
   implementation "com.github.skydoves:landscapist-transformation"
}

Taking Snapshot Images With Paparazzi

Paparazzi allows you to take snapshot images of your Composable functions without running them on physical devices. You can take proper snapshots images about your images with Paparazzi like the below:

paparazzi.snapshot {
  CompositionLocalProvider(LocalInspectionMode provides true) {
    GlideImage(
      modifier = Modifier.fillMaxSize(),
      imageModel = { ".." },
      previewPlaceholder = R.drawable.placeholder
  )
 }
}

Who's using Landscapist?

If your project uses Landscapist, please let me know by creating a new issue! ๐Ÿค—

Twitter for Android

twitter

Inspiration

This library was mostly inspired by Accompanist.

Accompanist is a group of libraries that contains some utilities which I've found myself copying around projects which use Jetpack Compose. Currently, it contains image loading and insets. You can get more variety and recent systems from the library maintained by Google.

Find this repository useful? โค๏ธ

Support it by joining stargazers for this repository. โญ
Also follow me for my next creations! ๐Ÿคฉ

License

Designed and developed by 2020 skydoves (Jaewoong Eum)

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.

More Repositories

1

Pokedex

๐Ÿ—ก๏ธ Pokedex demonstrates modern Android development with Hilt, Material Motion, Coroutines, Flow, Jetpack (Room, ViewModel) based on MVVM architecture.
Kotlin
7,496
star
2

android-developer-roadmap

๐Ÿ—บ The Android Developer Roadmap offers comprehensive learning paths to help you understand Android ecosystems.
Kotlin
6,880
star
3

Balloon

๐ŸŽˆ Modernized and sophisticated tooltips, fully customizable with an arrow and animations for Android.
Kotlin
3,535
star
4

chatgpt-android

๐Ÿ“ฒ ChatGPT Android demonstrates OpenAI's ChatGPT on Android with Stream Chat SDK for Compose.
Kotlin
3,460
star
5

TransformationLayout

๐ŸŒ  Transform between two Views, Activities, and Fragments, or a View to a Fragment with container transform animations for Android.
Kotlin
2,279
star
6

ColorPickerView

๐ŸŽจ Android colorpicker for getting colors from any images by tapping on the desired color.
Java
1,503
star
7

DisneyMotions

๐Ÿฆ A Disney app using transformation motions based on MVVM (ViewModel, Coroutines, Flow, Room, Repository, Koin) architecture.
Kotlin
1,482
star
8

sandwich

๐Ÿฅช Sandwich is an adaptable and lightweight sealed API library designed for handling API responses and exceptions in Kotlin for Retrofit, Ktor, and Kotlin Multiplatform.
Kotlin
1,403
star
9

AndroidVeil

๐ŸŽญ An easy, flexible way to implement loading skeletons and shimmering effect for Android.
Kotlin
1,384
star
10

MarvelHeroes

โค๏ธ A sample Marvel heroes application based on MVVM (ViewModel, Coroutines, Room, Repository, Koin) architecture.
Kotlin
1,224
star
11

PowerMenu

๐Ÿ”ฅ Powerful and modernized popup menu with fully customizable animations.
Java
1,163
star
12

PowerSpinner

๐ŸŒ€ A lightweight dropdown popup spinner, fully customizable with an arrow and animations for Android.
Kotlin
1,105
star
13

Orbital

๐Ÿช Jetpack Compose Multiplatform library that allows you to implement dynamic transition animations such as shared element transitions.
Kotlin
989
star
14

DisneyCompose

๐Ÿงธ A demo Disney app using Jetpack Compose and Hilt based on modern Android tech stacks and MVVM architecture.
Kotlin
929
star
15

WhatIf

โ˜” Fluent syntactic sugar of Kotlin for handling single if-else statements, nullable, collections, and booleans.
Kotlin
835
star
16

ExpandableLayout

๐Ÿฆš An expandable layout that shows a two-level layout with an indicator.
Kotlin
809
star
17

ElasticViews

โœจ An easy way to implement an elastic touch effect for Android.
Kotlin
784
star
18

ProgressView

๐ŸŒŠ A polished and flexible ProgressView, fully customizable with animations.
Kotlin
755
star
19

AndroidRibbon

๐ŸŽ€ A fancy and beautiful ribbon with shimmer effects for Android.
Kotlin
684
star
20

Cloudy

โ˜๏ธ Jetpack Compose blur effect library, which falls back onto a CPU-based implementation to support older API levels.
Kotlin
639
star
21

Needs

๐ŸŒ‚ An easy way to implement modern permission instructions popup.
Kotlin
616
star
22

Pokedex-AR

๐Ÿฆ„ Pokedex-AR demonstrates ARCore, Sceneform, and modern Android tech stacks โ€” such as Hilt, Coroutines, Flow, Jetpack (Room, ViewModel, LiveData) based on MVVM architecture.
Kotlin
582
star
23

FlexibleBottomSheet

๐Ÿฌ Advanced Compose Multiplatform bottom sheet for segmented sizing and non-modal type, similar to Google Maps.
Kotlin
541
star
24

Only

๐Ÿ’ An easy way to persist and run code block only as many times as necessary on Android.
Kotlin
485
star
25

TheMovies

๐ŸŽฌ A demo project for The Movie DB based on Kotlin MVVM architecture and material design & animations.
Kotlin
484
star
26

MovieCompose

๐ŸŽž A demo movie app using Jetpack Compose and Hilt based on modern Android tech stacks.
Kotlin
475
star
27

ColorPickerPreference

๐ŸŽจ A library that lets you implement ColorPicker, ColorPickerDialog, ColorPickerPreference.
Kotlin
474
star
28

TheMovies2

๐ŸŽฌ A demo project using The Movie DB based on Kotlin MVVM architecture and material design & animations.
Kotlin
474
star
29

Submarine

๐Ÿšค Floating navigation view for displaying a list of items dynamically on Android.
Kotlin
471
star
30

retrofit-adapters

๐Ÿš† Retrofit call adapters for modeling network responses using Kotlin Result, Jetpack Paging3, and Arrow Either.
Kotlin
462
star
31

Rainbow

๐ŸŒˆ Fluent syntactic sugar of Android for applying gradations, shading, and tinting.
Kotlin
451
star
32

Orchestra

๐ŸŽบ A collection of Jetpack Compose libraries, which allows you to build tooltips, spinners, and color pickers.
Kotlin
447
star
33

IndicatorScrollView

๐Ÿง€ A dynamic scroll view that animates indicators according to its scroll position.
Kotlin
415
star
34

PreferenceRoom

๐Ÿšš Android processing library for managing SharedPreferences persistence efficiently and structurally.
Java
378
star
35

colorpicker-compose

๐ŸŽจ Jetpack Compose color picker library for getting colors from any images by tapping on the desired color.
Kotlin
370
star
36

DoubleLift

๐Ÿฆ‹ Expands and collapses a layout horizontally and vertically sequentially.
Kotlin
360
star
37

GoldMovies

๐Ÿ‘‘ The GoldMovies is based on Kotlin, MVVM architecture, coroutines, dagger, koin, and material designs & animations.
Kotlin
354
star
38

lazybones

๐Ÿ˜ด A lazy and fluent syntactic sugar for observing Activity, Fragment, and ViewModel lifecycles with lifecycle-aware properties.
Kotlin
351
star
39

sealedx

๐ŸŽฒ Kotlin Symbol Processor that auto-generates extensive sealed classes and interfaces for Android and Kotlin.
Kotlin
316
star
40

Bindables

๐Ÿงฌ Android DataBinding kit for notifying data changes to UI layers with MVVM architecture.
Kotlin
304
star
41

AndroidBottomBar

๐Ÿซ A lightweight bottom navigation view, fully customizable with an indicator and animations.
Kotlin
297
star
42

GithubFollows

:octocat: A demo project based on MVVM architecture and material design & animations.
Kotlin
293
star
43

Bundler

๐ŸŽ Android Intent & Bundle extensions that insert and retrieve values elegantly.
Kotlin
262
star
44

gemini-android

โœจ Gemini Android demonstrates Google's Generative AI on Android with Stream Chat SDK for Compose.
Kotlin
262
star
45

snitcher

๐Ÿฆ‰ Snitcher captures global crashes, enabling easy redirection to the exception tracing screen for swift recovery.
Kotlin
216
star
46

Chamber

โš–๏ธ A lightweight Android lifecycle-aware and thread-safe pipeline for communicating between components with custom scopes.
Kotlin
185
star
47

twitch-clone-compose

๐ŸŽฎ Twitch clone project demonstrates modern Android development built with Jetpack Compose and Stream Chat/Video SDK for Compose.
Kotlin
180
star
48

Flourish

๐ŸŽฉ Flourish implements dynamic ways to show up and dismiss layouts with animations.
Kotlin
174
star
49

compose-stable-marker

โœ’๏ธ Compose stable markers for KMP to tell stable/immutable guarantees to the compose compiler.
Kotlin
169
star
50

BaseRecyclerViewAdapter

โšก Fast way to bind RecyclerView adapter and ViewHolder for implementing clean sections.
Kotlin
163
star
51

Multi-ColorPicker

Android multi colorpicker for getting colors from any images by tapping on the desired color.
Kotlin
125
star
52

All-In-One

๐Ÿ‘” Health care application for reminding health-todo lists and making healthy habits every day.
Kotlin
118
star
53

Medal

๐Ÿ…An easy way to implement medal effect for Android.
Kotlin
111
star
54

viewmodel-lifecycle

๐ŸŒณ ViewModel Lifecycle allows you to track and observe Jetpack's ViewModel lifecycle changes.
Kotlin
104
star
55

WaterDrink

๐Ÿ’ง Simple water drinking reminder application based on MVP architecture.
Kotlin
75
star
56

CameleonLayout

A library that let you implement double-layer-layout changing with slide animation.
Kotlin
71
star
57

Awesome-Android-Persistence

A curated list of awesome android persistence libraries about SQLite, ORM, Mobile Database, SharedPreferences, etc.
70
star
58

SyncMarket

Let managing your application version update more simply.
Java
41
star
59

MagicLight-Controller

This simple demo application is controlling MagicLight's smart bulbs by bluetooth-le
Java
35
star
60

MethodScope

Reduce repetitive inheritance works in OOP world using @MethodScope.
Java
33
star
61

MapEditor

You can draw your map using by this Map Editor project.
C#
22
star
62

skydoves

๐Ÿ•Š skydoves
14
star
63

seungmani

This simple project is cocos-2dx c++ multi-patform(win32, android, ios, linux) game in Jan 2015.
C++
8
star
64

soniaOnline

XNA C# win 32/64 patform MMO game in Jan 2016.
C#
5
star
65

NityLife

This simple project is cocos-2dx c++ multi-patform(win32, android, ios, linux) game in 2014.
C++
5
star
66

Rurimo-Camera

You can take some screenshots or save images at clipboard so easily like just one click on Windows with this application.
C#
1
star