mirror of
https://gitlab.futo.org/videostreaming/grayjay.git
synced 2025-08-04 15:19:48 +00:00
Added something more similar to Jdenticons.
This commit is contained in:
parent
e88c649578
commit
95785e6c78
3 changed files with 403 additions and 64 deletions
|
@ -1,32 +1,30 @@
|
||||||
package com.futo.platformplayer.views
|
package com.futo.platformplayer.views
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.graphics.Bitmap
|
||||||
import android.graphics.Canvas
|
import android.graphics.Canvas
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.graphics.Paint
|
import android.graphics.Paint
|
||||||
import android.graphics.Path
|
import android.graphics.Path
|
||||||
|
import android.graphics.PointF
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import java.security.MessageDigest
|
import java.security.MessageDigest
|
||||||
|
import kotlin.math.max
|
||||||
|
import kotlin.math.min
|
||||||
|
|
||||||
class IdenticonView(context: Context, attrs: AttributeSet) : View(context, attrs) {
|
class IdenticonView(context: Context, attrs: AttributeSet) : View(context, attrs) {
|
||||||
var hashString: String = "default"
|
var hashString: String = "default"
|
||||||
set(value) {
|
set(value) {
|
||||||
field = value
|
field = value
|
||||||
hash = md5(value)
|
hash = md5(value)
|
||||||
|
iconGenerator = null
|
||||||
invalidate()
|
invalidate()
|
||||||
}
|
}
|
||||||
|
|
||||||
private var hash = ByteArray(16)
|
private var hash = ByteArray(16)
|
||||||
|
private var iconGenerator: IconGenerator? = null
|
||||||
private val path = Path()
|
private val path = Path()
|
||||||
private val paint = Paint().apply {
|
|
||||||
style = Paint.Style.FILL
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
hashString = "default"
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDraw(canvas: Canvas) {
|
override fun onDraw(canvas: Canvas) {
|
||||||
super.onDraw(canvas)
|
super.onDraw(canvas)
|
||||||
|
@ -39,16 +37,11 @@ class IdenticonView(context: Context, attrs: AttributeSet) : View(context, attrs
|
||||||
|
|
||||||
canvas.clipPath(clipPath)
|
canvas.clipPath(clipPath)
|
||||||
|
|
||||||
val size = width.coerceAtMost(height) / 5
|
if (iconGenerator == null) {
|
||||||
val colors = generateColorsFromHash(hash)
|
iconGenerator = IconGenerator(min(height, width).toFloat(), hash)
|
||||||
|
}
|
||||||
|
|
||||||
for (x in 0 until 5) {
|
iconGenerator?.render(canvas)
|
||||||
for (y in 0 until 5) {
|
|
||||||
val shapeIndex = getShapeIndex(x, y, hash)
|
|
||||||
paint.color = colors[shapeIndex % colors.size]
|
|
||||||
drawShape(canvas, x, y, size, shapeIndex)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun md5(input: String): ByteArray {
|
private fun md5(input: String): ByteArray {
|
||||||
|
@ -56,62 +49,408 @@ class IdenticonView(context: Context, attrs: AttributeSet) : View(context, attrs
|
||||||
return md.digest(input.toByteArray(Charsets.UTF_8))
|
return md.digest(input.toByteArray(Charsets.UTF_8))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateColorsFromHash(hash: ByteArray): List<Int> {
|
interface Shape {
|
||||||
val hue = hash[0].toFloat() / 255f
|
fun draw(canvas: Canvas, size: Float, index: Int, paint: Paint)
|
||||||
return listOf(
|
}
|
||||||
adjustColor(hue, 0.5f, 0.4f),
|
|
||||||
adjustColor(hue, 0.5f, 0.8f),
|
class CutCorner : Shape {
|
||||||
adjustColor(hue, 0.5f, 0.3f, 0.9f),
|
override fun draw(canvas: Canvas, size: Float, index: Int, paint: Paint) {
|
||||||
adjustColor(hue, 0.5f, 0.4f, 0.7f)
|
val k = size * 0.42f
|
||||||
|
val path = Path().apply {
|
||||||
|
moveTo(0f, 0f)
|
||||||
|
lineTo(size, 0f)
|
||||||
|
lineTo(size, size - k * 2)
|
||||||
|
lineTo(size - k, size)
|
||||||
|
lineTo(0f, size)
|
||||||
|
close()
|
||||||
|
}
|
||||||
|
canvas.drawPath(path, paint)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SideTriangle : Shape {
|
||||||
|
override fun draw(canvas: Canvas, size: Float, index: Int, paint: Paint) {
|
||||||
|
val w = size / 2
|
||||||
|
val h = size * 0.8f
|
||||||
|
val path = Path().apply {
|
||||||
|
moveTo(size - w, 0f)
|
||||||
|
lineTo(size, h)
|
||||||
|
lineTo(size - w, h)
|
||||||
|
close()
|
||||||
|
}
|
||||||
|
canvas.drawPath(path, paint)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MiddleSquare : Shape {
|
||||||
|
override fun draw(canvas: Canvas, size: Float, index: Int, paint: Paint) {
|
||||||
|
val s = size / 3
|
||||||
|
canvas.drawRect(s, s, size - s, size - s, paint)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CornerSquare : Shape {
|
||||||
|
override fun draw(canvas: Canvas, size: Float, index: Int, paint: Paint) {
|
||||||
|
val inner = size * 0.1f
|
||||||
|
val outer = max(1f, size * 0.25f)
|
||||||
|
canvas.drawRect(outer, outer, size - inner - outer, size - inner - outer, paint)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class OffCenterCircle : Shape {
|
||||||
|
override fun draw(canvas: Canvas, size: Float, index: Int, paint: Paint) {
|
||||||
|
val m = size * 0.15f
|
||||||
|
val s = size * 0.5f
|
||||||
|
canvas.drawCircle(size - s - m, size - s - m, s / 2, paint)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class NegativeTriangle : Shape {
|
||||||
|
override fun draw(canvas: Canvas, size: Float, index: Int, paint: Paint) {
|
||||||
|
val inner = size * 0.1f
|
||||||
|
val outer = inner * 4
|
||||||
|
val path = Path().apply {
|
||||||
|
addRect(0f, 0f, size, size, Path.Direction.CW)
|
||||||
|
moveTo(outer, outer)
|
||||||
|
lineTo(size - inner, outer)
|
||||||
|
lineTo(outer + (size - outer - inner) / 2, size - inner)
|
||||||
|
close()
|
||||||
|
}
|
||||||
|
canvas.drawPath(path, paint)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CutSquare : Shape {
|
||||||
|
override fun draw(canvas: Canvas, size: Float, index: Int, paint: Paint) {
|
||||||
|
val path = Path().apply {
|
||||||
|
moveTo(0f, 0f)
|
||||||
|
lineTo(size, 0f)
|
||||||
|
lineTo(size, size * 0.7f)
|
||||||
|
lineTo(size * 0.4f, size * 0.4f)
|
||||||
|
lineTo(size * 0.7f, size)
|
||||||
|
lineTo(0f, size)
|
||||||
|
close()
|
||||||
|
}
|
||||||
|
canvas.drawPath(path, paint)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CornerPlusTriangle : Shape {
|
||||||
|
override fun draw(canvas: Canvas, size: Float, index: Int, paint: Paint) {
|
||||||
|
val halfSize = size / 2
|
||||||
|
canvas.drawRect(0f, 0f, size, halfSize, paint)
|
||||||
|
canvas.drawRect(0f, halfSize, halfSize, size, paint)
|
||||||
|
val path = Path().apply {
|
||||||
|
moveTo(halfSize, halfSize)
|
||||||
|
lineTo(size, halfSize)
|
||||||
|
lineTo(halfSize, size)
|
||||||
|
close()
|
||||||
|
}
|
||||||
|
canvas.drawPath(path, paint)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class NegativeSquare : Shape {
|
||||||
|
override fun draw(canvas: Canvas, size: Float, index: Int, paint: Paint) {
|
||||||
|
val inner = size * 0.14f
|
||||||
|
val outer = size * 0.35f
|
||||||
|
val path = Path().apply {
|
||||||
|
addRect(0f, 0f, size, size, Path.Direction.CW)
|
||||||
|
addRect(outer, outer, size - outer - inner, size - outer - inner, Path.Direction.CCW)
|
||||||
|
}
|
||||||
|
canvas.drawPath(path, paint)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class NegativeCircle : Shape {
|
||||||
|
override fun draw(canvas: Canvas, size: Float, index: Int, paint: Paint) {
|
||||||
|
val inner = size * 0.12f
|
||||||
|
val outer = inner * 3
|
||||||
|
val path = Path().apply {
|
||||||
|
addRect(0f, 0f, size, size, Path.Direction.CW)
|
||||||
|
addCircle(outer, outer, (size - inner - outer) / 2, Path.Direction.CCW)
|
||||||
|
}
|
||||||
|
canvas.drawPath(path, paint)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class NegativeRhombus : Shape {
|
||||||
|
override fun draw(canvas: Canvas, size: Float, index: Int, paint: Paint) {
|
||||||
|
val m = size * 0.25f
|
||||||
|
val path = Path().apply {
|
||||||
|
addRect(0f, 0f, size, size, Path.Direction.CW)
|
||||||
|
moveTo(m, size / 2)
|
||||||
|
lineTo(size / 2, m)
|
||||||
|
lineTo(size - m, size / 2)
|
||||||
|
lineTo(size / 2, size - m)
|
||||||
|
close()
|
||||||
|
}
|
||||||
|
canvas.drawPath(path, paint)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ConditionalCircle : Shape {
|
||||||
|
override fun draw(canvas: Canvas, size: Float, index: Int, paint: Paint) {
|
||||||
|
if (index == 0) {
|
||||||
|
val m = size * 0.4f
|
||||||
|
val s = size * 1.2f
|
||||||
|
canvas.drawCircle(m, m, s / 2, paint)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class HalfTriangle : Shape {
|
||||||
|
override fun draw(canvas: Canvas, size: Float, index: Int, paint: Paint) {
|
||||||
|
val path = Path().apply {
|
||||||
|
moveTo(size / 2, size / 2)
|
||||||
|
lineTo(size, size / 2)
|
||||||
|
lineTo(size / 2, size)
|
||||||
|
close()
|
||||||
|
}
|
||||||
|
canvas.drawPath(path, paint)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Triangle(val corner: Int = 0) : Shape {
|
||||||
|
override fun draw(canvas: Canvas, size: Float, index: Int, paint: Paint) {
|
||||||
|
val path = Path().apply {
|
||||||
|
when (corner) {
|
||||||
|
0 -> {
|
||||||
|
moveTo(0f, 0f)
|
||||||
|
lineTo(size, 0f)
|
||||||
|
lineTo(0f, size)
|
||||||
|
}
|
||||||
|
1 -> {
|
||||||
|
moveTo(size, 0f)
|
||||||
|
lineTo(size, size)
|
||||||
|
lineTo(0f, size)
|
||||||
|
}
|
||||||
|
2 -> {
|
||||||
|
moveTo(0f, 0f)
|
||||||
|
lineTo(size, 0f)
|
||||||
|
lineTo(size, size)
|
||||||
|
}
|
||||||
|
3 -> {
|
||||||
|
moveTo(0f, 0f)
|
||||||
|
lineTo(0f, size)
|
||||||
|
lineTo(size, size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close()
|
||||||
|
}
|
||||||
|
canvas.drawPath(path, paint)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class BottomHalfTriangle : Shape {
|
||||||
|
override fun draw(canvas: Canvas, size: Float, index: Int, paint: Paint) {
|
||||||
|
val path = Path().apply {
|
||||||
|
moveTo(0f, size / 2)
|
||||||
|
lineTo(size, size / 2)
|
||||||
|
lineTo(size / 2, size)
|
||||||
|
close()
|
||||||
|
}
|
||||||
|
canvas.drawPath(path, paint)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Rhombus : Shape {
|
||||||
|
override fun draw(canvas: Canvas, size: Float, index: Int, paint: Paint) {
|
||||||
|
val path = Path().apply {
|
||||||
|
moveTo(size / 2, 0f)
|
||||||
|
lineTo(size, size / 2)
|
||||||
|
lineTo(size / 2, size)
|
||||||
|
lineTo(0f, size / 2)
|
||||||
|
close()
|
||||||
|
}
|
||||||
|
canvas.drawPath(path, paint)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Circle : Shape {
|
||||||
|
override fun draw(canvas: Canvas, size: Float, index: Int, paint: Paint) {
|
||||||
|
val m = size / 6
|
||||||
|
canvas.drawCircle(m, m, size / 2 - m, paint)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class IconGenerator(private val size: Float, private val hash: ByteArray) {
|
||||||
|
private val digits: ByteArray
|
||||||
|
private var selectedColors = arrayOf<Paint>()
|
||||||
|
|
||||||
|
init {
|
||||||
|
digits = ByteArray(max(12, hash.size * 2))
|
||||||
|
var index = 0
|
||||||
|
for (byte in hash) {
|
||||||
|
if (index >= digits.size) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
digits[index] = ((byte.toInt() shr 4) and 0x0f).toByte()
|
||||||
|
digits[index + 1] = (byte.toInt() and 0x0f).toByte()
|
||||||
|
index += 2
|
||||||
|
}
|
||||||
|
selectColors()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun selectColors() {
|
||||||
|
val value = hash.copyOfRange(hash.size - 4, hash.size).fold(0) { acc, byte ->
|
||||||
|
(acc shl 8) or (byte.toInt() and 0xFF)
|
||||||
|
} and 0x0FFFFFFF
|
||||||
|
val colorTheme = ColorTheme(hue = value.toFloat() / 0x0FFFFFFF)
|
||||||
|
|
||||||
|
val selectedColorIndices = mutableListOf<Int>()
|
||||||
|
for (i in 0 until 3) {
|
||||||
|
val index = (digits[8 + i].toInt() % colorTheme.colors.size)
|
||||||
|
selectedColorIndices.add(colorTheme.validateIndex(index, selectedColorIndices))
|
||||||
|
}
|
||||||
|
|
||||||
|
selectedColors = selectedColorIndices.map { index ->
|
||||||
|
Paint().apply {
|
||||||
|
color = colorTheme.colors[index]
|
||||||
|
style = Paint.Style.FILL
|
||||||
|
}
|
||||||
|
}.toTypedArray()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun renderBitmap(): Bitmap {
|
||||||
|
val bitmap = Bitmap.createBitmap(size.toInt(), size.toInt(), Bitmap.Config.ARGB_8888)
|
||||||
|
val canvas = Canvas(bitmap)
|
||||||
|
render(canvas)
|
||||||
|
return bitmap
|
||||||
|
}
|
||||||
|
|
||||||
|
fun render(canvas: Canvas) {
|
||||||
|
canvas.drawColor(Color.WHITE)
|
||||||
|
|
||||||
|
renderShape(canvas, 0, outerShapes, 2, 3, arrayOf(
|
||||||
|
PointF(1f, 0f),
|
||||||
|
PointF(2f, 0f),
|
||||||
|
PointF(2f, 3f),
|
||||||
|
PointF(1f, 3f),
|
||||||
|
PointF(0f, 1f),
|
||||||
|
PointF(3f, 1f),
|
||||||
|
PointF(3f, 2f),
|
||||||
|
PointF(0f, 2f),
|
||||||
|
))
|
||||||
|
renderShape(canvas, 1, outerShapes, 4, 5, arrayOf(
|
||||||
|
PointF(0f, 0f),
|
||||||
|
PointF(3f, 0f),
|
||||||
|
PointF(3f, 3f),
|
||||||
|
PointF(0f, 3f),
|
||||||
|
))
|
||||||
|
renderShape(canvas, 2, centerShapes, 1, null, arrayOf(
|
||||||
|
PointF(1f, 1f),
|
||||||
|
PointF(2f, 1f),
|
||||||
|
PointF(2f, 2f),
|
||||||
|
PointF(1f, 2f),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun renderShape(
|
||||||
|
canvas: Canvas,
|
||||||
|
colorIndex: Int,
|
||||||
|
shapes: Array<Shape>,
|
||||||
|
index: Int,
|
||||||
|
rotationIndex: Int?,
|
||||||
|
positions: Array<PointF>
|
||||||
|
) {
|
||||||
|
val cellSize = size / 4
|
||||||
|
var r = rotationIndex?.let { digits[it].toInt() } ?: 0
|
||||||
|
val shape = shapes[digits[index].toInt() % shapes.size]
|
||||||
|
|
||||||
|
val paint = Paint().apply {
|
||||||
|
color = selectedColors[colorIndex % selectedColors.size].color
|
||||||
|
style = Paint.Style.FILL
|
||||||
|
}
|
||||||
|
|
||||||
|
for ((idx, position) in positions.withIndex()) {
|
||||||
|
canvas.save()
|
||||||
|
canvas.translate(position.x * cellSize, position.y * cellSize)
|
||||||
|
canvas.translate(cellSize / 2, cellSize / 2)
|
||||||
|
canvas.rotate((r % 4) * 90f)
|
||||||
|
canvas.translate(-cellSize / 2, -cellSize / 2)
|
||||||
|
|
||||||
|
shape.draw(canvas, cellSize, idx, paint)
|
||||||
|
canvas.restore()
|
||||||
|
r++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ColorTheme(val hue: Float, val saturation: Float = 0.5f) {
|
||||||
|
val colors: List<Int>
|
||||||
|
|
||||||
|
init {
|
||||||
|
colors = listOf(
|
||||||
|
// Dark gray
|
||||||
|
grayscaleColor(0f),
|
||||||
|
// Mid color
|
||||||
|
hslColor(hue, saturation, colorLightness(0.5f)),
|
||||||
|
// Light gray
|
||||||
|
grayscaleColor(1f),
|
||||||
|
// Light color
|
||||||
|
hslColor(hue, saturation, colorLightness(1f)),
|
||||||
|
// Dark color
|
||||||
|
hslColor(hue, saturation, colorLightness(0f))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getShapeIndex(x: Int, y: Int, hash: ByteArray): Int {
|
fun validateIndex(index: Int, selected: List<Int>): Int {
|
||||||
val index = if (x < 3) y else 4 - y
|
return if (isDuplicate(index, listOf(0, 4), selected) || isDuplicate(index, listOf(2, 3), selected)) {
|
||||||
return hash[index].toInt() shr x * 2 and 0x03
|
1
|
||||||
}
|
} else {
|
||||||
|
index
|
||||||
private fun drawShape(canvas: Canvas, x: Int, y: Int, size: Int, shapeIndex: Int) {
|
|
||||||
val left = x * size.toFloat()
|
|
||||||
val top = y * size.toFloat()
|
|
||||||
val path = Path()
|
|
||||||
|
|
||||||
when (shapeIndex) {
|
|
||||||
0 -> {
|
|
||||||
// Square
|
|
||||||
path.addRect(left, top, left + size, top + size, Path.Direction.CW)
|
|
||||||
}
|
|
||||||
1 -> {
|
|
||||||
// Circle
|
|
||||||
val radius = size / 2f
|
|
||||||
path.addCircle(left + radius, top + radius, radius, Path.Direction.CW)
|
|
||||||
}
|
|
||||||
2 -> {
|
|
||||||
// Diamond
|
|
||||||
val halfSize = size / 2f
|
|
||||||
path.moveTo(left + halfSize, top)
|
|
||||||
path.lineTo(left + size, top + halfSize)
|
|
||||||
path.lineTo(left + halfSize, top + size)
|
|
||||||
path.lineTo(left, top + halfSize)
|
|
||||||
path.close()
|
|
||||||
}
|
|
||||||
3 -> {
|
|
||||||
// Triangle
|
|
||||||
path.moveTo(left + size / 2f, top)
|
|
||||||
path.lineTo(left + size, top + size)
|
|
||||||
path.lineTo(left, top + size)
|
|
||||||
path.close()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
canvas.drawPath(path, paint)
|
private fun isDuplicate(index: Int, values: List<Int>, selected: List<Int>): Boolean {
|
||||||
|
if (!values.contains(index)) return false
|
||||||
|
return values.any { selected.contains(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun adjustColor(hue: Float, saturation: Float, lightness: Float, alpha: Float = 1.0f): Int {
|
private fun colorLightness(value: Float): Float = lightness(value, 0.4f, 0.8f)
|
||||||
val color = Color.HSVToColor(floatArrayOf(hue * 360, saturation, lightness))
|
|
||||||
val red = Color.red(color)
|
private fun grayscaleLightness(value: Float): Float = lightness(value, 0.3f, 0.9f)
|
||||||
val green = Color.green(color)
|
|
||||||
val blue = Color.blue(color)
|
private fun lightness(value: Float, min: Float, max: Float): Float {
|
||||||
return Color.argb((alpha * 255).toInt(), red, green, blue)
|
val lightness = min + value * (max - min)
|
||||||
|
return minOf(1f, maxOf(0f, lightness))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun grayscaleColor(lightness: Float): Int {
|
||||||
|
return Color.HSVToColor(floatArrayOf(0f, 0f, lightness))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun hslColor(hue: Float, saturation: Float, lightness: Float): Int {
|
||||||
|
return Color.HSVToColor(floatArrayOf(hue, saturation, lightness))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val centerShapes = arrayOf(
|
||||||
|
CutCorner(),
|
||||||
|
SideTriangle(),
|
||||||
|
MiddleSquare(),
|
||||||
|
CornerSquare(),
|
||||||
|
OffCenterCircle(),
|
||||||
|
NegativeTriangle(),
|
||||||
|
CutSquare(),
|
||||||
|
HalfTriangle(),
|
||||||
|
CornerPlusTriangle(),
|
||||||
|
CutSquare(),
|
||||||
|
NegativeCircle(),
|
||||||
|
HalfTriangle(),
|
||||||
|
NegativeRhombus(),
|
||||||
|
ConditionalCircle()
|
||||||
|
)
|
||||||
|
|
||||||
|
val outerShapes = arrayOf(
|
||||||
|
Triangle(),
|
||||||
|
BottomHalfTriangle(),
|
||||||
|
Rhombus(),
|
||||||
|
Circle(),
|
||||||
|
)
|
||||||
|
|
||||||
|
private const val TAG = "IdenticonView"
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -34,6 +34,7 @@ class CreatorThumbnail : ConstraintLayout {
|
||||||
_imageChannelThumbnail = findViewById(R.id.image_channel_thumbnail);
|
_imageChannelThumbnail = findViewById(R.id.image_channel_thumbnail);
|
||||||
_identicon = findViewById(R.id.identicon);
|
_identicon = findViewById(R.id.identicon);
|
||||||
_imageChannelThumbnail.clipToOutline = true;
|
_imageChannelThumbnail.clipToOutline = true;
|
||||||
|
_identicon.clipToOutline = true;
|
||||||
_imageChannelThumbnail.visibility = View.GONE
|
_imageChannelThumbnail.visibility = View.GONE
|
||||||
_imageNewActivity = findViewById(R.id.image_new_activity);
|
_imageNewActivity = findViewById(R.id.image_new_activity);
|
||||||
_imageNeoPass = findViewById(R.id.image_neopass);
|
_imageNeoPass = findViewById(R.id.image_neopass);
|
||||||
|
|
|
@ -12,8 +12,8 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
app:layout_constraintDimensionRatio="1:1"
|
app:layout_constraintDimensionRatio="1:1"
|
||||||
app:srcCompat="@drawable/ic_futo_logo"
|
|
||||||
android:background="@drawable/rounded_outline"
|
android:background="@drawable/rounded_outline"
|
||||||
|
android:clipToOutline="true"
|
||||||
android:contentDescription="@string/channel_image"
|
android:contentDescription="@string/channel_image"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
@ -24,7 +24,6 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
app:layout_constraintDimensionRatio="1:1"
|
app:layout_constraintDimensionRatio="1:1"
|
||||||
app:srcCompat="@drawable/ic_futo_logo"
|
|
||||||
android:background="@drawable/rounded_outline"
|
android:background="@drawable/rounded_outline"
|
||||||
android:clipToOutline="true"
|
android:clipToOutline="true"
|
||||||
android:scaleType="centerCrop"
|
android:scaleType="centerCrop"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue