blob: 1c22eb49c6d207dd0814ec3c1ebd8d0855a81440 [file] [log] [blame]
package com.airbnb.lottie.samples
import android.content.Context
import android.text.InputType
import android.util.AttributeSet
import android.view.KeyEvent
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.BaseInputConnection
import android.view.inputmethod.EditorInfo
import android.view.inputmethod.InputConnection
import android.widget.FrameLayout
import com.airbnb.lottie.LottieAnimationView
import com.airbnb.lottie.LottieComposition
import com.airbnb.lottie.LottieCompositionFactory
import com.airbnb.lottie.LottieDrawable
import java.util.*
class LottieFontViewGroup @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr) {
private val compositionMap = HashMap<String, LottieComposition>()
private val views = ArrayList<View>()
private val cursorView: LottieAnimationView by lazy { LottieAnimationView(context) }
init {
isFocusableInTouchMode = true
LottieCompositionFactory.fromAsset(context, "Mobilo/BlinkingCursor.json")
.addListener {
cursorView.layoutParams = FrameLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT
)
cursorView.setComposition(it)
cursorView.repeatCount = LottieDrawable.INFINITE
cursorView.playAnimation()
addView(cursorView)
}
}
private fun addSpace() {
val index = indexOfChild(cursorView)
addView(createSpaceView(), index)
}
override fun addView(child: View, index: Int) {
super.addView(child, index)
if (index == -1) {
views.add(child)
} else {
views.add(index, child)
}
}
private fun removeLastView() {
if (views.size > 1) {
val position = views.size - 2
removeView(views[position])
views.removeAt(position)
}
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
if (views.isEmpty()) {
return
}
var currentX = paddingTop
var currentY = paddingLeft
for (i in views.indices) {
val view = views[i]
if (!fitsOnCurrentLine(currentX, view)) {
if (view.tag != null && view.tag == "Space") {
continue
}
currentX = paddingLeft
currentY += view.measuredHeight
}
currentX += view.width
}
setMeasuredDimension(measuredWidth, currentY + views[views.size - 1].measuredHeight * 2)
}
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
if (views.isEmpty()) {
return
}
var currentX = paddingTop
var currentY = paddingLeft
for (i in views.indices) {
val view = views[i]
if (!fitsOnCurrentLine(currentX, view)) {
if (view.tag != null && view.tag == "Space") {
continue
}
currentX = paddingLeft
currentY += view.measuredHeight
}
view.layout(currentX, currentY, currentX + view.measuredWidth,
currentY + view.measuredHeight)
currentX += view.width
}
}
override fun onCreateInputConnection(outAttrs: EditorInfo): InputConnection {
val fic = BaseInputConnection(this, false)
outAttrs.actionLabel = null
outAttrs.inputType = InputType.TYPE_NULL
outAttrs.imeOptions = EditorInfo.IME_ACTION_NEXT
return fic
}
override fun onCheckIsTextEditor(): Boolean {
return true
}
override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean {
if (keyCode == KeyEvent.KEYCODE_SPACE) {
addSpace()
return true
}
if (keyCode == KeyEvent.KEYCODE_DEL) {
removeLastView()
return true
}
if (!isValidKey(event)) {
return super.onKeyUp(keyCode, event)
}
val letter = "" + Character.toUpperCase(event.unicodeChar.toChar())
// switch (letter) {
// case ",":
// letter = "Comma";
// break;
// case "'":
// letter = "Apostrophe";
// break;
// case ";":
// case ":":
// letter = "Colon";
// break;
// }
val fileName = "Mobilo/$letter.json"
if (compositionMap.containsKey(fileName)) {
addComposition(compositionMap[fileName]!!)
} else {
LottieCompositionFactory.fromAsset(context, fileName)
.addListener {
compositionMap.put(fileName, it)
addComposition(it)
}
}
return true
}
private fun isValidKey(event: KeyEvent): Boolean {
if (!event.hasNoModifiers()) {
return false
}
if (event.keyCode >= KeyEvent.KEYCODE_A && event.keyCode <= KeyEvent.KEYCODE_Z) {
return true
}
// switch (keyCode) {
// case KeyEvent.KEYCODE_COMMA:
// case KeyEvent.KEYCODE_APOSTROPHE:
// case KeyEvent.KEYCODE_SEMICOLON:
// return true;
// }
return false
}
private fun addComposition(composition: LottieComposition) {
val lottieAnimationView = LottieAnimationView(context)
lottieAnimationView.layoutParams = FrameLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT
)
lottieAnimationView.setComposition(composition)
lottieAnimationView.playAnimation()
val index = indexOfChild(cursorView)
addView(lottieAnimationView, index)
}
private fun fitsOnCurrentLine(currentX: Int, view: View): Boolean {
return currentX + view.measuredWidth < width - paddingRight
}
private fun createSpaceView(): View {
val spaceView = View(context)
spaceView.layoutParams = FrameLayout.LayoutParams(
resources.getDimensionPixelSize(R.dimen.font_space_width),
ViewGroup.LayoutParams.WRAP_CONTENT
)
spaceView.tag = "Space"
return spaceView
}
}