1 /* 2 * Copyright 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package androidx.graphics.shapes.test 18 19 import android.app.Activity 20 import android.graphics.Color 21 import android.graphics.Matrix 22 import android.os.Bundle 23 import android.view.View 24 import android.view.ViewGroup 25 import android.view.ViewGroup.LayoutParams 26 import android.widget.LinearLayout 27 import androidx.graphics.shapes.CornerRounding 28 import androidx.graphics.shapes.CornerRounding.Companion.Unrounded 29 import androidx.graphics.shapes.Morph 30 import androidx.graphics.shapes.RoundedPolygon 31 import androidx.graphics.shapes.circle 32 import androidx.graphics.shapes.pill 33 import androidx.graphics.shapes.pillStar 34 import androidx.graphics.shapes.rectangle 35 import androidx.graphics.shapes.star 36 import androidx.graphics.shapes.transformed 37 38 open class ShapeActivity : Activity() { 39 40 val shapes = mutableListOf<RoundedPolygon>() 41 42 lateinit var morphView: MorphView 43 44 lateinit var prevShape: RoundedPolygon 45 lateinit var currShape: RoundedPolygon 46 onCreatenull47 override fun onCreate(savedInstanceState: Bundle?) { 48 super.onCreate(savedInstanceState) 49 50 val container = LinearLayout(this) 51 container.layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT) 52 container.orientation = LinearLayout.VERTICAL 53 container.setBackgroundColor(Color.BLACK) 54 setContentView(container) 55 56 setupShapes() 57 58 addShapeViews(container) 59 60 setupMorphView() 61 container.addView(morphView) 62 } 63 setupMorphViewnull64 private fun setupMorphView() { 65 val morph = Morph(prevShape, currShape) 66 if (this::morphView.isInitialized) { 67 morphView.morph = morph 68 } else { 69 morphView = MorphView(this, morph) 70 } 71 } 72 getShapeViewnull73 private fun getShapeView(shape: RoundedPolygon, width: Int, height: Int): View { 74 val view = ShapeView(this, shape) 75 val layoutParams = LinearLayout.LayoutParams(width, height) 76 layoutParams.setMargins(5, 5, 5, 5) 77 view.layoutParams = layoutParams 78 // TODO: add click listener to show expanded version of shape at bottom of container 79 return view 80 } 81 setupShapesnull82 internal open fun setupShapes() { 83 // Note: all RoundedPolygon(4) shapes are placeholders for shapes not yet handled 84 val matrix1 = Matrix().apply { setRotate(-45f) } 85 val matrix2 = Matrix().apply { setRotate(45f) } 86 val blobR1 = MaterialShapes.blobR(.19f, .86f).transformed(matrix1) 87 val blobR2 = MaterialShapes.blobR(.19f, .86f).transformed(matrix2) 88 89 // "Circle" to DefaultShapes.star(4, 1f, 1f), 90 shapes.add(RoundedPolygon.circle()) 91 // "Squirrel" to DefaultShapes.fgSquircle(0.9f), 92 shapes.add(RoundedPolygon(4)) 93 // Square, using rectangle function 94 shapes.add(RoundedPolygon.rectangle(width = 2f, height = 2f)) 95 // "Scallop" to DefaultShapes.Scallop, 96 shapes.add(MaterialShapes.scallop()) 97 // "Clover" to DefaultShapes.Clover, 98 shapes.add(MaterialShapes.clover()) 99 100 // "Alice" to DefaultShapes.Alice, 101 shapes.add(MaterialShapes.alice()) 102 // Rectangle 103 shapes.add(RoundedPolygon.rectangle(width = 4f, height = 2f)) 104 // "Wiggle-Star" to DefaultShapes.WiggleStar, 105 shapes.add(MaterialShapes.wiggleStar()) 106 // "Wovel" to DefaultShapes.Wovel, 107 shapes.add(MaterialShapes.wovel()) 108 // "Blob Left" to DefaultShapes.BlobR.rotate(-TwoPI / 4), 109 shapes.add(blobR1) 110 111 // "Blob Right" to DefaultShapes.BlobR, 112 shapes.add(blobR2) 113 // "More" to DefaultShapes.More, 114 shapes.add(MaterialShapes.more()) 115 // Round Rect 116 shapes.add(RoundedPolygon.rectangle(width = 4f, height = 2f, rounding = CornerRounding(1f))) 117 // Round Rect (smoothed) 118 shapes.add( 119 RoundedPolygon.rectangle(width = 4f, height = 2f, rounding = CornerRounding(1f, .5f)) 120 ) 121 // Round Rect (smoothed more) 122 shapes.add( 123 RoundedPolygon.rectangle(width = 4f, height = 2f, rounding = CornerRounding(1f, 1f)) 124 ) 125 126 // "CornerSW" to DefaultShapes.CornerSE.rotate(TwoPI / 4), 127 shapes.add(RoundedPolygon(4)) 128 // "CornerSE" to DefaultShapes.CornerSE, 129 shapes.add(MaterialShapes.cornerSouthEast(.4f)) 130 // "Quarty" to DefaultShapes.Quarty, 131 shapes.add(MaterialShapes.quarty(.3f, smooth = .5f)) 132 // "5D Cube" to DefaultShapes.Cube5D, 133 shapes.add(MaterialShapes.cube5D()) 134 // "Pentagon" to DefaultShapes.Pentagon 135 shapes.add(MaterialShapes.pentagon()) 136 137 // Some non-Material shapes 138 139 val rounding = CornerRounding(.1f, .5f) 140 val starRounding = CornerRounding(.05f, .25f) 141 shapes.add(RoundedPolygon(numVertices = 4, rounding = rounding)) 142 shapes.add(RoundedPolygon.star(8, radius = 1f, innerRadius = .4f, rounding = starRounding)) 143 shapes.add( 144 RoundedPolygon.star( 145 8, 146 radius = 1f, 147 innerRadius = .4f, 148 rounding = starRounding, 149 innerRounding = CornerRounding.Unrounded 150 ) 151 ) 152 shapes.add( 153 MaterialShapes.clover(rounding = .352f, innerRadius = .1f, innerRounding = Unrounded) 154 ) 155 shapes.add(RoundedPolygon(3)) 156 157 // Pills 158 shapes.add(RoundedPolygon.pill()) 159 shapes.add(RoundedPolygon.pill(15f, 1f)) 160 shapes.add(RoundedPolygon.pillStar()) 161 shapes.add( 162 RoundedPolygon.pillStar(numVerticesPerRadius = 10, rounding = CornerRounding(.5f)) 163 ) 164 shapes.add( 165 RoundedPolygon.pillStar( 166 numVerticesPerRadius = 10, 167 rounding = CornerRounding(.5f), 168 innerRadiusRatio = .5f, 169 innerRounding = CornerRounding(.2f) 170 ) 171 ) 172 173 prevShape = shapes[0] 174 currShape = shapes[0] 175 } 176 addShapeViewsnull177 private fun addShapeViews(container: ViewGroup) { 178 val WIDTH = 170 179 val HEIGHT = 170 180 181 var shapeIndex = 0 182 var row: LinearLayout? = null 183 while (shapeIndex < shapes.size) { 184 if (shapeIndex % 6 == 0) { 185 row = LinearLayout(this) 186 val layoutParams = 187 LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT) 188 row.layoutParams = layoutParams 189 row.orientation = LinearLayout.HORIZONTAL 190 container.addView(row) 191 } 192 val shape = shapes[shapeIndex] 193 val shapeView = getShapeView(shape, WIDTH, HEIGHT) 194 row!!.addView(shapeView) 195 shapeView.setOnClickListener { 196 prevShape = currShape 197 currShape = shape 198 setupMorphView() 199 } 200 ++shapeIndex 201 } 202 } 203 } 204