Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions WindowSizeClassSample/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
local.properties
/.idea/
/.kotlin/
1 change: 1 addition & 0 deletions WindowSizeClassSample/app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
60 changes: 60 additions & 0 deletions WindowSizeClassSample/app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.compose)
}

android {
namespace = "com.google.sample.wsc.lxl"
compileSdk = 36

defaultConfig {
applicationId = "com.google.sample.wsc.lxl"
minSdk = 24
targetSdk = 36
versionCode = 1
versionName = "1.0"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}

buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
}
buildFeatures {
compose = true
}
}

dependencies {

implementation(libs.androidx.core.ktx)
implementation(libs.androidx.lifecycle.runtime.ktx)
implementation(libs.androidx.activity.compose)
implementation(platform(libs.androidx.compose.bom))
implementation(libs.androidx.ui)
implementation(libs.androidx.ui.graphics)
implementation(libs.androidx.ui.tooling.preview)
implementation(libs.androidx.material3)
implementation(libs.androidx.material3.adaptive)
implementation(libs.androidx.material3.wsc)
implementation(libs.androidx.window)
implementation(libs.androidx.window.core)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
androidTestImplementation(platform(libs.androidx.compose.bom))
androidTestImplementation(libs.androidx.ui.test.junit4)
debugImplementation(libs.androidx.ui.tooling)
debugImplementation(libs.androidx.ui.test.manifest)
}
21 changes: 21 additions & 0 deletions WindowSizeClassSample/app/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.google.sample.wsc.lxl

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.google.sample.wsc.lxl", appContext.packageName)
}
}
23 changes: 23 additions & 0 deletions WindowSizeClassSample/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.WindowSizeClassSample">
<activity
android:name=".MainActivity"
android:exported="true"
android:theme="@style/Theme.WindowSizeClassSample">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.google.sample.wsc.lxl

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Scaffold
import androidx.compose.ui.Modifier
import com.google.sample.wsc.lxl.ui.Content
import com.google.sample.wsc.lxl.ui.theme.WindowSizeClassSampleTheme

class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
WindowSizeClassSampleTheme {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
Content(
modifier = Modifier.padding(innerPadding)
)
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
package com.google.sample.wsc.lxl.ui

import androidx.activity.compose.LocalActivity
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.GridItemSpan
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.PreviewScreenSizes
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.google.sample.wsc.lxl.utils.Height
import com.google.sample.wsc.lxl.utils.Width
import com.google.sample.wsc.lxl.utils.calculateColumns
import com.google.sample.wsc.lxl.utils.calculateColumnsForTitles
import com.google.sample.wsc.lxl.utils.material
import com.google.sample.wsc.lxl.utils.windowManager

@PreviewScreenSizes
@Composable
fun Content(modifier: Modifier = Modifier) {

val wm = LocalActivity.current?.windowManager() ?: return
val material = material()
val numberOfColumns = calculateColumns(wm.first)
val numberOfColumnsForTitles = calculateColumnsForTitles(wm.first)

LazyVerticalGrid(
columns = GridCells.Fixed(numberOfColumns), modifier = modifier.fillMaxSize()
) {
item(span = { GridItemSpan(numberOfColumnsForTitles) }) {
Title()
}
item(span = { GridItemSpan(numberOfColumnsForTitles) }) {
Subtitle("WindowManager")
}
item {
WidthComposable(width = wm.first)
}
item {
HeightComposable(height = wm.second)
}

if (numberOfColumns < 3) {
item(span = { GridItemSpan(numberOfColumnsForTitles) }) {
HorizontalDivider(
modifier = Modifier
.fillMaxSize()
.padding(vertical = 8.dp, horizontal = 24.dp),
thickness = 4.dp,
color = MaterialTheme.colorScheme.onPrimaryFixedVariant
)
}
}

item(span = { GridItemSpan(numberOfColumnsForTitles) }) {
Subtitle("Material")
}
item {
WidthComposable(material.first)
}
item {
HeightComposable(material.second)
}
}
}

@Composable
private fun Title() {
Text(
text = "WindowSizeClass Sample",
modifier = Modifier
.fillMaxSize()
.background(color = MaterialTheme.colorScheme.inverseOnSurface)
.padding(vertical = 16.dp),
style = MaterialTheme.typography.headlineLarge,
textAlign = TextAlign.Center
)
}

@Composable
private fun Subtitle(text: String) {
Text(
text = text,
modifier = Modifier
.fillMaxSize()
.background(color = MaterialTheme.colorScheme.onPrimaryContainer)
.padding(vertical = 16.dp),
color = MaterialTheme.colorScheme.onPrimary,
style = MaterialTheme.typography.headlineSmall,
textAlign = TextAlign.Center
)
}

@OptIn(ExperimentalMaterial3ExpressiveApi::class)
@Composable
private fun WidthComposable(width: Width) {
Column {
DimensionTitle(title = "Width")
Row(
modifier = Modifier
.fillMaxSize()
.padding(top = 4.dp),
horizontalArrangement = Arrangement.SpaceEvenly
) {
for (w in Width.entries) {
Indicator(label = w.label, isSelected = w == width)
}
}
}
}

@Composable
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
private fun DimensionTitle(title: String) {
Text(
text = title, modifier = Modifier
.fillMaxSize()
.background(color = MaterialTheme.colorScheme.tertiaryContainer)
.padding(vertical = 8.dp),
color = MaterialTheme.colorScheme.onTertiaryContainer,
style = MaterialTheme.typography.bodyMediumEmphasized,
textAlign = TextAlign.Center
)
}

@Composable
private fun RowScope.Indicator(label: String, isSelected: Boolean) {
val backgroundColor = if (isSelected) {
MaterialTheme.colorScheme.primaryContainer
} else {
MaterialTheme.colorScheme.secondaryContainer
}
val borderWidth = if (isSelected) {
2.dp
} else {
0.dp
}
val textColor = if (isSelected) {
MaterialTheme.colorScheme.onPrimaryContainer
} else {
MaterialTheme.colorScheme.onSecondaryContainer
}
Box(
modifier = Modifier
.padding(horizontal = 2.dp)
.weight(1f)
.height(200.dp)
.background(color = backgroundColor, shape = MaterialTheme.shapes.medium)
.border(
width = borderWidth,
color = MaterialTheme.colorScheme.onPrimaryContainer,
shape = MaterialTheme.shapes.medium
),
contentAlignment = Alignment.BottomCenter
) {
Text(
text = label,
color = textColor,
modifier = Modifier.padding(all = 4.dp),
fontSize = 12.sp
)
}
}

@Composable
private fun HeightComposable(height: Height) {
Column {
DimensionTitle(title = "Height")
Row(
modifier = Modifier
.fillMaxSize()
.padding(top = 4.dp),
horizontalArrangement = Arrangement.SpaceEvenly
) {
for (h in Height.entries) {
Indicator(label = h.label, isSelected = h == height)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.google.sample.wsc.lxl.ui.theme

import androidx.compose.ui.graphics.Color

val Purple80 = Color(0xFFD0BCFF)
val PurpleGrey80 = Color(0xFFCCC2DC)
val Pink80 = Color(0xFFEFB8C8)

val Purple40 = Color(0xFF6650a4)
val PurpleGrey40 = Color(0xFF625b71)
val Pink40 = Color(0xFF7D5260)
Loading