• Stars
    star
    269
  • Rank 149,643 (Top 3 %)
  • Language
    Kotlin
  • License
    Apache License 2.0
  • Created over 2 years ago
  • Updated 11 months ago

Reviews

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

Repository Details

๐Ÿค– Android app built with jetpack ๐Ÿš€ compose follows new revamped guide to app architecture. Implemented with State, Coroutines โžฐ, ViewModels, Repository pattern, Light/Dark theme ๐ŸŒˆ MD3, Animations, Draw on canvas, Custom layouts, UI state handling, ๐ŸŒ€ Image loading with coil, Palette ๐ŸŽจ usage and dynamic theming etc.

Compose Actors ๐Ÿ’ƒ

Roadmap v0.3.0

  • Let users search for movies directly just like searching for actors.
  • Hilt will be replaced by removing Koin.
  • Restructure packages and files by introducing new source files.
  • Replace every Spacer composable used in code with various custom AppSpacer.
  • Separate the ViewModel param from Screen and UI composables to see previews for all screens.
  • Break composables into smaller for previewing.
  • Separate composables into Screen and UI to separated ViewModel usage and previewing for all screens.
  • Add feature for adding actors to favorites like movies.
  • Add bottom sheet to home screen to support navigation for various screens.
  • Implement paging to upcoming lazy list movies in home tab.
  • Setup project dependencies, resources for initial testing, write simple test.
  • Write tests for app navigation for all composable destinations.

Roadmap v0.4.0

Rename app from Compose actors -> Compose Entertainer.

  • Add new feature seasons or series information to app.
  • Include seasons in home tabs navigation.
  • Enabled adding seasons to favorites.
  • Move favorites section from home tab to new place (Restructure all screen flows).
  • Collapsable TopBars, BottomBars, Scroll effects, new animations.

AppBanner

New release - v0.2.0

  • Add DI with Koin.
  • Modal bottom sheets & Bottom sheets.
  • Migrate to compose insets from accompanist.
  • Add new movie details screen, made changes to actors details screen.
  • Improved search functionality, added voice search, handled keyboard changes.
  • New feature to add Movie to favorites.
  • Add new database repository layer for favorites.
  • Add tabs in Home screen with actors/movies/favorites categories.

V2 Previews

Home Tabs

Actors Movies Favorites

Modal bottom sheets

Actor Movie

Movie details & Add to favorites

Add to favorites Favorites Details

Voice search actors

Search capabilities

Inspired from

JetCaster JetNews JetSnack

More compose content

๐Ÿ—ผ Architecture

Follows new architecture guide updated on 14 December 2021 from revamped guide to app architecture.

๐ŸŽน Layer of this app.

Network Repository ViewModels Screens
Data
๐ŸŽ๐ŸŽ
๐ŸŽ๐ŸŽ
---> Source
๐ŸŽ
--->
Suspend
Coroutines
โžฐโžฐ
--->
State
Composables
๐Ÿ“ฑ๐Ÿ“ฑ
๐Ÿ“ฑ๐Ÿ“ฑ

ArchitectureLayer

๐Ÿก App Overview Compose Blog

Android app built with Jetpack Compose shows actors information fetched from Tmdb Api. You may install and try to understand the code better, but make sure you provide your own Tmdb api key for data to show up in directory /utils/ApiKey.kt.

Release - v0.1.0

Screen Preview
Home Screen (Default destination)

โ€ข Shows category list of actors in row of type popular & trending.
โ€ข Has it's own ViewModel to manage it's ui state.
โ€ข Custom TopAppBar container with search box.
โ€ข Navigates to Search screen clicking search box.
โ€ข Navigates to Detail screen with castId clicking any cast item.
โ€ข If user is offline snackbar message is shown.
โ€ข CircularProgressIndicator will be shown untill data is fetched.
โ€ข Image fetching with Coil, manages state error/placeholder.
Home screen preview
Search Screen

