Merge "Frosted glass material test"

This commit is contained in:
Lucas Dupin
2020-09-01 18:28:20 +00:00
committed by Android (Google) Code Review
10 changed files with 502 additions and 0 deletions

View File

@@ -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",
],
}

View File

@@ -39,5 +39,8 @@
<activity android:name=".hdr.GlowActivity"
android:label="Glow Examples"/>
<activity android:name=".materials.GlassActivity"
android:label="Glass Examples"/>
</application>
</manifest>

Binary file not shown.

After

Width:  |  Height:  |  Size: 196 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 311 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 483 KiB

View File

@@ -0,0 +1,246 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
** Copyright 2012, 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.
-->
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ImageView
android:id="@+id/background"
android:layout_width="0dp"
android:layout_height="0dp"
android:scaleType="matrix"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:srcCompat="@drawable/background1" />
<com.android.test.silkfx.materials.GlassView
android:id="@+id/materialView"
android:layout_width="0dp"
android:layout_height="180dp"
android:layout_marginEnd="64dp"
android:layout_marginStart="64dp"
app:layout_constraintBottom_toTopOf="@+id/bottomPanel"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/bottomPanel"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="?android:attr/colorBackground"
android:paddingTop="24dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent">
<SeekBar
android:id="@+id/materialOpacity"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:layout_marginBottom="16dp"
android:max="100"
android:progress="12"
app:layout_constraintBottom_toTopOf="@+id/scrimOpacityTitle"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent" />
<SeekBar
android:id="@+id/blurRadius"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:layout_marginEnd="12dp"
android:layout_marginStart="12dp"
android:max="150"
android:progress="50"
app:layout_constraintBottom_toTopOf="@+id/materialOpacityTitle"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent" />
<SeekBar
android:id="@+id/scrimOpacity"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:layout_marginBottom="16dp"
android:max="100"
android:progress="50"
app:layout_constraintBottom_toTopOf="@+id/noiseOpacityTitle"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent" />
<SeekBar
android:id="@+id/noiseOpacity"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:layout_marginBottom="24dp"
android:max="100"
android:progress="5"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/scrimOpacityTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginBottom="8dp"
android:text="Scrim Opacity"
android:textColor="@android:color/white"
app:layout_constraintBottom_toTopOf="@+id/scrimOpacity"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/materialOpacityTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginBottom="8dp"
android:text="Material Opacity"
android:textColor="@android:color/white"
app:layout_constraintBottom_toTopOf="@+id/materialOpacity"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/blurRadiusTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginBottom="8dp"
android:text="Blur Radius"
android:textColor="@android:color/white"
app:layout_constraintBottom_toTopOf="@+id/blurRadius"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/noiseOpacityTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginBottom="8dp"
android:textColor="@android:color/white"
android:text="Noise Opacity"
app:layout_constraintBottom_toTopOf="@+id/noiseOpacity"
app:layout_constraintStart_toStartOf="parent" />
<ImageView
android:id="@+id/background1"
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_marginStart="24dp"
android:layout_marginBottom="16dp"
android:foreground="?android:attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:onClick="onBackgroundClick"
android:scaleType="centerCrop"
app:layout_constraintBottom_toTopOf="@+id/lightMaterialSwitch"
app:layout_constraintStart_toStartOf="parent"
android:src="@drawable/background1" />
<ImageView
android:id="@+id/background2"
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_marginStart="8dp"
android:foreground="?android:attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:onClick="onBackgroundClick"
android:scaleType="centerCrop"
app:layout_constraintBottom_toBottomOf="@+id/background1"
app:layout_constraintStart_toEndOf="@+id/background1"
android:src="@drawable/background2" />
<ImageView
android:id="@+id/background3"
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_marginStart="8dp"
android:scaleType="centerCrop"
android:foreground="?android:attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:onClick="onBackgroundClick"
app:layout_constraintBottom_toBottomOf="@+id/background1"
app:layout_constraintStart_toEndOf="@+id/background2"
android:src="@drawable/background3" />
<Switch
android:id="@+id/lightMaterialSwitch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginBottom="8dp"
android:text="Light Material"
app:layout_constraintBottom_toTopOf="@+id/blurRadiusTitle"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/blurRadiusValue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
android:layout_marginLeft="8dp"
app:layout_constraintBottom_toBottomOf="@+id/blurRadiusTitle"
app:layout_constraintStart_toEndOf="@+id/blurRadiusTitle" />
<TextView
android:id="@+id/materialOpacityValue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
android:layout_marginLeft="8dp"
app:layout_constraintBottom_toBottomOf="@+id/materialOpacityTitle"
app:layout_constraintStart_toEndOf="@+id/materialOpacityTitle" />
<TextView
android:id="@+id/noiseOpacityValue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
android:layout_marginLeft="8dp"
app:layout_constraintBottom_toBottomOf="@+id/noiseOpacityTitle"
app:layout_constraintStart_toEndOf="@+id/noiseOpacityTitle" />
<TextView
android:id="@+id/scrimOpacityValue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
android:layout_marginLeft="8dp"
app:layout_constraintBottom_toBottomOf="@+id/scrimOpacityTitle"
app:layout_constraintStart_toEndOf="@+id/scrimOpacityTitle" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -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)
))
)

View File

@@ -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
}
}

View File

@@ -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)
}
}