-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathSimpleTarget.kt
176 lines (150 loc) · 6.93 KB
/
SimpleTarget.kt
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
package co.kyash.targetinstructions.targets
import android.content.Context
import android.support.annotation.LayoutRes
import android.view.LayoutInflater
import android.view.View
import android.view.ViewTreeObserver
import android.view.animation.Animation
import android.view.animation.Interpolator
import android.view.animation.OvershootInterpolator
import android.view.animation.ScaleAnimation
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import co.kyash.targetinstructions.AbstractTargetBuilder
import co.kyash.targetinstructions.R
class SimpleTarget(
override var left: Float,
override var top: Float,
override var width: Float,
override var height: Float,
override val highlightRadius: Float,
override val highlightPaddingLeft: Float,
override val highlightPaddingTop: Float,
override val highlightPaddingRight: Float,
override val highlightPaddingBottom: Float,
override val messageView: View,
override val targetView: View? = null,
override val delay: Long = 0L,
override var positionType: Position? = null,
private val messageAnimationDuration: Long = 300L,
private val messageInterpolator: Interpolator,
private val listener: OnStateChangedListener?
) : Target(
left,
top,
width,
height,
highlightRadius,
highlightPaddingLeft,
highlightPaddingTop,
highlightPaddingRight,
highlightPaddingBottom,
messageView,
targetView,
delay,
positionType
) {
override fun showImmediately() {
val container = messageView.findViewById<LinearLayout>(R.id.container)
val topCaret = container.findViewById<ImageView>(R.id.top_caret)
val bottomCaret = container.findViewById<ImageView>(R.id.bottom_caret)
when (positionType) {
Position.ABOVE -> {
if (container.height > 0) {
bottomCaret.x = getCenterX() - bottomCaret.width / 2
bottomCaret.visibility = View.VISIBLE
container.y = top - container.height.toFloat() - highlightPaddingTop
animateMessage(container.y)
} else {
messageView.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
messageView.viewTreeObserver.removeOnGlobalLayoutListener(this)
bottomCaret.x = getCenterX() - bottomCaret.width / 2
bottomCaret.visibility = View.VISIBLE
container.y = top - container.height.toFloat() - highlightPaddingTop
animateMessage(container.y)
}
})
}
}
Position.BELOW -> {
topCaret.x = getCenterX() - topCaret.width / 2
topCaret.visibility = View.VISIBLE
container.y = top + height + highlightPaddingBottom
animateMessage(container.y)
}
}
}
override fun hideImmediately() {
this.listener?.onClosed()
}
private fun animateMessage(pivotY: Float) {
val animation = ScaleAnimation(0.5f, 1.0f, 0.5f, 1.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.ABSOLUTE, pivotY).apply {
this.interpolator = messageInterpolator
repeatCount = 0
duration = this@SimpleTarget.messageAnimationDuration
fillAfter = true
setAnimationListener(object : Animation.AnimationListener {
override fun onAnimationRepeat(animation: Animation?) {
//
}
override fun onAnimationEnd(animation: Animation?) {
//
}
override fun onAnimationStart(animation: Animation?) {
messageView.visibility = View.VISIBLE
}
})
}
messageView.startAnimation(animation)
}
class Builder(context: Context) : AbstractTargetBuilder<Builder, SimpleTarget>(context) {
private lateinit var title: CharSequence
private lateinit var description: CharSequence
@LayoutRes
private var messageLayoutResId = R.layout.layout_simple_message
private var messageAnimationDuration: Long = 300L
private var messageInterpolator: Interpolator = OvershootInterpolator()
private var listener: OnStateChangedListener? = null
override fun self(): Builder = this
fun setTitle(title: CharSequence): Builder = apply { this.title = title }
fun setDescription(description: CharSequence): Builder = apply { this.description = description }
fun setListener(listener: OnStateChangedListener): Builder = apply { this.listener = listener }
fun setMessageLayoutResId(@LayoutRes messageLayoutResId: Int) = apply { this.messageLayoutResId = messageLayoutResId }
fun setMessageAnimationDuration(duration: Long) = apply { this.messageAnimationDuration = duration }
fun setMessageInterpolator(interpolator: Interpolator) = apply { this.messageInterpolator = interpolator }
override fun build(): SimpleTarget {
val context = contextWeakReference.get()
if (context == null) {
throw IllegalStateException("activity is null")
} else {
val targetView = viewWeakReference?.get()
val messageView = LayoutInflater.from(context).inflate(messageLayoutResId, null).apply {
layoutParams = FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT)
(findViewById<TextView>(R.id.title)).text = title
(findViewById<TextView>(R.id.description)).text = description
}
return SimpleTarget(
left = left,
top = top,
width = width,
height = height,
highlightRadius = highlightRadius,
highlightPaddingLeft = highlightPaddingLeft,
highlightPaddingTop = highlightPaddingTop,
highlightPaddingRight = highlightPaddingRight,
highlightPaddingBottom = highlightPaddingBottom,
messageView = messageView,
targetView = targetView,
delay = startDelayMillis,
positionType = positionType,
messageAnimationDuration = messageAnimationDuration,
messageInterpolator = messageInterpolator,
listener = listener
)
}
}
}
}