โ€ข Shows list of actors based on user submitted query.
โ€ข Animatable shapes infinitely repeatable.
โ€ข Has it's own ViewModel to manage it's ui state.
โ€ข TextField contained in TopAppBar completely transparent.
โ€ข Navigates to Detail screen with castId clicking any cast item.
โ€ข Screen and animation state changes on search began.
โ€ข Handles query & value changes correctly to fetch results.
โ€ข Draw Arc/Line on canvas & animate to shape shift like search icon.
โ€ข Different colors for animatables for both light/dark theme.
Search screen preview
Detail Screen

โ€ข Shows user selected actor from other screens.
โ€ข Has it's own ViewModel to manage it's ui state.
โ€ข Reveal effect animation added to few composables.
โ€ข CircularProgressIndicator will be shown untill data is fetched.
โ€ข Image fetching with Coil, manages state error/placeholder.
โ€ข Background image with gradient foreground effect.
โ€ข Draws dynamic color behind system bars.
Detail screen preview

๐Ÿ” Search Animation

// Simple progressive circle looking animation
val animateCircle = remember { Animatable(0f) }.apply {
    AnimateShapeInfinitely(this)
}

@Composable
fun AnimateShapeInfinitely(
    // shape which will be animated infinitely.
    animateShape: Animatable<Float, AnimationVector1D>,
    // final float state to be animated.
    targetValue: Float = 1f,
    // duration took for animating once.
    durationMillis: Int = 1000
) {
    LaunchedEffect(animateShape) {
        animateShape.animateTo(
            targetValue = targetValue,
            animationSpec = infiniteRepeatable(
                animation = tween(durationMillis, LinearEasing),
                repeatMode = RepeatMode.Restart
            )
        )
    }
}

Although I couldn't fully achieve the desired result as I imagined, I've settled for this current state for now.

Offline Dark

Calling the function once will draw a circle, in my example I have drawn it thrice with differnt colors, radius and scales.

DrawCircleOnCanvas(
    scale = scaleInfiniteTransition(targetValue = 2f, durationMillis = 600),
    color = circleColor,
    radiusRatio = 4f
)

I have kept all initial states of 3 circles to 0f to make end result much smoother.
Random or uneven gaps between initial/target/durationMillis will make end animation look more abrupt and aggressively pushing it's bounds.

@Composable
private fun scaleInfiniteTransition(
    initialValue: Float = 0f,
    targetValue: Float,
    durationMillis: Int,
): Float {
    val infiniteTransition = rememberInfiniteTransition()
    val scale: Float by infiniteTransition.animateFloat(
        initialValue = initialValue,
        targetValue = targetValue,
        animationSpec = infiniteRepeatable(
            animation = tween(durationMillis, easing = LinearEasing),
            repeatMode = RepeatMode.Reverse
        )
    )
    return scale
}
@Composable
fun DrawCircleOnCanvas(
    scale: Float,
    color: Color,
    radiusRatio: Float
) {
    Canvas(
        modifier = Modifier
            .fillMaxSize()
            .graphicsLayer {
                scaleX = scale
                scaleY = scale
            }
    ) {
        val canvasWidth = size.width
        val canvasHeight = size.height
        drawCircle(
            color = color,
            center = Offset(
                x = canvasWidth / 2,
                y = canvasHeight / 2
            ),
            radius = size.minDimension / radiusRatio,
        )
    }
}

๐Ÿ“ด Offline state

Dark Light
Offline Dark Offline Light

Show a Snackbar message with SnackbarHostState.

if (!isOnline) {
    LaunchedEffect(scope) {
        scope.launch {
            scaffoldState.snackbarHostState.showSnackbar(
                message = context.getString(R.string.offline_snackbar_message),
                duration = SnackbarDuration.Indefinite
            )
        }
    }
}

ViewModels

All screens have their own ViewModels for managing the ui state.

