Theming, App bar,Home Screen tabs.

This commit is contained in:
shabinder 2020-12-29 12:46:25 +05:30
parent fa2c295a8b
commit b2c1b57fe0
15 changed files with 248 additions and 83 deletions

View File

@ -14,7 +14,7 @@ android {
buildToolsVersion "30.0.3"
defaultConfig {
applicationId "com.example.composelearn"
applicationId "com.shabinder.spotiflyer"
minSdkVersion 22
targetSdkVersion 30
versionCode 1
@ -75,9 +75,10 @@ dependencies {
//Compose
implementation "androidx.compose.ui:ui:$compose_version"
implementation "androidx.compose.ui:ui-tooling:$compose_version"
implementation "androidx.compose.runtime:runtime-livedata:$compose_version"
implementation "androidx.compose.material:material:$compose_version"
implementation "androidx.compose.material:material-icons-extended:$compose_version"
implementation "androidx.compose.ui:ui-tooling:$compose_version"
//Lifecycle
implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version"

View File

@ -1,24 +0,0 @@
package com.example.composelearn
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.example.composelearn", appContext.packageName)
}
}

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.composelearn">
package="com.shabinder.spotiflyer">
<application
android:allowBackup="true"
@ -8,11 +8,11 @@
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.ComposeLearn">
android:theme="@style/Theme.SpotiFlyer">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@style/Theme.ComposeLearn">
android:theme="@style/Theme.SpotiFlyer">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

View File

@ -1,4 +1,4 @@
package com.example.composelearn
package com.shabinder.spotiflyer
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
@ -15,11 +15,10 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.setContent
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.core.view.WindowCompat
import com.example.composelearn.ui.ComposeLearnTheme
import com.example.composelearn.ui.appNameStyle
import com.shabinder.spotiflyer.home.Home
import com.shabinder.spotiflyer.ui.ComposeLearnTheme
import com.shabinder.spotiflyer.ui.appNameStyle
import dev.chrisbanes.accompanist.insets.ProvideWindowInsets
import dev.chrisbanes.accompanist.insets.statusBarsHeight
@ -33,28 +32,23 @@ class MainActivity : AppCompatActivity() {
setContent {
ComposeLearnTheme {
ProvideWindowInsets {
HomeScreen()
Column {
val appBarColor = MaterialTheme.colors.surface.copy(alpha = 0.87f)
// Draw a scrim over the status bar which matches the app bar
Spacer(Modifier.background(appBarColor).fillMaxWidth().statusBarsHeight())
AppBar(
backgroundColor = appBarColor,
modifier = Modifier.fillMaxWidth()
)
Home()
}
}
}
}
}
}
@Composable
fun HomeScreen() {
Column {
val appBarColor = MaterialTheme.colors.surface.copy(alpha = 0.87f)
// Draw a scrim over the status bar which matches the app bar
Spacer(Modifier.background(appBarColor).fillMaxWidth().statusBarsHeight())
AppBar(
backgroundColor = appBarColor,
modifier = Modifier.fillMaxWidth()
)
}
}
@Composable
@ -89,10 +83,10 @@ fun AppBar(
}
@Preview(showBackground = true)
//@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
ComposeLearnTheme {
HomeScreen()
}
}

View File

@ -0,0 +1,148 @@
package com.shabinder.spotiflyer.home
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.*
import androidx.compose.material.TabDefaults.tabIndicatorOffset
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.InsertLink
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.viewinterop.viewModel
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.shabinder.spotiflyer.R
import com.shabinder.spotiflyer.ui.SpotiFlyerTypography
import com.shabinder.spotiflyer.ui.colorAccent
import com.shabinder.spotiflyer.ui.colorPrimary
@Composable
fun Home(modifier: Modifier = Modifier) {
val viewModel: HomeViewModel = viewModel()
Column(modifier = modifier) {
AuthenticationBanner(viewModel,modifier)
SearchBar(viewModel,modifier)
val selectedCategory by viewModel.selectedCategory.collectAsState()
HomeTabBar(
selectedCategory,
HomeCategory.values(),
viewModel::selectCategory,
modifier
)
}
}
@Composable
fun AuthenticationBanner(viewModel: HomeViewModel, modifier: Modifier) {
val authenticationStatus by viewModel.isAuthenticating.collectAsState()
if (authenticationStatus) {
// TODO show a progress indicator or similar
}
}
@Composable
fun HomeTabBar(
selectedCategory: HomeCategory,
categories: Array<HomeCategory>,
selectCategory: (HomeCategory) -> Unit,
modifier: Modifier = Modifier
) {
val selectedIndex =categories.indexOfFirst { it == selectedCategory }
val indicator = @Composable { tabPositions: List<TabPosition> ->
HomeCategoryTabIndicator(
Modifier.tabIndicatorOffset(tabPositions[selectedIndex])
)
}
TabRow(
selectedTabIndex = selectedIndex,
indicator = indicator,
modifier = modifier
) {
categories.forEachIndexed { index, category ->
Tab(
selected = index == selectedIndex,
onClick = { selectCategory(category) },
text = {
Text(
text = when (category) {
HomeCategory.About -> stringResource(R.string.home_about)
HomeCategory.History -> stringResource(R.string.home_history)
},
style = MaterialTheme.typography.body2
)
}
)
}
}
}
@Composable
fun SearchBar(
viewModel: HomeViewModel,
modifier: Modifier = Modifier
){
val link by viewModel.link.collectAsState()
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = modifier.padding(top = 16.dp,bottom = 16.dp)
){
TextField(
leadingIcon = {
Icon(Icons.Rounded.InsertLink,tint = Color.LightGray)
},
label = {Text(text = "Paste Link Here...",color = Color.LightGray)},
value = link,
onValueChange = { viewModel.updateLink(it) },
singleLine = true,
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Uri),
modifier = Modifier.padding(12.dp).fillMaxWidth()
.border(
BorderStroke(2.dp, Brush.horizontalGradient(listOf(colorPrimary, colorAccent))),
RoundedCornerShape(30.dp)
),
backgroundColor = Color.Black,
textStyle = AmbientTextStyle.current.merge(TextStyle(fontSize = 20.sp)),
shape = RoundedCornerShape(size = 30.dp),
activeColor = Color.Transparent,
inactiveColor = Color.Transparent
)
OutlinedButton(
modifier = Modifier.padding(12.dp).wrapContentWidth(),
onClick = {/*TODO*/},
border = BorderStroke(1.dp, Brush.horizontalGradient(listOf(colorPrimary, colorAccent)))
){
Text(text = "Search",style = SpotiFlyerTypography.h6,modifier = Modifier.padding(4.dp))
}
}
}
@Composable
fun HomeCategoryTabIndicator(
modifier: Modifier = Modifier,
color: Color = MaterialTheme.colors.onSurface
) {
Spacer(
modifier.padding(horizontal = 24.dp)
.preferredHeight(4.dp)
.background(color, RoundedCornerShape(topLeftPercent = 100, topRightPercent = 100))
)
}

