Skip to content

Commit b224311

Browse files
committed
OnBubbleClick and OnBackgroundDimClick methods added to listener.
BUG FIXED: Sequence with a bubble without target stops all the sequence. README updated
1 parent 686e73d commit b224311

File tree

8 files changed

+112
-52
lines changed

8 files changed

+112
-52
lines changed

README.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,16 @@ BubbleShowCaseBuilder(this) //Activity instance
4646
override fun onTargetClick(bubbleShowCase: BubbleShowCase) {
4747
//Called when the user clicks the target
4848
}
49-
override fun onClose(bubbleShowCase: BubbleShowCase) {
49+
override fun onCloseActionImageClick(bubbleShowCase: BubbleShowCase) {
5050
//Called when the user clicks the close button
5151
}
52+
override fun onBubbleClick(bubbleShowCase: BubbleShowCase) {
53+
//Called when the user clicks on the bubble
54+
}
55+
56+
override fun onBackgroundDimClick(bubbleShowCase: BubbleShowCase) {
57+
//Called when the user clicks on the background dim
58+
}
5259
})
5360
.targetView(buttonArrowRightShowCase) //View to point out
5461
.show() //Display the ShowCase

app/src/main/java/com/elconfidencial/bubbleshowcase/MainActivity.kt

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ package com.elconfidencial.bubbleshowcase
33
import android.support.v7.app.AppCompatActivity
44
import android.os.Bundle
55
import android.support.v4.content.ContextCompat
6+
import android.support.v7.view.menu.ActionMenuItemView
7+
import android.view.Menu
8+
import android.view.MenuItem
69
import android.widget.Toast
710
import kotlinx.android.synthetic.main.activity_main.*
811

@@ -14,6 +17,16 @@ class MainActivity : AppCompatActivity() {
1417
setUpListeners()
1518
}
1619