class HomeViewModel(
    application: Application,
    private val repository: AppRepository
) : AndroidViewModel(application) {

    // Holds the state for values in HomeViewState
    var uiState by mutableStateOf(HomeViewState())
        private set

    init {
        // Update the values in uiState from all data sources.
        viewModelScope.launch {
            uiState = HomeViewState(isFetchingActors = true)
            val popularActorsList = repository.getPopularActorsData()
            val trendingActorsList = repository.getTrendingActorsData()
            uiState = HomeViewState(
                popularActorList = popularActorsList,
                trendingActorList = trendingActorsList,
                isFetchingActors = false
            )
        }
    }
}

Model for UI state of the screen.

data class HomeViewState(
    var popularActorList: List<Actor> = emptyList(),
    var trendingActorList: List<Actor> = emptyList(),
    val isFetchingActors: Boolean = false,
)

ViewModel used in a screen-level composable.

@Composable
fun HomeScreen(
    viewModel: HomeViewModel
) {
    val uiState = viewModel.uiState
    Box {
        ScreenContent(uiState.popularActorList)
    }
}

Repository

All ViewModels have access to repository which has single instance.

class AppRepository {

    private val networkDataSource by lazy { NetworkDataSource() }

    suspend fun getPopularActorsData(): List<Actor> {
        val listData: List<Actor>
        withContext(Dispatchers.IO) {
            listData = networkDataSource.getPopularActors()
        }
        return listData
    }
}

Instantiated repository will be passed to all ViewModels.

val repository = (application as ComposeActorsApp).repository

NavHost(
    navController = navController,
    startDestination = startDestination
) {
    composable(
        "Destination Route"
    ) {
        HomeScreen(
            viewModel = viewModel(
                factory = HomeViewModel.provideFactory(
                    application, repository
                )
            )
        )
    }
}

๐Ÿ”จ Structure

๐Ÿ“ data ๐Ÿ“ navigation ๐Ÿ“ repository ๐Ÿ“ root
๐Ÿ“„ NetworkDataSource.kt
๐Ÿ“„ JsonRemoteData.kt
๐Ÿ“„ Urls.kt
๐Ÿ“„ AppActions.kt
๐Ÿ“„ AppDestinations.kt
๐Ÿ“„ AppNavigation.kt
๐Ÿ“„ AppRepository.kt ๐Ÿ“„ MainActivity.kt
๐Ÿ“„ Application.kt
๐Ÿ“ ui ๐Ÿ“ utils ๐Ÿ“ model
๐Ÿ“ home
๐Ÿ“ details
๐Ÿ“ search
๐Ÿ“ components
๐Ÿ“ theme
๐Ÿ“„ InfiniteFlowingThings.kt
๐Ÿ“„ RevealEffect.kt
๐Ÿ“„ Utilities.kt
๐Ÿ“„ DynamicThemeGenerator.kt
๐Ÿ“„ NetworkManager.kt
๐Ÿ“„ NetworkQueryUtils.kt
๐Ÿ“„ Actor.kt
๐Ÿ“„ ActorDetail.kt
๐Ÿ“„ Movie.kt

๐Ÿ“ Packages in ui

๐Ÿ“ home ๐Ÿ“ details ๐Ÿ“ search ๐Ÿ“ components ๐Ÿ“ theme
๐Ÿ“„ HomeScreen.kt
๐Ÿ“„ HomeViewModel.kt
๐Ÿ“„ DetailsScreen.kt
๐Ÿ“„ DetailsViewModel.kt
๐Ÿ“„ SearchScreen.kt
๐Ÿ“„ SearchViewModel.kt
๐Ÿ“„ AnimatedSearch.kt
๐Ÿ“„ AppBars.kt
๐Ÿ“„ Components.kt
๐Ÿ“„ NetworkImage.kt
๐Ÿ“„ Progress.kt
๐Ÿ“„ Color.kt
๐Ÿ“„ Shape.kt
๐Ÿ“„ Theme.kt
๐Ÿ“„ Type.kt

๐ŸŒ€ Image loading with Coil

