Ağ geçişleri, 2D bir yama ızgarası kullanarak karmaşık, çok yönlü renk geçişleri oluşturur. Doğrusal veya dairesel renk geçişlerinin aksine, ağ renk geçişleri, renkleri 2D bir ızgara üzerinde sorunsuz bir şekilde birleştirir. Kullanıcı arayüzünüzde akıcı, organik veya çok noktalı arka planlar oluştururken birden fazla radialGradient veya linearGradient fırçayı üst üste koymak yerine ağ geçişleri kullanın.
Temel kavramlar
Örgü geçişi oluşturmak için ızgara boyutlarını, köşeleri ve noktalar arasındaki renk geçişlerini tanımlayın:
- Izgara boyutları: Ağ, dikey ve yatay eksenler boyunca parçalara bölünür.
rowsvecolumnsboyutundaki bir ızgara, (satır+1)×(sütun+1) köşe içerir. Örneğin, 1×1'lik bir ağ, bir yama oluşturan 4 köşeden oluşur. - Normalleştirilmiş koordinatlar: Tüm köşe konumları, çizim sınırlarının sol üst kısmını
(0f, 0f)ve sağ alt kısmını(1f, 1f)değerinin temsil ettiği normalleştirilmiş bir koordinat sistemi kullanır. - Bezier kontrol noktaları (teğetler): Her köşe, en fazla dört isteğe bağlı bezier kontrol noktası içerir. Bu teğetler, komşu köşeler arasındaki kenar eğriliğini belirtir.
Offset.Unspecifiedkullanırsanız Compose, yamalar arasında sorunsuz geçişler sağlamak için teğetleri tahmin eder. Her bir ızgara hücresi, kontrol noktalarıyla birlikte 4 köşeden oluşur ve bir Bezier parçası oluşturur. - Renk interpolasyonu: Çerçeve, ana köşeler arasındaki renkleri hesaplar. Daha yumuşak renk geçişleri için
hasBicubicColordeğerinitrueolarak ayarlayarak Catmull-Rom enterpolasyonunu,falseolarak ayarlayarak bilineer enterpolasyonu kullanın.
MeshGradientPainter ile çizim yapma
Jetpack Compose'da, ağ geçişi oluşturmak için MeshGradientPainter kullanın. MeshGradientPainter, tuval üzerine çizim yapar.
Basit bir ağ geçişi oluşturma
Temel bir statik ağ gradyanı oluşturmak için boyutlarını belirterek ve yapılandırma bloğundaki setVertex işlevini kullanarak köşe noktalarınızı konumlandırıp renkler atayarak bir MeshGradientPainter başlatın.
val rows = 1 val columns = 1 val gradientPainter = remember { MeshGradientPainter(rows, columns) { // Parameters: row, column, position, color setVertex(0, 0, Offset(0f, 0f), Color.Red) // Top-Left setVertex(0, 1, Offset(1f, 0f), Color.Blue) // Top-Right setVertex(1, 0, Offset(0f, 1f), Color.Green) // Bottom-Left setVertex(1, 1, Offset(1f, 1f), Color.Yellow) // Bottom-Right } } Box( modifier = modifier .aspectRatio(16/9f) .fillMaxWidth() .paint(gradientPainter) )
Belirli Bezier kontrol noktalarını kullanma
Varsayılan olarak, ağ oluşturucu, ızgara geçişlerini sorunsuz tutmak için karmaşık hesaplamaları gerçekleştirir. Ancak belirli renk bölümlerini seçerek itmek, çekmek veya keskin bir şekilde sıkıştırmak istiyorsanız herhangi bir tepe noktasındaki teğetleri açıkça özelleştirebilirsiniz.
Kontrol ofsetleri, ana tepe noktasının konumuna göre ölçülür.
val customTangentPainter = remember { MeshGradientPainter(rows = 1, columns = 1) { // Tweak the top-left vertex to curve outwards to the right and bottom setVertex( row = 0, column = 0, position = Offset(0f, 0f), color = Color.Magenta, rightControlPoint = Offset(0.4f, 0.1f), bottomControlPoint = Offset(0.1f, 0.4f) ) // Other points can remain unspecified to use default inferred fallback tangents setVertex(0, 1, Offset(1f, 0f), Color.Cyan) setVertex(1, 0, Offset(0f, 1f), Color.Blue) setVertex(1, 1, Offset(1f, 1f), Color.Black) } } Box( modifier = modifier .aspectRatio(16/9f) .fillMaxWidth() .paint(customTangentPainter) )
Gelişmiş ızgaralar oluşturma
Bu örnekte, 3'e 3'lük bir ızgara gösterilmektedir. Bu, belirtilmesi gereken 16 nokta olduğu ve orta noktaların farklı ofsetlerle ayarlandığı anlamına gelir:
val points = remember { listOf( Offset(0.0f, 0.0f), Offset(0.3f, 0.0f), Offset(0.7f, 0.0f), Offset(1.0f, 0.0f), Offset(0.0f, 0.3f), Offset(0.2f, 0.4f), Offset(0.7f, 0.2f), Offset(1.0f, 0.3f), Offset(0.0f, 0.7f), Offset(0.3f, 0.8f), Offset(0.7f, 0.6f), Offset(1.0f, 0.7f), Offset(0.0f, 1.0f), Offset(0.3f, 1.0f), Offset(0.7f, 1.0f), Offset(1.0f, 1.0f) ) } val gradientPainter = remember { MeshGradientPainter(rows = 3, columns = 3) { // Row 0 setVertex(0, 0, points[0], yellow) setVertex(0, 1, points[1], orange) setVertex(0, 2, points[2], yellow) setVertex(0, 3, points[3], purple) // Row 1 setVertex(1, 0, points[4], pink) setVertex(1, 1, points[5], yellow) setVertex(1, 2, points[6], pink) setVertex(1, 3, points[7], purple) // Row 2 setVertex(2, 0, points[8], indigo) setVertex(2, 1, points[9], pink) setVertex(2, 2, points[10], purple) setVertex(2, 3, points[11], indigo) // Row 3 setVertex(3, 0, points[12], purple) setVertex(3, 1, points[13], indigo) setVertex(3, 2, points[14], pink) setVertex(3, 3, points[15], yellow) } } Box( modifier = modifier.padding(32.dp) .aspectRatio(16 / 9f) .fillMaxWidth() .paint(gradientPainter) // ... )
Örgü geçişini canlandırma
MeshGradientPainter işlevinin block lambda parametresi bir DrawScope içinde yürütüldüğünden, değişebilir durumu okuyabilir ve gözlemleyebilir. Gölgelendiricileri veya bitmap'leri yeniden tahsis etmeden konumları ya da renkleri zaman içinde canlandırabilirsiniz.
val infiniteTransition = rememberInfiniteTransition(label = "meshMovement") val animatedOffset by infiniteTransition.animateFloat( initialValue = -0.1f, targetValue = 0.1f, animationSpec = infiniteRepeatable( animation = tween(2500, easing = LinearEasing), repeatMode = RepeatMode.Reverse ), label = "offset" ) val coral = Color(255, 90, 90) val peach = Color(255, 139, 90) val amber = Color(255, 169, 90) val sunshine = Color(255, 212, 90) val indigo = Color(0xFF5856D6) val pink = Color(0xFFFF2D55) val gradientPainter = remember { MeshGradientPainter(rows = 3, columns = 3) { // Row 0 setVertex(0, 0, Offset(0.0f, 0.0f), indigo) setVertex(0, 1, Offset(0.3f, 0.0f), peach) setVertex(0, 2, Offset(0.7f, 0.0f), amber) setVertex(0, 3, Offset(1.0f, 0.0f), sunshine) // Row 1 setVertex(1, 0, Offset(0.0f, 0.3f), pink) setVertex(1, 1, Offset(0.2f, 0.4f) + Offset(animatedOffset, animatedOffset), coral) setVertex(1, 2, Offset(0.7f, 0.2f) + Offset(animatedOffset, animatedOffset), peach) setVertex(1, 3, Offset(1.0f, 0.3f), indigo) // Row 2 setVertex(2, 0, Offset(0.0f, 0.7f), coral) setVertex(2, 1, Offset(0.3f, 0.8f) + Offset(animatedOffset, 0f), pink) setVertex(2, 2, Offset(0.7f, 0.6f) + Offset(animatedOffset, 0f), sunshine) setVertex(2, 3, Offset(1.0f, 0.7f), amber) // Row 3 setVertex(3, 0, Offset(0.0f, 1.0f), sunshine) setVertex(3, 1, Offset(0.3f, 1.0f), amber) setVertex(3, 2, Offset(0.7f, 1.0f), pink) setVertex(3, 3, Offset(1.0f, 1.0f), indigo) } } Box( modifier = modifier.padding(32.dp) .safeContentPadding() .aspectRatio(16 / 9f) .fillMaxWidth() .paint(gradientPainter) )