@@ -190,103 +190,137 @@ private void checking(){
190
190
191
191
}
192
192
private void handleDisableClicking (FrameLayoutWithHole frameLayoutWithHole ){
193
- // 1. if user provides an overlay listener, use that as 1st priority
194
- if (mOverlay != null && mOverlay .mOnClickListener !=null ) {
195
- frameLayoutWithHole .setClickable (true );
196
- frameLayoutWithHole .setOnClickListener (mOverlay .mOnClickListener );
197
- }
198
- // 2. if overlay listener is not provided, check if it's disabled
199
- else if (mOverlay != null && mOverlay .mDisableClick ) {
193
+ if (mOverlay != null && mOverlay .mDisableClick ) {
200
194
frameLayoutWithHole .setViewHole (mHighlightedView );
201
195
frameLayoutWithHole .setSoundEffectsEnabled (false );
202
-
203
- //passing Overlay On-Click listener to frame layout
204
196
frameLayoutWithHole .setOnClickListener (new View .OnClickListener () {
205
197
@ Override
206
198
public void onClick (View view ) {
207
199
Log .d ("tourguide" , "disable, do nothing" );
208
200
}
209
201
});
210
-
211
202
}
212
-
213
203
}
214
204
private void setupToolTip (FrameLayoutWithHole frameLayoutWithHole ){
215
- FrameLayout .LayoutParams layoutParams = new FrameLayout .LayoutParams (FrameLayout .LayoutParams .WRAP_CONTENT , FrameLayout .LayoutParams .WRAP_CONTENT );
216
- // layoutParams.setGravity = Gravity.BOTTOM;
205
+ final FrameLayout .LayoutParams layoutParams = new FrameLayout .LayoutParams (FrameLayout .LayoutParams .WRAP_CONTENT , FrameLayout .LayoutParams .WRAP_CONTENT );
217
206
218
207
if (mToolTip != null ) {
208
+ /* inflate and get views */
219
209
ViewGroup parent = (ViewGroup ) mActivity .getWindow ().getDecorView ();
220
210
LayoutInflater layoutInflater = mActivity .getLayoutInflater ();
221
211
mToolTipViewGroup = layoutInflater .inflate (R .layout .tooltip , null );
222
212
View toolTipContainer = mToolTipViewGroup .findViewById (R .id .toolTip_container );
223
213
TextView toolTipTitleTV = (TextView ) mToolTipViewGroup .findViewById (R .id .title );
224
214
TextView toolTipDescriptionTV = (TextView ) mToolTipViewGroup .findViewById (R .id .description );
225
215
216
+ /* set tooltip attributes */
226
217
toolTipContainer .setBackgroundColor (mToolTip .mBackgroundColor );
227
218
toolTipTitleTV .setText (mToolTip .mTitle );
228
219
toolTipDescriptionTV .setText (mToolTip .mDescription );
229
220
230
221
mToolTipViewGroup .startAnimation (mToolTip .mEnterAnimation );
231
222
232
- // measure size of image to be placed
233
- mToolTipViewGroup .measure (FrameLayout .LayoutParams .WRAP_CONTENT , FrameLayout .LayoutParams .WRAP_CONTENT );
234
- int width = mToolTipViewGroup .getMeasuredWidth ();
235
- int height = mToolTipViewGroup .getMeasuredHeight ();
236
-
237
- Point point = null ;
238
- if (width > parent .getWidth ()){
239
- point = getXYForToolTip (mToolTip .mGravity , parent .getWidth (), height );
240
- } else {
241
- point = getXYForToolTip (mToolTip .mGravity , width , height );
242
- }
243
- layoutParams .setMargins (point .x , point .y , 0 , 0 );
244
223
/* add setShadow if it's turned on */
245
224
if (mToolTip .mShadow ) {
246
225
mToolTipViewGroup .setBackgroundDrawable (mActivity .getResources ().getDrawable (R .drawable .drop_shadow ));
247
226
}
227
+
228
+ /* position and size calculation */
229
+ int [] pos = new int [2 ];
230
+ mHighlightedView .getLocationOnScreen (pos );
231
+ int targetViewX = pos [0 ];
232
+ final int targetViewY = pos [1 ];
233
+
234
+ // get measured size of tooltip
235
+ mToolTipViewGroup .measure (FrameLayout .LayoutParams .WRAP_CONTENT , FrameLayout .LayoutParams .WRAP_CONTENT );
236
+ int toolTipMeasuredWidth = mToolTipViewGroup .getMeasuredWidth ();
237
+ int toolTipMeasuredHeight = mToolTipViewGroup .getMeasuredHeight ();
238
+
239
+ Point resultPoint = new Point (); // this holds the final position of tooltip
240
+ float density = mActivity .getResources ().getDisplayMetrics ().density ;
241
+ final float adjustment = 10 * density ; //adjustment is that little overlapping area of tooltip and targeted button
242
+
243
+ // calculate x position, based on gravity, tooltipMeasuredWidth, parent max width, x position of target view, adjustment
244
+ if (toolTipMeasuredWidth > parent .getWidth ()){
245
+ resultPoint .x = getXForTooTip (mToolTip .mGravity , parent .getWidth (), targetViewX , adjustment );
246
+ } else {
247
+ resultPoint .x = getXForTooTip (mToolTip .mGravity , toolTipMeasuredWidth , targetViewX , adjustment );
248
+ }
249
+
250
+ resultPoint .y = getYForTooTip (mToolTip .mGravity , toolTipMeasuredHeight , targetViewY , adjustment );
251
+
252
+ // add view to parent
248
253
// ((ViewGroup) mActivity.getWindow().getDecorView().findViewById(android.R.id.content)).addView(mToolTipViewGroup, layoutParams);
249
254
parent .addView (mToolTipViewGroup , layoutParams );
250
- if (width > parent .getWidth ()){
251
- mToolTipViewGroup .getLayoutParams ().width = parent .getWidth ();
252
255
256
+ // 1. width < screen check
257
+ if (toolTipMeasuredWidth > parent .getWidth ()){
258
+ mToolTipViewGroup .getLayoutParams ().width = parent .getWidth ();
259
+ toolTipMeasuredWidth = parent .getWidth ();
253
260
}
261
+ // 2. x left boundary check
262
+ if (resultPoint .x < 0 ){
263
+ mToolTipViewGroup .getLayoutParams ().width = toolTipMeasuredWidth + resultPoint .x ; //since point.x is negative, use plus
264
+ resultPoint .x = 0 ;
265
+ }
266
+ // 3. x right boundary check
267
+ int tempRightX = resultPoint .x + toolTipMeasuredWidth ;
268
+ if ( tempRightX > parent .getWidth ()){
269
+ mToolTipViewGroup .getLayoutParams ().width = parent .getWidth () - resultPoint .x ; //since point.x is negative, use plus
270
+ }
271
+
272
+ // TODO: no boundary check for height yet, this is a unlikely case though
273
+ // height boundary can be fixed by user changing the gravity to the other size, since there are plenty of space vertically compared to horizontally
274
+
275
+ // this needs an viewTreeObserver, that's because TextView measurement of it's vertical height is not accurate (didn't take into account of multiple lines yet) before it's rendered
276
+ // re-calculate height again once it's rendered
277
+ final ViewTreeObserver viewTreeObserver = mToolTipViewGroup .getViewTreeObserver ();
278
+ viewTreeObserver .addOnGlobalLayoutListener (new ViewTreeObserver .OnGlobalLayoutListener () {
279
+ @ Override
280
+ public void onGlobalLayout () {
281
+ mToolTipViewGroup .getViewTreeObserver ().removeGlobalOnLayoutListener (this );// make sure this only run once
282
+
283
+ int fixedY ;
284
+ int toolTipHeightAfterLayouted = mToolTipViewGroup .getHeight ();
285
+ fixedY = getYForTooTip (mToolTip .mGravity , toolTipHeightAfterLayouted , targetViewY , adjustment );
286
+ layoutParams .setMargins ((int )mToolTipViewGroup .getX (),fixedY ,0 ,0 );
287
+ }
288
+ });
289
+
290
+ // set the position using setMargins on the left and top
291
+ layoutParams .setMargins (resultPoint .x , resultPoint .y , 0 , 0 );
254
292
}
255
293
256
294
}
257
- private Point getXYForToolTip (int gravity , int width , int height ) {
258
- Point point = new Point ();
259
- int [] pos = new int [2 ];
260
- mHighlightedView .getLocationOnScreen (pos );
261
- int x = pos [0 ];
262
- int y = pos [1 ];
263
- float density = mActivity .getResources ().getDisplayMetrics ().density ;
264
- float adjustment = 10 * density ;
265
- // x calculation
295
+
296
+ private int getXForTooTip (int gravity , int toolTipMeasuredWidth , int targetViewX , float adjustment ){
297
+ int x ;
266
298
if ((gravity & Gravity .LEFT ) == Gravity .LEFT ){
267
- point . x = x - width + (int )adjustment ;
299
+ x = targetViewX - toolTipMeasuredWidth + (int )adjustment ;
268
300
} else if ((gravity & Gravity .RIGHT ) == Gravity .RIGHT ) {
269
- point . x = x + mHighlightedView .getWidth () - (int )adjustment ;
301
+ x = targetViewX + mHighlightedView .getWidth () - (int )adjustment ;
270
302
} else {
271
- point . x = x + mHighlightedView .getWidth () / 2 - width / 2 ;
303
+ x = targetViewX + mHighlightedView .getWidth () / 2 - toolTipMeasuredWidth / 2 ;
272
304
}
273
-
274
- // y calculation
305
+ return x ;
306
+ }
307
+ private int getYForTooTip (int gravity , int toolTipMeasuredHeight , int targetViewY , float adjustment ){
308
+ int y ;
275
309
if ((gravity & Gravity .TOP ) == Gravity .TOP ) {
276
310
277
311
if (((gravity & Gravity .LEFT ) == Gravity .LEFT ) || ((gravity & Gravity .RIGHT ) == Gravity .RIGHT )) {
278
- point . y = y - height + (int )adjustment ;
312
+ y = targetViewY - toolTipMeasuredHeight + (int )adjustment ;
279
313
} else {
280
- point . y = y - height - (int )adjustment ;
314
+ y = targetViewY - toolTipMeasuredHeight - (int )adjustment ;
281
315
}
282
316
} else { // this is center
283
317
if (((gravity & Gravity .LEFT ) == Gravity .LEFT ) || ((gravity & Gravity .RIGHT ) == Gravity .RIGHT )) {
284
- point . y = y + mHighlightedView .getHeight () - (int ) adjustment ;
318
+ y = targetViewY + mHighlightedView .getHeight () - (int ) adjustment ;
285
319
} else {
286
- point . y = y + mHighlightedView .getHeight () + (int ) adjustment ;
320
+ y = targetViewY + mHighlightedView .getHeight () + (int ) adjustment ;
287
321
}
288
322
}
289
- return point ;
323
+ return y ;
290
324
}
291
325
292
326
private FloatingActionButton setupAndAddFABToFrameLayout (final FrameLayoutWithHole frameLayoutWithHole ){
@@ -509,8 +543,10 @@ private int getScreenWidth(){
509
543
return 0 ;
510
544
}
511
545
}
512
-
513
546
public FrameLayoutWithHole getOverlay (){
514
547
return mFrameLayout ;
515
548
}
549
+ public View getToolTip (){
550
+ return mToolTipViewGroup ;
551
+ }
516
552
}
0 commit comments