diff --git a/tests/SilkFX/Android.bp b/tests/SilkFX/Android.bp index ca0a091e65bbe..92e3efa7fd55a 100644 --- a/tests/SilkFX/Android.bp +++ b/tests/SilkFX/Android.bp @@ -19,4 +19,10 @@ android_test { srcs: ["**/*.java", "**/*.kt"], platform_apis: true, certificate: "platform", + static_libs: [ + "androidx.core_core", + "androidx.appcompat_appcompat", + "com.google.android.material_material", + "androidx-constraintlayout_constraintlayout", + ], } diff --git a/tests/SilkFX/AndroidManifest.xml b/tests/SilkFX/AndroidManifest.xml index ca9550a9eeab0..050e9c33aeac9 100644 --- a/tests/SilkFX/AndroidManifest.xml +++ b/tests/SilkFX/AndroidManifest.xml @@ -39,5 +39,8 @@ + + diff --git a/tests/SilkFX/res/drawable-hdpi/background1.jpeg b/tests/SilkFX/res/drawable-hdpi/background1.jpeg new file mode 100644 index 0000000000000..dcdfa7b850bc4 Binary files /dev/null and b/tests/SilkFX/res/drawable-hdpi/background1.jpeg differ diff --git a/tests/SilkFX/res/drawable-hdpi/background2.jpeg b/tests/SilkFX/res/drawable-hdpi/background2.jpeg new file mode 100644 index 0000000000000..dc7ce84e6784f Binary files /dev/null and b/tests/SilkFX/res/drawable-hdpi/background2.jpeg differ diff --git a/tests/SilkFX/res/drawable-hdpi/background3.jpeg b/tests/SilkFX/res/drawable-hdpi/background3.jpeg new file mode 100644 index 0000000000000..12b3429e39209 Binary files /dev/null and b/tests/SilkFX/res/drawable-hdpi/background3.jpeg differ diff --git a/tests/SilkFX/res/drawable-hdpi/noise.png b/tests/SilkFX/res/drawable-hdpi/noise.png new file mode 100644 index 0000000000000..053995dad7602 Binary files /dev/null and b/tests/SilkFX/res/drawable-hdpi/noise.png differ diff --git a/tests/SilkFX/res/layout/activity_glass.xml b/tests/SilkFX/res/layout/activity_glass.xml new file mode 100644 index 0000000000000..85dab9315197a --- /dev/null +++ b/tests/SilkFX/res/layout/activity_glass.xml @@ -0,0 +1,246 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/SilkFX/src/com/android/test/silkfx/Main.kt b/tests/SilkFX/src/com/android/test/silkfx/Main.kt index 76e62a6c8cff0..9ed8d2f5edf7d 100644 --- a/tests/SilkFX/src/com/android/test/silkfx/Main.kt +++ b/tests/SilkFX/src/com/android/test/silkfx/Main.kt @@ -29,6 +29,7 @@ import com.android.test.silkfx.app.CommonDemoActivity import com.android.test.silkfx.app.EXTRA_LAYOUT import com.android.test.silkfx.app.EXTRA_TITLE import com.android.test.silkfx.hdr.GlowActivity +import com.android.test.silkfx.materials.GlassActivity import kotlin.reflect.KClass class Demo(val name: String, val makeIntent: (Context) -> Intent) { @@ -48,6 +49,9 @@ private val AllDemos = listOf( DemoGroup("HDR", listOf( Demo("Glow", GlowActivity::class), Demo("Blingy Notifications", R.layout.bling_notifications) + )), + DemoGroup("Materials", listOf( + Demo("Glass", GlassActivity::class) )) ) diff --git a/tests/SilkFX/src/com/android/test/silkfx/materials/GlassActivity.kt b/tests/SilkFX/src/com/android/test/silkfx/materials/GlassActivity.kt new file mode 100644 index 0000000000000..6f5ddacb27331 --- /dev/null +++ b/tests/SilkFX/src/com/android/test/silkfx/materials/GlassActivity.kt @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.test.silkfx.materials + +import android.app.Activity +import android.graphics.Bitmap +import android.graphics.BitmapFactory +import android.graphics.Color +import android.os.Bundle +import android.util.TypedValue +import android.view.View +import android.widget.ImageView +import android.widget.SeekBar +import android.widget.Switch +import android.widget.TextView +import com.android.test.silkfx.R + +class GlassActivity : Activity(), SeekBar.OnSeekBarChangeListener { + + lateinit var backgroundButton1: ImageView + lateinit var backgroundButton2: ImageView + lateinit var backgroundButton3: ImageView + lateinit var backgroundView: ImageView + lateinit var materialView: GlassView + lateinit var lightMaterialSwitch: Switch + lateinit var noiseOpacitySeekBar: SeekBar + lateinit var materialOpacitySeekBar: SeekBar + lateinit var scrimOpacitySeekBar: SeekBar + lateinit var blurRadiusSeekBar: SeekBar + lateinit var noiseOpacityValue: TextView + lateinit var materialOpacityValue: TextView + lateinit var scrimOpacityValue: TextView + lateinit var blurRadiusValue: TextView + + lateinit var background: Bitmap + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_glass) + backgroundButton1 = requireViewById(R.id.background1) + backgroundButton2 = requireViewById(R.id.background2) + backgroundButton3 = requireViewById(R.id.background3) + backgroundView = requireViewById(R.id.background) + lightMaterialSwitch = requireViewById(R.id.lightMaterialSwitch) + materialView = requireViewById(R.id.materialView) + materialOpacitySeekBar = requireViewById(R.id.materialOpacity) + blurRadiusSeekBar = requireViewById(R.id.blurRadius) + noiseOpacitySeekBar = requireViewById(R.id.noiseOpacity) + scrimOpacitySeekBar = requireViewById(R.id.scrimOpacity) + noiseOpacityValue = requireViewById(R.id.noiseOpacityValue) + materialOpacityValue = requireViewById(R.id.materialOpacityValue) + scrimOpacityValue = requireViewById(R.id.scrimOpacityValue) + blurRadiusValue = requireViewById(R.id.blurRadiusValue) + + background = BitmapFactory.decodeResource(resources, R.drawable.background1) + backgroundView.setImageBitmap(background) + materialView.backgroundBitmap = background + + blurRadiusSeekBar.setOnSeekBarChangeListener(this) + materialOpacitySeekBar.setOnSeekBarChangeListener(this) + noiseOpacitySeekBar.setOnSeekBarChangeListener(this) + scrimOpacitySeekBar.setOnSeekBarChangeListener(this) + + arrayOf(blurRadiusSeekBar, materialOpacitySeekBar, noiseOpacitySeekBar, + scrimOpacitySeekBar).forEach { + it.setOnSeekBarChangeListener(this) + onProgressChanged(it, it.progress, fromUser = false) + } + + lightMaterialSwitch.setOnCheckedChangeListener { _, isChecked -> + materialView.color = if (isChecked) Color.WHITE else Color.BLACK + } + } + + override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) { + when (seekBar) { + blurRadiusSeekBar -> { + materialView.blurRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, + progress.toFloat(), resources.displayMetrics) + blurRadiusValue.text = progress.toString() + } + materialOpacitySeekBar -> { + materialView.materialOpacity = progress / seekBar.max.toFloat() + materialOpacityValue.text = progress.toString() + } + noiseOpacitySeekBar -> { + materialView.noiseOpacity = progress / seekBar.max.toFloat() + noiseOpacityValue.text = progress.toString() + } + scrimOpacitySeekBar -> { + materialView.scrimOpacity = progress / seekBar.max.toFloat() + scrimOpacityValue.text = progress.toString() + } + else -> throw IllegalArgumentException("Unknown seek bar") + } + } + + override fun onStartTrackingTouch(seekBar: SeekBar?) {} + override fun onStopTrackingTouch(seekBar: SeekBar?) {} + + fun onBackgroundClick(view: View) { + val resource = when (view) { + backgroundButton1 -> R.drawable.background1 + backgroundButton2 -> R.drawable.background2 + backgroundButton3 -> R.drawable.background3 + else -> throw IllegalArgumentException("Invalid button") + } + + background = BitmapFactory.decodeResource(resources, resource) + backgroundView.setImageBitmap(background) + materialView.backgroundBitmap = background + } +} \ No newline at end of file diff --git a/tests/SilkFX/src/com/android/test/silkfx/materials/GlassView.kt b/tests/SilkFX/src/com/android/test/silkfx/materials/GlassView.kt new file mode 100644 index 0000000000000..e100959908c30 --- /dev/null +++ b/tests/SilkFX/src/com/android/test/silkfx/materials/GlassView.kt @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.test.silkfx.materials + +import android.content.Context +import android.graphics.Bitmap +import android.graphics.BitmapFactory +import android.graphics.BitmapShader +import android.graphics.BlendMode +import android.graphics.BlurShader +import android.graphics.Canvas +import android.graphics.Color +import android.graphics.Outline +import android.graphics.Paint +import android.graphics.Rect +import android.graphics.Shader +import android.util.AttributeSet +import android.view.View +import android.view.ViewOutlineProvider +import com.android.test.silkfx.R + +class GlassView(context: Context, attributeSet: AttributeSet) : View(context, attributeSet) { + + var noise = BitmapFactory.decodeResource(resources, R.drawable.noise) + var materialPaint = Paint() + var scrimPaint = Paint() + var noisePaint = Paint() + var blurPaint = Paint() + + val src = Rect() + val dst = Rect() + + var backgroundBitmap: Bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888) + set(value) { + field = value + invalidate() + } + + var noiseOpacity = 0.0f + set(value) { + field = value + noisePaint.alpha = (value * 255).toInt() + invalidate() + } + + var materialOpacity = 0.0f + set(value) { + field = value + materialPaint.alpha = (value * 255).toInt() + invalidate() + } + + var scrimOpacity = 0.5f + set(value) { + field = value + scrimPaint.alpha = (value * 255).toInt() + invalidate() + } + + var color = Color.BLACK + set(value) { + field = value + var alpha = materialPaint.alpha + materialPaint.color = color + materialPaint.alpha = alpha + + alpha = scrimPaint.alpha + scrimPaint.color = color + scrimPaint.alpha = alpha + invalidate() + } + + var blurRadius = 150f + set(value) { + field = value + blurPaint.shader = BlurShader(value, value, null) + invalidate() + } + + init { + materialPaint.blendMode = BlendMode.SOFT_LIGHT + noisePaint.blendMode = BlendMode.SOFT_LIGHT + noisePaint.shader = BitmapShader(noise, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT) + scrimPaint.alpha = (scrimOpacity * 255).toInt() + noisePaint.alpha = (noiseOpacity * 255).toInt() + materialPaint.alpha = (materialOpacity * 255).toInt() + blurPaint.shader = BlurShader(blurRadius, blurRadius, null) + outlineProvider = object : ViewOutlineProvider() { + override fun getOutline(view: View?, outline: Outline?) { + outline?.setRoundRect(Rect(0, 0, width, height), 100f) + } + } + clipToOutline = true + } + + override fun onDraw(canvas: Canvas?) { + src.set(left, top, right, bottom) + dst.set(0, 0, width, height) + canvas?.drawBitmap(backgroundBitmap, src, dst, blurPaint) + canvas?.drawRect(dst, materialPaint) + canvas?.drawRect(dst, noisePaint) + canvas?.drawRect(dst, scrimPaint) + } +} \ No newline at end of file