View File

@ -0,0 +1,39 @@
package com.shabinder.spotiflyer.home
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
class HomeViewModel: ViewModel() {
private val _link = MutableStateFlow("")
val link:StateFlow<String>
get() = _link
fun updateLink(s:String) {
_link.value = s
}
private val _isAuthenticating = MutableStateFlow(true)
val isAuthenticating:StateFlow<Boolean>
get() = _isAuthenticating
fun authenticated(s:Boolean) {
_isAuthenticating.value = s
}
private val _selectedCategory = MutableStateFlow(HomeCategory.About)
val selectedCategory :StateFlow<HomeCategory>
get() = _selectedCategory
fun selectCategory(s:HomeCategory) {
_selectedCategory.value = s
}
}
enum class HomeCategory {
About, History
}

View File

@ -1,4 +1,4 @@
package com.example.composelearn.ui
package com.shabinder.spotiflyer.ui
import androidx.compose.material.Colors
import androidx.compose.material.darkColors
@ -22,7 +22,9 @@ val SpotiFlyerColors = darkColors(
error = colorRedError,
onError = Color.Black,
surface = darkBackgroundColor,
background = darkBackgroundColor
background = darkBackgroundColor,
onSurface = Color.LightGray,
onBackground = Color.LightGray
)
/**

View File

@ -1,4 +1,4 @@
package com.example.composelearn.ui
package com.shabinder.spotiflyer.ui
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Shapes

View File

@ -1,4 +1,4 @@
package com.example.composelearn.ui
package com.shabinder.spotiflyer.ui
import androidx.compose.material.MaterialTheme
import androidx.compose.runtime.Composable

View File

@ -1,11 +1,11 @@
package com.example.composelearn.ui
package com.shabinder.spotiflyer.ui
import androidx.compose.material.Typography
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.*
import androidx.compose.ui.unit.sp
import com.example.composelearn.R
import com.shabinder.spotiflyer.R
private val Montserrat = fontFamily(
font(R.font.montserrat_light, FontWeight.Light),
@ -110,9 +110,9 @@ val SpotiFlyerTypography = Typography(
val appNameStyle = TextStyle(
fontFamily = pristineFont,
fontSize = 42.sp,
fontSize = 40.sp,
fontWeight = FontWeight.SemiBold,
lineHeight = 42.sp,
letterSpacing = (-0.5).sp,
color = Color.White
letterSpacing = (1.5).sp,
color = Color(0xFFECECEC)
)

View File

@ -1,3 +1,5 @@
<resources>
<string name="app_name">SpotiFlyer</string>
<string name="home_about">About</string>
<string name="home_history">History</string>
</resources>

View File

@ -1,9 +1,10 @@
<resources>
<!-- Base application theme. -->
<style name="Theme.ComposeLearn" parent="Theme.AppCompat.NoActionBar">
<style name="Theme.SpotiFlyer" parent="Theme.AppCompat.NoActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:textColor">@color/white</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
</style>

View File

@ -1,17 +0,0 @@
package com.example.composelearn
import org.junit.Test
import org.junit.Assert.*
/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
}

View File

@ -23,12 +23,31 @@ buildscript {
}
}
allprojects {
subprojects{
repositories {
google()
jcenter()
maven { url "https://jitpack.io" }
}
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach {
kotlinOptions {
// Treat all Kotlin warnings as errors
//allWarningsAsErrors = true
freeCompilerArgs += '-Xopt-in=kotlin.RequiresOptIn'
// Enable experimental coroutines APIs, including Flow
freeCompilerArgs += '-Xopt-in=kotlinx.coroutines.ExperimentalCoroutinesApi'
freeCompilerArgs += '-Xopt-in=kotlinx.coroutines.FlowPreview'
freeCompilerArgs += '-Xopt-in=kotlin.Experimental'
freeCompilerArgs += "-Xallow-jvm-ir-dependencies"
// Set JVM target to 1.8
jvmTarget = "1.8"
}
}
}
task clean(type: Delete) {

View File

@ -1,2 +1,2 @@
rootProject.name = "ComposeLearn"
rootProject.name = "SpotiFlyer"
include ':app'