1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
package ca.allanwang.kau.widgets
import android.content.Context
import android.graphics.Color
import android.support.v4.widget.TextViewCompat
import android.text.TextUtils
import android.util.AttributeSet
import android.view.Gravity
import android.view.animation.Animation
import android.view.animation.AnimationUtils
import android.widget.TextSwitcher
import android.widget.TextView
import ca.allanwang.kau.R
import java.util.*
/**
* Created by Allan Wang on 2017-06-21.
*
* Text switcher with global text color and embedded sliding animations
* Also has a stack to keep track of title changes
*/
class KauTextSlider @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null
) : TextSwitcher(context, attrs) {
val titleStack: Stack<CharSequence?> = Stack()
/**
* Holds a mapping of animation types to their respective animations
*/
val animationMap = mapOf(
ANIMATION_NONE to null,
ANIMATION_SLIDE_HORIZONTAL to AnimationBundle(
R.anim.kau_slide_in_right, R.anim.kau_slide_out_left,
R.anim.kau_slide_in_left, R.anim.kau_slide_out_right),
ANIMATION_SLIDE_VERTICAL to AnimationBundle(
R.anim.kau_slide_in_bottom, R.anim.kau_slide_out_top,
R.anim.kau_slide_in_top, R.anim.kau_slide_out_bottom
)
)
/**
* Holds lazy instances of the animations
*/
inner class AnimationBundle(private val nextIn: Int, private val nextOut: Int, private val prevIn: Int, private val prevOut: Int) {
val NEXT_IN: Animation by lazy { AnimationUtils.loadAnimation(context, nextIn) }
val NEXT_OUT: Animation by lazy { AnimationUtils.loadAnimation(context, nextOut) }
val PREV_IN: Animation by lazy { AnimationUtils.loadAnimation(context, prevIn) }
val PREV_OUT: Animation by lazy { AnimationUtils.loadAnimation(context, prevOut) }
}
companion object {
const val ANIMATION_NONE = 1000
const val ANIMATION_SLIDE_HORIZONTAL = 1001
const val ANIMATION_SLIDE_VERTICAL = 1002
}
var animationType: Int = ANIMATION_SLIDE_HORIZONTAL
var textColor: Int = Color.WHITE
get() = field
set(value) {
field = value
(getChildAt(0) as TextView).setTextColor(value)
(getChildAt(1) as TextView).setTextColor(value)
}
val isRoot: Boolean
get() = titleStack.size <= 1
init {
if (attrs != null) {
val styledAttrs = context.obtainStyledAttributes(attrs, R.styleable.KauTextSlider)
animationType = styledAttrs.getInteger(R.styleable.KauTextSlider_kau_animation_type, ANIMATION_SLIDE_HORIZONTAL)
styledAttrs.recycle()
}
}
override fun setText(text: CharSequence?) {
if ((currentView as TextView).text == text) return
super.setText(text)
}
override fun setCurrentText(text: CharSequence?) {
if (titleStack.isNotEmpty()) titleStack.pop()
titleStack.push(text)
super.setCurrentText(text)
}
fun setNextText(text: CharSequence?) {
if (titleStack.isEmpty()) {
setCurrentText(text)
return
}
titleStack.push(text)
val anim = animationMap[animationType]
inAnimation = anim?.NEXT_IN
outAnimation = anim?.NEXT_OUT
setText(text)
}
/**
* Sets the text as the previous title
* No further checks are done, so be sure to verify with [isRoot]
*/
@Throws(EmptyStackException::class)
fun setPrevText() {
titleStack.pop()
val anim = animationMap[animationType]
inAnimation = anim?.PREV_IN
outAnimation = anim?.PREV_OUT
val text = titleStack.peek()
setText(text)
}
init {
setFactory {
TextView(context).apply {
//replica of toolbar title
gravity = Gravity.START
setSingleLine()
ellipsize = TextUtils.TruncateAt.END
TextViewCompat.setTextAppearance(this, R.style.TextAppearance_AppCompat_Title)
}
}
}
}
|