Reusable composable used in all screens to load image from an Url.

@Composable
fun LoadNetworkImage(
    imageUrl: String,
    contentDescription: String,
    modifier: Modifier,
    shape: Shape
) {
    Image(
        painter = rememberImagePainter(
            data = imageUrl,
            builder = {
                placeholder(R.drawable.animated_progress)
                error(R.drawable.ic_image_not_available)
            }),
        contentDescription = contentDescription,
        contentScale = ContentScale.Crop,
        modifier = modifier
            .clip(shape)
            .background(color = MaterialTheme.colors.surface)
    )
}

Then we will just call the composable anywhere in app screens.

LoadNetworkImage(
    imageUrl = "https://image_url",
    contentDescription = stringResource(R.string.cd_movie_poster),
    modifier = Modifier.size(100.dp, 150.dp),
    shape = MaterialTheme.shapes.medium,
)

๐ŸŽจ App Theme

๐ŸŒˆ Material Design 3.

Followed theming and color practices from Material Theme Builder Web Tool. Learn more here

Color.kt

// Light theme colors
val light_primary = Color(0xFFaa370c)
val light_onPrimary = Color(0xFFffffff)
val light_background = Color(0xFFFFFAF9)
val light_onBackground = Color(0xFF211a18)
val light_surface = Color(0xFFFFE6DB)
val light_onSurface = Color(0xFF211a18)

// Dark theme colors
val dark_primary = Color(0xFFffb59c)
val dark_onPrimary = Color(0xFF5f1600)
val dark_background = Color(0xFF211a18)
val dark_onBackground = Color(0xFFede0dc)
val dark_surface = Color(0xFF302522)
val dark_onSurface = Color(0xFFede0dc)

Theme.kt

val LightColorPalette = lightColors(
    primary = light_primary,
    onPrimary = light_onPrimary,
    background = light_background,
    onBackground = light_onBackground,
    surface = light_surface,
    onSurface = light_onSurface,
)

val DarkColorPalette = darkColors(
    primary = dark_primary,
    onPrimary = dark_onPrimary,
    background = dark_background,
    onBackground = dark_onBackground,
    surface = dark_surface,
    onSurface = dark_onSurface
)

โšชโšซ Light/Dark theme screenshots

Home Search Detail
Home Dark
Home Light
Search Dark
Search Light
Detail Dark
Detail Light

๐Ÿ“ Blog

Article banner
Reveal effect animations in compose jetpack android
Read article
Article banner
Compose and build android app with new architecture principles
Read article
Article banner
Custom shape animations pulsating circles on canvas in compose android
Read article
Article banner
Search with TextField in list Compose Android Jetpack
Read article

AppPreview

๐Ÿ’ก Motivation and Context

Jetpack Compose is Androidโ€™s modern toolkit for building native UI. It enables you to quickly bring your app to life with less code, powerful tools, and intuitive Kotlin APIs.

Understanding to implement own Theme Shape Typography Color has became bit easier by referring to lot of official jetpack compose samples which are available in GitHub.

Best of all we got to do this in Kotlin way. Excited and long way to go from here.

๐Ÿ† Credits

๐Ÿš€ JetCaster

Check the official JetCaster example from Android Team, I have used their code to generate Swatch with Palette Api in my Detail screen.

๐Ÿ”‘ Tmdb Api

Images and all information in app belongs to and taken from Tmdb Api. I do not own any of it and only made use of it for this app demonstration purpose.

Obtain your own Tmdb Api Key from here

License

Copyright 2021 Rajasekhar K E

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

    https://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

jetpack-compose-samples

This repository contains samples on jetpack compose for building different components like layouts, animations, transitions, saving states and more. Most of examples are demonstrated in blog posts.
Kotlin
63
star
2

hangman-compose