20+
override fun onCreateOptionsMenu(menu: Menu): Boolean {
21+
menuInflater.inflate(R.menu.menu_test, menu)
22+
return true
23+
}
24+
25+
override fun onOptionsItemSelected(item: MenuItem): Boolean {
26+
val id = item.itemId
27+
return if(id == R.id.action_test) true else super.onOptionsItemSelected(item)
28+
}
29+
1730
private fun setUpListeners(){
1831
buttonSimpleShowCase.setOnClickListener { getSimpleShowCaseBuilder().show() }
1932
buttonColorShowCase.setOnClickListener { getCustomColorShowCaseBuilder().show() }
@@ -73,18 +86,27 @@ class MainActivity : AppCompatActivity() {
7386
.targetView(buttonArrowRightShowCase)
7487
}
7588

89+
7690
private fun getListenerShowCaseBuilder(): BubbleShowCaseBuilder{
7791
return BubbleShowCaseBuilder(this)
7892
.title("Listen user actions!")
7993
.description("You can detect when the user interacts with the different view elements to act consequently.")
8094
.backgroundColor(ContextCompat.getColor(this, R.color.colorOrange))
8195
.image(ContextCompat.getDrawable(this, R.drawable.ic_sentiment_satisfied)!!)
8296
.listener(object : BubbleShowCaseListener{
97+
override fun onBubbleClick(bubbleShowCase: BubbleShowCase) {
98+
Toast.makeText(this@MainActivity, "OnBubbleClick", Toast.LENGTH_SHORT).show()
99+
}
100+
101+
override fun onBackgroundDimClick(bubbleShowCase: BubbleShowCase) {
102+
Toast.makeText(this@MainActivity, "OnBackgroundDimClick", Toast.LENGTH_SHORT).show()
103+
}
104+
83105
override fun onTargetClick(bubbleShowCase: BubbleShowCase) {
84106
Toast.makeText(this@MainActivity, "OnTargetClick", Toast.LENGTH_SHORT).show()
85107
}
86108

87-
override fun onClose(bubbleShowCase: BubbleShowCase) {
109+
override fun onCloseActionImageClick(bubbleShowCase: BubbleShowCase) {
88110
Toast.makeText(this@MainActivity, "OnClose", Toast.LENGTH_SHORT).show()
89111
}
90112
})

bubbleshowcase/deploy.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ apply from: 'keystore.gradle'
77
ext{
88
groupId = 'com.elconfidencial.bubbleshowcase'
99
artifactId = 'bubbleshowcase'
10-
libraryVersion = '1.2.2'
10+
libraryVersion = '1.3.0'
1111
}
1212

1313
version = libraryVersion

bubbleshowcase/src/main/java/com/elconfidencial/bubbleshowcase/BubbleMessageView.kt

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package com.elconfidencial.bubbleshowcase
22

33
import android.content.Context
4-
import android.content.res.TypedArray
54
import android.graphics.Canvas
65
import android.graphics.Paint
76
import android.graphics.Path
@@ -26,6 +25,8 @@ class BubbleMessageView : ConstraintLayout {
2625

2726
private val WIDTH_ARROW = 20
2827

28+
private var itemView: View? = null
29+
2930
private var imageViewIcon: ImageView? = null
3031
private var textViewTitle: TextView? = null
3132
private var textViewSubtitle: TextView? = null
@@ -45,6 +46,7 @@ class BubbleMessageView : ConstraintLayout {
4546
constructor(context: Context, builder: Builder) : super(context) {
4647
initView()
4748
setAttributes(builder)
49+
setBubbleListener(builder)
4850
}
4951

5052
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
@@ -59,7 +61,7 @@ class BubbleMessageView : ConstraintLayout {
5961
}
6062

6163
private fun inflateXML() {
62-
inflate(context, R.layout.view_bubble_message, this)
64+
itemView = inflate(context, R.layout.view_bubble_message, this)
6365
}
6466

6567
private fun bindViews() {
@@ -105,14 +107,14 @@ class BubbleMessageView : ConstraintLayout {
105107
builder.mBackgroundColor?.let { mBackgroundColor = builder.mBackgroundColor!! }
106108
arrowPositionList = builder.mArrowPosition
107109
targetViewScreenLocation = builder.mTargetViewScreenLocation
108-
109-
setOnDismissListener(builder)
110110
}
111111

112-
private fun setOnDismissListener(builder: Builder){
113-
imageViewClose?.setOnClickListener {builder.mListener?.onDismiss()}
112+
private fun setBubbleListener(builder: Builder){
113+
imageViewClose?.setOnClickListener {builder.mListener?.onCloseActionImageClick()}
114+
itemView?.setOnClickListener {builder.mListener?.onBubbleClick()}
114115
}
115116

117+
116118
//END REGION
117119

118120
//REGION AUX FUNCTIONS
@@ -249,7 +251,7 @@ class BubbleMessageView : ConstraintLayout {
249251
var mTitleTextSize: Int? = null
250252
var mSubtitleTextSize: Int? = null
251253
var mArrowPosition = ArrayList<BubbleShowCase.ArrowPosition>()
252-
var mListener: OnDismissBubbleMessageViewListener? = null
254+
var mListener: OnBubbleMessageViewListener? = null
253255

254256
fun from(context: Context): Builder{
255257
mContext = WeakReference(context)
@@ -312,7 +314,7 @@ class BubbleMessageView : ConstraintLayout {
312314
return this
313315
}
314316

315-
fun listener(listener: OnDismissBubbleMessageViewListener?): Builder {
317+
fun listener(listener: OnBubbleMessageViewListener?): Builder {
316318
mListener = listener
317319
return this
318320
}

bubbleshowcase/src/main/java/com/elconfidencial/bubbleshowcase/BubbleShowCase.kt

Lines changed: 42 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ class BubbleShowCase(builder: BubbleShowCaseBuilder){
7575
private val isLastOfSequence: Boolean = builder.mIsLastOfSequence!!
7676

7777
//References
78-
private var foregroundLayoutWithBlur: RelativeLayout? = null
78+
private var backgroundDimLayout: RelativeLayout? = null
7979
private var bubbleMessageViewBuilder: BubbleMessageView.Builder? = null
8080

8181
fun show(){
@@ -89,7 +89,8 @@ class BubbleShowCase(builder: BubbleShowCaseBuilder){
8989
}
9090

9191
val rootView = getViewRoot(mActivity.get()!!)
92-
foregroundLayoutWithBlur = getForegroundLayoutWithBlur()
92+
backgroundDimLayout = getBackgroundDimLayout()
93+
setBackgroundDimListener(backgroundDimLayout)
9394
bubbleMessageViewBuilder = getBubbleMessageViewBuilder()
9495

9596
if (mTargetView != null && mArrowPositionList.size <= 1) {
@@ -104,33 +105,37 @@ class BubbleShowCase(builder: BubbleShowCaseBuilder){
104105
}
105106

106107
if (ScreenUtils.isVisibleOnScreen(target)) {
107-
addTargetViewAtForegroundLayout(target, foregroundLayoutWithBlur)
108-
addBubbleMessageViewDependingOnTargetView(target, bubbleMessageViewBuilder!!, foregroundLayoutWithBlur)
108+
addTargetViewAtBackgroundDimLayout(target, backgroundDimLayout)
109+
addBubbleMessageViewDependingOnTargetView(target, bubbleMessageViewBuilder!!, backgroundDimLayout)
109110
} else {
110111
dismiss()
111112
}
112113
}, DURATION_BACKGROUND_ANIMATION.toLong())
113114
} else {
114-
addBubbleMessageViewOnScreenCenter(bubbleMessageViewBuilder!!, foregroundLayoutWithBlur)
115+
addBubbleMessageViewOnScreenCenter(bubbleMessageViewBuilder!!, backgroundDimLayout)
115116
}
116117
if(isFirstOfSequence){
117-
//Add the foreground layout above the root view
118+
//Add the background dim layout above the root view
118119
val animation = AnimationUtils.getFadeInAnimation(0, DURATION_BACKGROUND_ANIMATION)
119-
foregroundLayoutWithBlur?.let { rootView.addView(AnimationUtils.setAnimationToView(foregroundLayoutWithBlur!!, animation)) }
120+
backgroundDimLayout?.let { rootView.addView(AnimationUtils.setAnimationToView(backgroundDimLayout!!, animation)) }
120121
}
121122
}
122123

123124
fun dismiss() {
124-
notifyDismissToSequenceListener()
125-
if (foregroundLayoutWithBlur != null && isLastOfSequence) {
126-
//Remove foreground layout if the BubbleShowCase is the last of the sequence
127-
val rootView = getViewRoot(mActivity.get()!!)
128-
rootView.removeView(foregroundLayoutWithBlur)
129-
foregroundLayoutWithBlur = null
125+
if (backgroundDimLayout != null && isLastOfSequence) {
126+
//Remove background dim layout if the BubbleShowCase is the last of the sequence
127+
finishSequence()
130128
} else {
131-
//Remove all the views created over the foreground layout waiting for the next BubbleShowCsse in the sequence
132-
foregroundLayoutWithBlur?.removeAllViews()
129+
//Remove all the views created over the background dim layout waiting for the next BubbleShowCsse in the sequence
130+
backgroundDimLayout?.removeAllViews()
133131
}
132+
notifyDismissToSequenceListener()
133+
}
134+
135+
fun finishSequence() {
136+
val rootView = getViewRoot(mActivity.get()!!)
137+
rootView.removeView(backgroundDimLayout)
138+
backgroundDimLayout = null
134139
}
135140

136141
private fun notifyDismissToSequenceListener(){
@@ -142,7 +147,7 @@ class BubbleShowCase(builder: BubbleShowCaseBuilder){
142147
return androidContent.parent.parent as ViewGroup
143148
}
144149

145-
private fun getForegroundLayoutWithBlur(): RelativeLayout {
150+
private fun getBackgroundDimLayout(): RelativeLayout {
146151
if(mActivity.get()!!.findViewById<RelativeLayout>(FOREGROUND_LAYOUT_ID) != null)
147152
return mActivity.get()!!.findViewById(FOREGROUND_LAYOUT_ID)
148153
val backgroundLayout = RelativeLayout(mActivity.get()!!)
@@ -153,6 +158,10 @@ class BubbleShowCase(builder: BubbleShowCaseBuilder){
153158
return backgroundLayout
154159
}
155160

161+
private fun setBackgroundDimListener(backgroundDimLayout: RelativeLayout?){
162+
backgroundDimLayout?.setOnClickListener { mBubbleShowCaseListener?.onBackgroundDimClick(this) }
163+
}
164+
156165
private fun getBubbleMessageViewBuilder(): BubbleMessageView.Builder{
157166
return BubbleMessageView.Builder()
158167
.from(mActivity.get()!!)
@@ -166,10 +175,14 @@ class BubbleShowCase(builder: BubbleShowCaseBuilder){
166175
.image(mImage)
167176
.closeActionImage(mCloseAction)
168177
.disableCloseAction(mDisableCloseAction)
169-
.listener(object : OnDismissBubbleMessageViewListener{
170-
override fun onDismiss() {
178+
.listener(object : OnBubbleMessageViewListener {
179+
override fun onBubbleClick() {
180+
mBubbleShowCaseListener?.onBubbleClick(this@BubbleShowCase)
181+
}
182+
183+
override fun onCloseActionImageClick() {
171184
dismiss()
172-
mBubbleShowCaseListener?.onClose(this@BubbleShowCase)
185+
mBubbleShowCaseListener?.onCloseActionImageClick(this@BubbleShowCase)
173186
}
174187
})
175188
}
@@ -184,11 +197,11 @@ class BubbleShowCase(builder: BubbleShowCaseBuilder){
184197
setString(mPrefs, id, id)
185198
}
186199

187-
fun getString(mPrefs: SharedPreferences, key: String): String? {
200+
private fun getString(mPrefs: SharedPreferences, key: String): String? {
188201
return mPrefs.getString(key, null)
189202
}
190203

191-
fun setString(mPrefs: SharedPreferences, key: String, value: String) {
204+
private fun setString(mPrefs: SharedPreferences, key: String, value: String) {
192205
val editor = mPrefs.edit()
193206
editor.putString(key, value)
194207
editor.apply()
@@ -198,7 +211,7 @@ class BubbleShowCase(builder: BubbleShowCaseBuilder){
198211
/**
199212
* This function takes a screenshot of the targetView, creating an ImageView from it. This new ImageView is also set on the layout passed by param
200213
*/
201-
private fun addTargetViewAtForegroundLayout(targetView: View?, foregroundLayout: RelativeLayout?) {
214+
private fun addTargetViewAtBackgroundDimLayout(targetView: View?, backgroundDimLayout: RelativeLayout?) {
202215
if(targetView==null) return
203216

204217
val targetScreenshot = takeScreenshot(targetView, mHighlightMode)
@@ -212,13 +225,13 @@ class BubbleShowCase(builder: BubbleShowCaseBuilder){
212225

213226
val targetViewParams = RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT)
214227
targetViewParams.setMargins(getXposition(targetView), getYposition(targetView), getScreenWidth(mActivity.get()!!) - (getXposition(targetView) + targetView.width), 0)
215-
foregroundLayout?.addView(AnimationUtils.setBouncingAnimation(targetScreenshotView, 0, DURATION_BEATING_ANIMATION), targetViewParams)
228+
backgroundDimLayout?.addView(AnimationUtils.setBouncingAnimation(targetScreenshotView, 0, DURATION_BEATING_ANIMATION), targetViewParams)
216229
}
217230

218231
/**
219232
* This function creates the BubbleMessageView depending the position of the target and the desired arrow position. This new view is also set on the layout passed by param
220233
*/
221-
private fun addBubbleMessageViewDependingOnTargetView(targetView: View?, bubbleMessageViewBuilder: BubbleMessageView.Builder, foregroundLayout: RelativeLayout?) {
234+
private fun addBubbleMessageViewDependingOnTargetView(targetView: View?, bubbleMessageViewBuilder: BubbleMessageView.Builder, backgroundDimLayout: RelativeLayout?) {
222235
if(targetView==null) return
223236
val showCaseParams = RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT)
224237

@@ -302,13 +315,13 @@ class BubbleShowCase(builder: BubbleShowCaseBuilder){
302315

303316
bubbleMessageView.id = createViewId()
304317
val animation = AnimationUtils.getScaleAnimation(0, DURATION_SHOW_CASE_ANIMATION)
305-
foregroundLayout?.addView(AnimationUtils.setAnimationToView(bubbleMessageView, animation), showCaseParams)
318+
backgroundDimLayout?.addView(AnimationUtils.setAnimationToView(bubbleMessageView, animation), showCaseParams)
306319
}
307320

308321
/**
309322
* This function creates a BubbleMessageView and it is set on the center of the layout passed by param
310323
*/
311-
private fun addBubbleMessageViewOnScreenCenter(bubbleMessageViewBuilder: BubbleMessageView.Builder, foregroundLayout: RelativeLayout?) {
324+
private fun addBubbleMessageViewOnScreenCenter(bubbleMessageViewBuilder: BubbleMessageView.Builder, backgroundDimLayout: RelativeLayout?) {
312325
val showCaseParams = RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT)
313326
showCaseParams.addRule(RelativeLayout. CENTER_VERTICAL)
314327
val bubbleMessageView: BubbleMessageView = bubbleMessageViewBuilder.build()
@@ -319,7 +332,7 @@ class BubbleShowCase(builder: BubbleShowCaseBuilder){
319332
if (isTablet()) getScreenWidth(mActivity.get()!!)/2 - ScreenUtils.dpToPx(MAX_WIDTH_MESSAGE_VIEW_TABLET)/2 else 0,
320333
0)
321334
val animation = AnimationUtils.getScaleAnimation(0, DURATION_SHOW_CASE_ANIMATION)
322-
foregroundLayout?.addView(AnimationUtils.setAnimationToView(bubbleMessageView, animation), showCaseParams)
335+
backgroundDimLayout?.addView(AnimationUtils.setAnimationToView(bubbleMessageView, animation), showCaseParams)
323336
}
324337

325338
private fun createViewId(): Int {
@@ -379,11 +392,11 @@ class BubbleShowCase(builder: BubbleShowCaseBuilder){
379392
}
380393

381394
private fun getScreenVerticalOffset(): Int{
382-
return if(foregroundLayoutWithBlur!=null) ScreenUtils.getAxisYpositionOfViewOnScreen(foregroundLayoutWithBlur!!) else 0
395+
return if(backgroundDimLayout !=null) ScreenUtils.getAxisYpositionOfViewOnScreen(backgroundDimLayout!!) else 0
383396
}
384397

385398
private fun getScreenHorizontalOffset(): Int{
386-
return if(foregroundLayoutWithBlur!=null) ScreenUtils.getAxisXpositionOfViewOnScreen(foregroundLayoutWithBlur!!) else 0
399+
return if(backgroundDimLayout !=null) ScreenUtils.getAxisXpositionOfViewOnScreen(backgroundDimLayout!!) else 0
387400
}
388401

389402
private fun getMessageViewWidthOnTablet(availableSpace: Int): Int{

bubbleshowcase/src/main/java/com/elconfidencial/bubbleshowcase/BubbleShowCaseListener.kt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,15 @@ interface BubbleShowCaseListener {
1414
/**
1515
* It is called when the user clicks on the close icon
1616
*/
17-
fun onClose(bubbleShowCase: BubbleShowCase)
17+
fun onCloseActionImageClick(bubbleShowCase: BubbleShowCase)
18+
19+
/**
20+
* It is called when the user clicks on the background dim
21+
*/
22+
fun onBackgroundDimClick(bubbleShowCase: BubbleShowCase)
23+
24+
/**
25+
* It is called when the user clicks on the bubble
26+
*/
27+
fun onBubbleClick(bubbleShowCase: BubbleShowCase)
1828
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.elconfidencial.bubbleshowcase
2+
3+
/**
4+
* Created by jcampos on 10/09/2018.
5+
*/
6+
interface OnBubbleMessageViewListener {
7+
/**
8+
* It is called when a user clicks the close action image in the BubbleMessageView
9+
*/
10+
fun onCloseActionImageClick()
11+
12+
13+
/**
14+
* It is called when a user clicks the BubbleMessageView
15+
*/
16+
fun onBubbleClick()
17+
}

bubbleshowcase/src/main/java/com/elconfidencial/bubbleshowcase/OnDismissBubbleMessageViewListener.kt

Lines changed: 0 additions & 11 deletions
This file was deleted.

0 commit comments

Comments
 (0)