@@ -11,9 +11,11 @@ import androidx.compose.foundation.Canvas
11
11
import androidx.compose.foundation.Image
12
12
import androidx.compose.foundation.background
13
13
import androidx.compose.foundation.border
14
+ import androidx.compose.foundation.clickable
14
15
import androidx.compose.foundation.layout.Arrangement
15
16
import androidx.compose.foundation.layout.Box
16
17
import androidx.compose.foundation.layout.Column
18
+ import androidx.compose.foundation.layout.PaddingValues
17
19
import androidx.compose.foundation.layout.Spacer
18
20
import androidx.compose.foundation.layout.aspectRatio
19
21
import androidx.compose.foundation.layout.fillMaxSize
@@ -22,21 +24,22 @@ import androidx.compose.foundation.layout.height
22
24
import androidx.compose.foundation.layout.padding
23
25
import androidx.compose.foundation.layout.width
24
26
import androidx.compose.foundation.lazy.LazyColumn
27
+ import androidx.compose.foundation.lazy.LazyRow
28
+ import androidx.compose.foundation.lazy.rememberLazyListState
25
29
import androidx.compose.foundation.rememberScrollState
26
30
import androidx.compose.foundation.shape.RoundedCornerShape
27
31
import androidx.compose.foundation.verticalScroll
28
32
import androidx.compose.material3.Slider
29
33
import androidx.compose.material3.Text
30
34
import androidx.compose.runtime.Composable
31
- import androidx.compose.runtime.LaunchedEffect
32
35
import androidx.compose.runtime.getValue
33
36
import androidx.compose.runtime.mutableFloatStateOf
34
- import androidx.compose.runtime.mutableIntStateOf
35
37
import androidx.compose.runtime.remember
36
38
import androidx.compose.runtime.setValue
37
39
import androidx.compose.ui.Alignment
38
40
import androidx.compose.ui.Modifier
39
41
import androidx.compose.ui.draw.clipToBounds
42
+ import androidx.compose.ui.draw.drawWithCache
40
43
import androidx.compose.ui.draw.drawWithContent
41
44
import androidx.compose.ui.geometry.Offset
42
45
import androidx.compose.ui.graphics.Brush
@@ -59,15 +62,16 @@ import androidx.compose.ui.platform.LocalDensity
59
62
import androidx.compose.ui.res.imageResource
60
63
import androidx.compose.ui.res.painterResource
61
64
import androidx.compose.ui.tooling.preview.Preview
65
+ import androidx.compose.ui.unit.Dp
62
66
import androidx.compose.ui.unit.IntSize
63
67
import androidx.compose.ui.unit.dp
68
+ import androidx.compose.ui.unit.roundToIntSize
64
69
import androidx.compose.ui.unit.sp
65
70
import com.smarttoolfactory.tutorial1_1basics.R
66
71
import com.smarttoolfactory.tutorial1_1basics.ui.backgroundColor
67
72
import com.smarttoolfactory.tutorial1_1basics.ui.components.StyleableTutorialText
68
73
import com.smarttoolfactory.tutorial1_1basics.ui.components.TutorialHeader
69
74
import com.smarttoolfactory.tutorial1_1basics.ui.components.TutorialText2
70
- import kotlinx.coroutines.delay
71
75
import org.intellij.lang.annotations.Language
72
76
import kotlin.math.roundToInt
73
77
@@ -77,7 +81,6 @@ fun Tutorial6_40Screen2() {
77
81
TutorialContent ()
78
82
}
79
83
80
-
81
84
@Composable
82
85
private fun TutorialContent () {
83
86
Column (modifier = Modifier .padding(8 .dp)) {
@@ -507,19 +510,11 @@ fun RenderNodeSample() {
507
510
508
511
val graphicsLayer = rememberGraphicsLayer()
509
512
510
- var counter by remember {
511
- mutableIntStateOf(0 )
512
- }
513
-
514
- LaunchedEffect (Unit ) {
515
- while (true ) {
516
- delay(60 )
517
- counter++
518
- }
519
- }
513
+ val state = rememberLazyListState()
520
514
521
515
Box {
522
516
LazyColumn (
517
+ state = state,
523
518
modifier = Modifier
524
519
.background(backgroundColor)
525
520
.fillMaxSize()
@@ -536,20 +531,6 @@ fun RenderNodeSample() {
536
531
) {
537
532
this @drawWithContent.drawContent()
538
533
}
539
-
540
- // val recordingCanvas = contentNode.beginRecording()
541
- // canvasHolder.drawInto(recordingCanvas) {
542
- // drawContext.also {
543
- // it.layoutDirection = layoutDirection
544
- // it.size = size
545
- // it.canvas = this
546
- // }
547
-
548
- // drawLayer(graphicsLayer)
549
- // }
550
- //
551
- // contentNode.endRecording()
552
-
553
534
},
554
535
verticalArrangement = Arrangement .spacedBy(8 .dp)
555
536
) {
@@ -600,8 +581,6 @@ fun RenderNodeSample() {
600
581
)
601
582
)
602
583
603
- println (" Drawing...$counter " )
604
-
605
584
drawIntoCanvas { canvas: Canvas ->
606
585
val recordingCanvas = contentNode.beginRecording()
607
586
canvasHolder.drawInto(recordingCanvas) {
@@ -626,4 +605,165 @@ fun RenderNodeSample() {
626
605
)
627
606
}
628
607
}
608
+ }
609
+
610
+ fun Modifier.frostedGlass (height : Dp ) = this .then(
611
+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .S ) {
612
+ Modifier .drawWithCache {
613
+ val topBarHeightPx = height.toPx()
614
+
615
+ val blurLayer = obtainGraphicsLayer().apply {
616
+ renderEffect = RenderEffect
617
+ .createBlurEffect(16f , 16f , Shader .TileMode .DECAL )
618
+ .asComposeRenderEffect()
619
+ }
620
+
621
+ onDrawWithContent {
622
+ blurLayer.record(size.copy(height = topBarHeightPx).roundToIntSize()) {
623
+ this @onDrawWithContent.drawContent()
624
+ }
625
+
626
+ drawLayer(blurLayer)
627
+ clipRect(top = topBarHeightPx) {
628
+ this @onDrawWithContent.drawContent()
629
+ }
630
+ }
631
+ }
632
+ } else {
633
+ Modifier
634
+ }
635
+ )
636
+
637
+ @RequiresApi(Build .VERSION_CODES .TIRAMISU )
638
+ @Preview(showBackground = true )
639
+ @Composable
640
+ fun PartialBlurTest () {
641
+
642
+ val scrollState = rememberLazyListState()
643
+ val topBarHeight = 180 .dp
644
+
645
+ LazyColumn (
646
+ state = scrollState,
647
+ modifier = Modifier
648
+ .fillMaxSize()
649
+ .frostedGlass(height = topBarHeight),
650
+ verticalArrangement = Arrangement .spacedBy(8 .dp)
651
+ ) {
652
+
653
+ item {
654
+ Spacer (modifier = Modifier .height(topBarHeight))
655
+ }
656
+
657
+ item {
658
+ LazyRow (
659
+ modifier = Modifier .fillMaxWidth().aspectRatio(2f ),
660
+ contentPadding = PaddingValues (horizontal = 16 .dp),
661
+ horizontalArrangement = Arrangement .spacedBy(8 .dp)
662
+ ) {
663
+ items(5 ) {
664
+ Image (
665
+ modifier = Modifier
666
+ .fillParentMaxWidth()
667
+ .aspectRatio(2f ),
668
+ contentScale = ContentScale .Crop ,
669
+ painter = painterResource(R .drawable.landscape11), contentDescription = null
670
+ )
671
+ }
672
+ }
673
+ }
674
+ items(100 ) {
675
+ if (it == 5 ) {
676
+ Image (
677
+ modifier = Modifier
678
+ .fillMaxWidth()
679
+ .aspectRatio(.5f ),
680
+ painter = painterResource(R .drawable.landscape11),
681
+ contentScale = ContentScale .Crop ,
682
+ contentDescription = null
683
+ )
684
+ } else {
685
+ Box (
686
+ modifier = Modifier
687
+ .clickable {
688
+
689
+ }
690
+ .fillMaxWidth()
691
+ .background(Color .White , RoundedCornerShape (16 .dp))
692
+ .padding(16 .dp)
693
+ ) {
694
+ Text (" Row $it " , fontSize = 22 .sp)
695
+ }
696
+ }
697
+ }
698
+ }
699
+ }
700
+
701
+
702
+ @Language(" GLSL" )
703
+ val CheapFrostedGlassTopBarAGSL =
704
+ """
705
+ const vec4 white = vec4(1.0);
706
+
707
+ uniform shader inputShader;
708
+ uniform float barHeight;
709
+
710
+ vec4 main(vec2 coord) {
711
+ if (coord.y > barHeight) {
712
+ return inputShader.eval(coord);
713
+ } else {
714
+ vec2 factor = vec2(3.0);
715
+
716
+ vec4 color = vec4(0.0);
717
+ color += inputShader.eval(coord - 3.0 * factor) * 0.0540540541;
718
+ color += inputShader.eval(coord - 2.0 * factor) * 0.1216216216;
719
+ color += inputShader.eval(coord - factor) * 0.1945945946;
720
+ color += inputShader.eval(coord) * 0.2270270270;
721
+ color += inputShader.eval(coord + factor) * 0.1945945946;
722
+ color += inputShader.eval(coord + 2.0 * factor) * 0.1216216216;
723
+ color += inputShader.eval(coord + 3.0 * factor) * 0.0540540541;
724
+
725
+ return mix(color, white, 0.7);
726
+ }
727
+ }
728
+ """ .trimIndent()
729
+
730
+ val TopAppBarHeight = 180 .dp
731
+
732
+ @RequiresApi(Build .VERSION_CODES .TIRAMISU )
733
+ @Preview(showBackground = true )
734
+ @Composable
735
+ fun FrostedGlassTopBarTest () {
736
+ LazyColumn (
737
+ modifier = Modifier
738
+ .fillMaxSize()
739
+ .graphicsLayer {
740
+ val shader = RuntimeShader (CheapFrostedGlassTopBarAGSL )
741
+ shader.setFloatUniform(" barHeight" , TopAppBarHeight .toPx())
742
+ val androidRenderEffect = android.graphics.RenderEffect
743
+ .createRuntimeShaderEffect(shader, " inputShader" )
744
+ renderEffect = androidRenderEffect.asComposeRenderEffect()
745
+ }
746
+ ) {
747
+ items(100 ) {
748
+ if (it == 5 ) {
749
+ Image (
750
+ modifier = Modifier
751
+ .fillMaxWidth()
752
+ .aspectRatio(2f ),
753
+ painter = painterResource(R .drawable.landscape11),
754
+ contentScale = ContentScale .Crop ,
755
+ contentDescription = null
756
+ )
757
+ } else {
758
+ Box (
759
+ modifier = Modifier
760
+ .fillMaxWidth()
761
+ .background(Color .White , RoundedCornerShape (16 .dp))
762
+ .padding(16 .dp)
763
+ ) {
764
+ Text (" Row $it " , fontSize = 22 .sp)
765
+ }
766
+ }
767
+ }
768
+ }
629
769
}
0 commit comments