๐ŸŽฎ Hangman Game for Android ๐Ÿค– build with Compose ๐Ÿš€. Built with jetpack components, Room for saving game history, preferences for loading game settings, ViewModels for persisting game state, LiveData/States for observing states, Koin for DI, minimal compose animations for good UX, Light/Dark theme ๐ŸŒˆ MD3.
Kotlin
19
star
3

Filter-Search-RecyclerView

Repository for android application which shows how to filter search in RecyclerView with user entered query , also voice search enabled with modern layout interface. These implementations are demonstrated in my blog, link is posted below.
Kotlin
18
star
4

android-navigation-with-compose

Build navigation flow with list and detail screen with jetpack compose in android. This app contains an overview screen that displays a list of cats, and a detail screen showing each cat's details.
Kotlin
10
star
5

RecyclerViewToViewPager

ViewPager2 comes with major improvements from ViewPager which enables swipe views with RecyclerView, vertical swipe, orientation, right-to-left support, Modifiable fragment collection, PageTransformations, swipe between fragments with TabLayout, DiffUtils etc. Let's understand with an example implementation.
Kotlin
10
star
6

firebase-cloud-firestore-android

Android app built to demonstrate on how to build RecyclerView using Cloud Firestore with Collections, Documents and Fields.
Kotlin
6
star
7

ArchitectureComponentsJava

This project demonstrates how to build a simple app with Navigation components part of Android Jetpack Components. Check the blog from given link.
Java
6
star
8

SharedElementTransitionExample

Implement SharedElementTransition in android application with NavigationComponent. This project walkthrough will be clearly explained in my blog. Check the link for the blog on this example.
Kotlin
4
star
9

BottomNavigationView-NavigationComponent

Source code for bottom navigation view. setting up with navigation controller
Kotlin
4
star
10

NavigationComponent-with-simple-example

This project demonstrated how to implement navigation in our android application with a simple example.
Java
3
star
11

ProjectSubmission-GoogleDevelopers

Project Submission for 30 Days of Kotlin with Google Developers.
Kotlin
2
star
12

Book-Listing-App

Book Listing app which would allow a user to get a list of published books on a given topic using the google books api in order to fetch results and display them to the user.
Java
1
star
13

pass-data-between-fragments-navigation

This is sample android app demonstrates on how to use NavigationComponent to pass data between fragments, adding destinations to navigation graph with kotlin.
Kotlin
1
star
14

News-App

A News feed app which gives a user regularly-updated news from the internet related to a particular topic, person, or location.
Java
1
star
15

Introduction_To_JavaScript

This Repository has solutions for quizes in Introduction to JavaScript lesson from udacity.
JavaScript
1
star
16

WebViewAndroid

Learn how to implement WebView interface in Android application using WebKit API. Build interactive webview using JavaScript and WebSettings.
Kotlin
1
star
17

Tour-Guide-App-Udacity-student-project-

This app shows information and various locations in multiple screens. Feel free to make changes : )
Java
1
star
18

ConcatAdapter-AndroidExample

Merge mutiple adapters with single RecyclerView using ConcatAdapter. Check my blog to learn more with example i have implemented here.
Java
1
star
19

SearchInterface-Android

Android application to show how to implement search interface. Filter search results from internet. With kotlin using Coroutines, RecyclerView, MaterialDesign.
Kotlin
1
star
20

google-play-example

Android application built with all fragments and components which looks and implements structure like Google play app.
Kotlin
1
star
21

NetworkRequestUsingViewModel

This repository is created to build android applications based on architecture components. You will find different repositories in each branch for dealing with separate components like WorkManager, LiveData, ViewModel, Room, Paging etc. Things which are missing will be added eventually.
Java
1
star
22

Inventory-App

Inventory App which would allow a store to keep track of its inventory of products. The app will need to store information about price, quantity available, supplier, and a picture of the product. It will also need to allow the user to track sales and shipments and make it easy for the user to order more from the listed supplier.
Java
1
star
23

developers-breach-android

Android app shows generated feed from site with wordpress api. Completed second release with major changes.
Kotlin
1
star