react-native-navigation 7.25.1 → 7.25.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/lib/android/app/src/main/java/com/reactnativenavigation/NavigationActivity.java +7 -9
  2. package/lib/android/app/src/main/java/com/reactnativenavigation/options/BottomTabOptions.java +4 -0
  3. package/lib/android/app/src/main/java/com/reactnativenavigation/options/OverlayOptions.java +3 -2
  4. package/lib/android/app/src/main/java/com/reactnativenavigation/options/OverlayOptions.kt +31 -0
  5. package/lib/android/app/src/main/java/com/reactnativenavigation/options/parsers/JSONParser.java +0 -2
  6. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/bottomtabs/BottomTabPresenter.java +2 -1
  7. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/bottomtabs/BottomTabsController.java +31 -4
  8. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/child/ChildController.java +6 -13
  9. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/component/ComponentViewController.java +35 -11
  10. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/modal/ModalStack.java +4 -0
  11. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/navigator/Navigator.java +20 -6
  12. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/overlay/OverlayManager.kt +104 -33
  13. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/parent/ParentController.java +86 -9
  14. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/sidemenu/SideMenuController.java +12 -0
  15. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/StackController.java +18 -1
  16. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/StackPresenter.java +51 -0
  17. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/topbar/TopBarController.kt +4 -2
  18. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/topbar/button/ButtonController.kt +7 -1
  19. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/topbar/button/ButtonPresenter.kt +1 -1
  20. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/viewcontroller/RootPresenter.java +0 -1
  21. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/viewcontroller/ViewController.java +12 -0
  22. package/lib/android/app/src/main/java/com/reactnativenavigation/views/bottomtabs/BottomTabs.java +29 -1
  23. package/lib/android/app/src/main/java/com/reactnativenavigation/views/bottomtabs/BottomTabsContainer.kt +1 -0
  24. package/lib/android/app/src/main/java/com/reactnativenavigation/views/bottomtabs/BottomTabsLayout.java +10 -1
  25. package/lib/android/app/src/main/java/com/reactnativenavigation/views/component/ComponentLayout.java +10 -2
  26. package/lib/android/app/src/main/java/com/reactnativenavigation/views/overlay/AttachedOverlayContainer.kt +69 -0
  27. package/lib/android/app/src/main/java/com/reactnativenavigation/views/overlay/ViewTooltip.java +921 -0
  28. package/lib/android/app/src/main/java/com/reactnativenavigation/views/sidemenu/SideMenuRoot.java +9 -1
  29. package/lib/android/app/src/main/java/com/reactnativenavigation/views/stack/StackLayout.java +14 -4
  30. package/lib/android/app/src/main/java/com/reactnativenavigation/views/stack/topbar/TopBar.java +0 -1
  31. package/lib/android/app/src/main/java/com/reactnativenavigation/views/toptabs/TopTabsStyleHelper.java +0 -1
  32. package/lib/dist/src/interfaces/Options.d.ts +25 -1
  33. package/lib/src/interfaces/Options.ts +27 -1
  34. package/package.json +1 -1
@@ -0,0 +1,921 @@
1
+ package com.reactnativenavigation.views.overlay;
2
+
3
+ import android.animation.Animator;
4
+ import android.animation.AnimatorListenerAdapter;
5
+ import android.app.Activity;
6
+ import android.content.Context;
7
+ import android.content.ContextWrapper;
8
+ import android.graphics.Canvas;
9
+ import android.graphics.Color;
10
+ import android.graphics.Paint;
11
+ import android.graphics.Path;
12
+ import android.graphics.Point;
13
+ import android.graphics.Rect;
14
+ import android.graphics.RectF;
15
+ import android.graphics.Typeface;
16
+ import android.text.Html;
17
+ import android.view.View;
18
+ import android.view.ViewGroup;
19
+ import android.view.ViewTreeObserver;
20
+ import android.view.Window;
21
+ import android.widget.FrameLayout;
22
+ import android.widget.TextView;
23
+
24
+ import androidx.annotation.ColorInt;
25
+ import androidx.annotation.StringRes;
26
+ import androidx.core.widget.NestedScrollView;
27
+ import androidx.fragment.app.DialogFragment;
28
+ import androidx.fragment.app.Fragment;
29
+
30
+ import com.reactnativenavigation.utils.UiUtils;
31
+
32
+ import java.util.Arrays;
33
+
34
+
35
+ public class ViewTooltip {
36
+
37
+ private View rootView;
38
+ private final View view;
39
+ private final TooltipView tooltip_view;
40
+
41
+ private ViewTooltip(MyContext myContext, View view) {
42
+ this.view = view;
43
+ this.tooltip_view = new TooltipView(myContext.getContext());
44
+ final NestedScrollView scrollParent = findScrollParent(view);
45
+ if (scrollParent != null) {
46
+ scrollParent.setOnScrollChangeListener((NestedScrollView.OnScrollChangeListener) (v, scrollX, scrollY, oldScrollX, oldScrollY) -> tooltip_view.setTranslationY(tooltip_view.getTranslationY() - (scrollY - oldScrollY)));
47
+ }
48
+ }
49
+
50
+ private ViewTooltip(MyContext myContext, View rootView, View view) {
51
+ this.rootView = rootView;
52
+ this.view = view;
53
+ this.tooltip_view = new TooltipView(myContext.getContext());
54
+ final NestedScrollView scrollParent = findScrollParent(view);
55
+ if (scrollParent != null) {
56
+ scrollParent.setOnScrollChangeListener((NestedScrollView.OnScrollChangeListener) (v, scrollX, scrollY, oldScrollX, oldScrollY) -> tooltip_view.setTranslationY(tooltip_view.getTranslationY() - (scrollY - oldScrollY)));
57
+ }
58
+ }
59
+
60
+ private ViewTooltip(View view) {
61
+ this(new MyContext(getActivityContext(view.getContext())), view);
62
+ }
63
+
64
+ public static ViewTooltip on(final View view) {
65
+ return new ViewTooltip(new MyContext(getActivityContext(view.getContext())), view);
66
+ }
67
+
68
+ public static ViewTooltip on(Fragment fragment, final View view) {
69
+ return new ViewTooltip(new MyContext(fragment), view);
70
+ }
71
+
72
+ public static ViewTooltip on(Activity activity, final View view) {
73
+ return new ViewTooltip(new MyContext(getActivityContext(activity)), view);
74
+ }
75
+
76
+ public static ViewTooltip on(Activity activity, final View rootView, final View view) {
77
+ return new ViewTooltip(new MyContext(getActivityContext(activity)), rootView, view);
78
+ }
79
+
80
+ private NestedScrollView findScrollParent(View view) {
81
+ if (view.getParent() == null || !(view.getParent() instanceof View)) {
82
+ return null;
83
+ } else if (view.getParent() instanceof NestedScrollView) {
84
+ return ((NestedScrollView) view.getParent());
85
+ } else {
86
+ return findScrollParent(((View) view.getParent()));
87
+ }
88
+ }
89
+
90
+ private static Activity getActivityContext(Context context) {
91
+ while (context instanceof ContextWrapper) {
92
+ if (context instanceof Activity) {
93
+ return (Activity) context;
94
+ }
95
+ context = ((ContextWrapper) context).getBaseContext();
96
+ }
97
+ return null;
98
+ }
99
+
100
+ public ViewTooltip position(Position position) {
101
+ this.tooltip_view.setPosition(position);
102
+ return this;
103
+ }
104
+
105
+ public ViewTooltip withShadow(boolean withShadow) {
106
+ this.tooltip_view.setWithShadow(withShadow);
107
+ return this;
108
+ }
109
+
110
+ public ViewTooltip shadowColor(@ColorInt int shadowColor) {
111
+ this.tooltip_view.setShadowColor(shadowColor);
112
+ return this;
113
+ }
114
+
115
+ public ViewTooltip customView(View customView) {
116
+ this.tooltip_view.setCustomView(customView);
117
+ return this;
118
+ }
119
+
120
+ public ViewTooltip customView(int viewId) {
121
+ this.tooltip_view.setCustomView(((Activity) view.getContext()).findViewById(viewId));
122
+ return this;
123
+ }
124
+
125
+ public ViewTooltip arrowWidth(int arrowWidth) {
126
+ this.tooltip_view.setArrowWidth(arrowWidth);
127
+ return this;
128
+ }
129
+
130
+ public ViewTooltip arrowHeight(int arrowHeight) {
131
+ this.tooltip_view.setArrowHeight(arrowHeight);
132
+ return this;
133
+ }
134
+
135
+ public ViewTooltip arrowSourceMargin(int arrowSourceMargin) {
136
+ this.tooltip_view.setArrowSourceMargin(arrowSourceMargin);
137
+ return this;
138
+ }
139
+
140
+ public ViewTooltip arrowTargetMargin(int arrowTargetMargin) {
141
+ this.tooltip_view.setArrowTargetMargin(arrowTargetMargin);
142
+ return this;
143
+ }
144
+
145
+ public ViewTooltip bubble(boolean visbile) {
146
+ this.tooltip_view.enableBubble(visbile);
147
+ return this;
148
+ }
149
+
150
+ public ViewTooltip align(ALIGN align) {
151
+ this.tooltip_view.setAlign(align);
152
+ return this;
153
+ }
154
+
155
+ public TooltipView show() {
156
+ final Context activityContext = tooltip_view.getContext();
157
+ if (activityContext != null && activityContext instanceof Activity) {
158
+ final ViewGroup decorView = rootView != null ?
159
+ (ViewGroup) rootView :
160
+ (ViewGroup) ((Activity) activityContext).getWindow().getDecorView();
161
+ final Rect rect = new Rect();
162
+ view.getGlobalVisibleRect(rect);
163
+
164
+ final Rect rootGlobalRect = new Rect();
165
+ final Point rootGlobalOffset = new Point();
166
+ decorView.getGlobalVisibleRect(rootGlobalRect, rootGlobalOffset);
167
+
168
+ int[] location = new int[2];
169
+ view.getLocationOnScreen(location);
170
+ rect.left = location[0];
171
+ if (rootGlobalOffset != null) {
172
+ rect.top -= rootGlobalOffset.y;
173
+ rect.bottom -= rootGlobalOffset.y;
174
+ rect.left -= rootGlobalOffset.x;
175
+ rect.right -= rootGlobalOffset.x;
176
+ }
177
+
178
+ decorView.addView(tooltip_view, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
179
+ UiUtils.runOnMeasured(tooltip_view, () -> {
180
+ tooltip_view.setup(rect, decorView.getWidth());
181
+ });
182
+
183
+ }
184
+ return tooltip_view;
185
+ }
186
+
187
+ public void close() {
188
+ tooltip_view.close();
189
+ }
190
+
191
+ public ViewTooltip duration(long duration) {
192
+ this.tooltip_view.setDuration(duration);
193
+ return this;
194
+ }
195
+
196
+ public ViewTooltip color(int color) {
197
+ this.tooltip_view.setColor(color);
198
+ return this;
199
+ }
200
+
201
+ public ViewTooltip color(Paint paint) {
202
+ this.tooltip_view.setPaint(paint);
203
+ return this;
204
+ }
205
+
206
+ public ViewTooltip onDisplay(ListenerDisplay listener) {
207
+ this.tooltip_view.setListenerDisplay(listener);
208
+ return this;
209
+ }
210
+
211
+ public ViewTooltip onHide(ListenerHide listener) {
212
+ this.tooltip_view.setListenerHide(listener);
213
+ return this;
214
+ }
215
+
216
+ public ViewTooltip padding(int left, int top, int right, int bottom) {
217
+ this.tooltip_view.paddingTop = top;
218
+ this.tooltip_view.paddingBottom = bottom;
219
+ this.tooltip_view.paddingLeft = left;
220
+ this.tooltip_view.paddingRight = right;
221
+ return this;
222
+ }
223
+
224
+ public ViewTooltip animation(TooltipAnimation tooltipAnimation) {
225
+ this.tooltip_view.setTooltipAnimation(tooltipAnimation);
226
+ return this;
227
+ }
228
+
229
+ public ViewTooltip text(String text) {
230
+ this.tooltip_view.setText(text);
231
+ return this;
232
+ }
233
+
234
+ public ViewTooltip text(@StringRes int text) {
235
+ this.tooltip_view.setText(text);
236
+ return this;
237
+ }
238
+
239
+ public ViewTooltip corner(int corner) {
240
+ this.tooltip_view.setCorner(corner);
241
+ return this;
242
+ }
243
+
244
+ public ViewTooltip textColor(int textColor) {
245
+ this.tooltip_view.setTextColor(textColor);
246
+ return this;
247
+ }
248
+
249
+ public ViewTooltip textTypeFace(Typeface typeface) {
250
+ this.tooltip_view.setTextTypeFace(typeface);
251
+ return this;
252
+ }
253
+
254
+ public ViewTooltip textSize(int unit, float textSize) {
255
+ this.tooltip_view.setTextSize(unit, textSize);
256
+ return this;
257
+ }
258
+
259
+ public ViewTooltip margin(int left, int top, int right, int bottom) {
260
+ this.tooltip_view.setMargin(left, top, right, bottom);
261
+ return this;
262
+ }
263
+
264
+ public ViewTooltip setTextGravity(int textGravity) {
265
+ this.tooltip_view.setTextGravity(textGravity);
266
+ return this;
267
+ }
268
+
269
+ public ViewTooltip clickToHide(boolean clickToHide) {
270
+ this.tooltip_view.setClickToHide(clickToHide);
271
+ return this;
272
+ }
273
+
274
+ public ViewTooltip autoHide(boolean autoHide, long duration) {
275
+ this.tooltip_view.setAutoHide(autoHide);
276
+ this.tooltip_view.setDuration(duration);
277
+ return this;
278
+ }
279
+
280
+ public ViewTooltip distanceWithView(int distance) {
281
+ this.tooltip_view.setDistanceWithView(distance);
282
+ return this;
283
+ }
284
+
285
+ public ViewTooltip border(int color, float width) {
286
+ Paint borderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
287
+ borderPaint.setColor(color);
288
+ borderPaint.setStyle(Paint.Style.STROKE);
289
+ borderPaint.setStrokeWidth(width);
290
+ this.tooltip_view.setBorderPaint(borderPaint);
291
+ return this;
292
+ }
293
+
294
+ public enum Position {
295
+ LEFT,
296
+ RIGHT,
297
+ TOP,
298
+ BOTTOM,
299
+ }
300
+
301
+ public enum ALIGN {
302
+ START,
303
+ CENTER,
304
+ END
305
+ }
306
+
307
+ public interface TooltipAnimation {
308
+ void animateEnter(View view, Animator.AnimatorListener animatorListener);
309
+
310
+ void animateExit(View view, Animator.AnimatorListener animatorListener);
311
+ }
312
+
313
+ public interface ListenerDisplay {
314
+ void onDisplay(View view);
315
+ }
316
+
317
+ public interface ListenerHide {
318
+ void onHide(View view);
319
+ }
320
+
321
+ public static class FadeTooltipAnimation implements TooltipAnimation {
322
+
323
+ private long fadeDuration = 400;
324
+
325
+ public FadeTooltipAnimation() {
326
+ }
327
+
328
+ public FadeTooltipAnimation(long fadeDuration) {
329
+ this.fadeDuration = fadeDuration;
330
+ }
331
+
332
+ @Override
333
+ public void animateEnter(View view, Animator.AnimatorListener animatorListener) {
334
+ view.setAlpha(0);
335
+ view.animate().alpha(1).setDuration(fadeDuration).setListener(animatorListener);
336
+ }
337
+
338
+ @Override
339
+ public void animateExit(View view, Animator.AnimatorListener animatorListener) {
340
+ view.animate().alpha(0).setDuration(fadeDuration).setListener(animatorListener);
341
+ }
342
+ }
343
+
344
+ public static class TooltipView extends FrameLayout {
345
+
346
+ private static final int MARGIN_SCREEN_BORDER_TOOLTIP = 30;
347
+ private int arrowHeight = 15;
348
+ private int arrowWidth = 15;
349
+ private int arrowSourceMargin = 0;
350
+ private int arrowTargetMargin = 0;
351
+ protected View childView;
352
+ private int color = Color.parseColor("#1F7C82");
353
+ private boolean drawBubble = true;
354
+ private Path bubblePath;
355
+ private Paint bubblePaint;
356
+ private Paint borderPaint;
357
+ private Position position = Position.BOTTOM;
358
+ private ALIGN align = ALIGN.CENTER;
359
+ private boolean clickToHide;
360
+ private boolean autoHide = true;
361
+ private long duration = 4000;
362
+
363
+ private ListenerDisplay listenerDisplay;
364
+
365
+ private ListenerHide listenerHide;
366
+
367
+ private TooltipAnimation tooltipAnimation = new FadeTooltipAnimation();
368
+
369
+ private int corner = 30;
370
+
371
+ private int paddingTop = 20;
372
+ private int paddingBottom = 30;
373
+ private int paddingRight = 30;
374
+ private int paddingLeft = 30;
375
+
376
+ private int marginTop = 0;
377
+ private int marginBottom = 0;
378
+ private int marginRight = 0;
379
+ private int marginLeft = 0;
380
+
381
+ int shadowPadding = 4;
382
+ int shadowWidth = 8;
383
+
384
+ private Rect viewRect;
385
+ private int distanceWithView = 0;
386
+ private int shadowColor = Color.parseColor("#aaaaaa");
387
+
388
+ public TooltipView(Context context) {
389
+ super(context);
390
+ setWillNotDraw(false);
391
+
392
+ this.childView = new TextView(context);
393
+ ((TextView) childView).setTextColor(Color.WHITE);
394
+ addView(childView, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
395
+ childView.setPadding(0, 0, 0, 0);
396
+
397
+ bubblePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
398
+ bubblePaint.setColor(color);
399
+ bubblePaint.setStyle(Paint.Style.FILL);
400
+
401
+ borderPaint = null;
402
+
403
+ setLayerType(LAYER_TYPE_SOFTWARE, bubblePaint);
404
+
405
+ setWithShadow(true);
406
+
407
+ }
408
+
409
+ public void setCustomView(View customView) {
410
+ this.removeView(childView);
411
+ this.childView = customView;
412
+ addView(childView, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
413
+ }
414
+
415
+ public void setColor(int color) {
416
+ this.color = color;
417
+ bubblePaint.setColor(color);
418
+ postInvalidate();
419
+ }
420
+
421
+ public void setShadowColor(int color) {
422
+ this.shadowColor = color;
423
+ postInvalidate();
424
+ }
425
+
426
+ public void setMargin(int left, int top, int right, int bottom) {
427
+ this.marginLeft = left;
428
+ this.marginTop = top;
429
+ this.marginRight = right;
430
+ this.marginBottom = top;
431
+
432
+ childView.setPadding(childView.getPaddingLeft() + left, childView.getPaddingTop() + top, childView.getPaddingRight() + right, childView.getPaddingBottom() + bottom);
433
+ postInvalidate();
434
+ }
435
+
436
+ public void setPaint(Paint paint) {
437
+ bubblePaint = paint;
438
+ setLayerType(LAYER_TYPE_SOFTWARE, paint);
439
+ postInvalidate();
440
+ }
441
+
442
+ public void setPosition(Position position) {
443
+ this.position = position;
444
+ switch (position) {
445
+ case TOP:
446
+ setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom + arrowHeight);
447
+ break;
448
+ case BOTTOM:
449
+ setPadding(paddingLeft, paddingTop + arrowHeight, paddingRight, paddingBottom);
450
+ break;
451
+ case LEFT:
452
+ setPadding(paddingLeft, paddingTop, paddingRight + arrowHeight, paddingBottom);
453
+ break;
454
+ case RIGHT:
455
+ setPadding(paddingLeft + arrowHeight, paddingTop, paddingRight, paddingBottom);
456
+ break;
457
+ }
458
+ postInvalidate();
459
+ }
460
+
461
+ public void setAlign(ALIGN align) {
462
+ this.align = align;
463
+ postInvalidate();
464
+ }
465
+
466
+ public void setText(String text) {
467
+ if (childView instanceof TextView) {
468
+ ((TextView) this.childView).setText(Html.fromHtml(text));
469
+ }
470
+ postInvalidate();
471
+ }
472
+
473
+ public void setText(int text) {
474
+ if (childView instanceof TextView) {
475
+ ((TextView) this.childView).setText(text);
476
+ }
477
+ postInvalidate();
478
+ }
479
+
480
+ public void setTextColor(int textColor) {
481
+ if (childView instanceof TextView) {
482
+ ((TextView) this.childView).setTextColor(textColor);
483
+ }
484
+ postInvalidate();
485
+ }
486
+
487
+ public int getArrowHeight() {
488
+ return arrowHeight;
489
+ }
490
+
491
+ public void setArrowHeight(int arrowHeight) {
492
+ this.arrowHeight = arrowHeight;
493
+ postInvalidate();
494
+ }
495
+
496
+ public int getArrowWidth() {
497
+ return arrowWidth;
498
+ }
499
+
500
+ public void setArrowWidth(int arrowWidth) {
501
+ this.arrowWidth = arrowWidth;
502
+ postInvalidate();
503
+ }
504
+
505
+ public int getArrowSourceMargin() {
506
+ return arrowSourceMargin;
507
+ }
508
+
509
+ public void setArrowSourceMargin(int arrowSourceMargin) {
510
+ this.arrowSourceMargin = arrowSourceMargin;
511
+ postInvalidate();
512
+ }
513
+
514
+ public int getArrowTargetMargin() {
515
+ return arrowTargetMargin;
516
+ }
517
+
518
+ public void setArrowTargetMargin(int arrowTargetMargin) {
519
+ this.arrowTargetMargin = arrowTargetMargin;
520
+ postInvalidate();
521
+ }
522
+
523
+ public void setTextTypeFace(Typeface textTypeFace) {
524
+ if (childView instanceof TextView) {
525
+ ((TextView) this.childView).setTypeface(textTypeFace);
526
+ }
527
+ postInvalidate();
528
+ }
529
+
530
+ public void setTextSize(int unit, float size) {
531
+ if (childView instanceof TextView) {
532
+ ((TextView) this.childView).setTextSize(unit, size);
533
+ }
534
+ postInvalidate();
535
+ }
536
+
537
+ public void setTextGravity(int textGravity) {
538
+ if (childView instanceof TextView) {
539
+ ((TextView) this.childView).setGravity(textGravity);
540
+ }
541
+ postInvalidate();
542
+ }
543
+
544
+ public void setClickToHide(boolean clickToHide) {
545
+ this.clickToHide = clickToHide;
546
+ }
547
+
548
+ public void setCorner(int corner) {
549
+ this.corner = corner;
550
+ }
551
+
552
+ @Override
553
+ protected void onSizeChanged(int width, int height, int oldw, int oldh) {
554
+ super.onSizeChanged(width, height, oldw, oldh);
555
+ if (drawBubble)
556
+ bubblePath = drawBubble(new RectF(shadowPadding, shadowPadding, width - shadowPadding * 2, height - shadowPadding * 2), corner, corner, corner, corner);
557
+ }
558
+
559
+ @Override
560
+ protected void onDraw(Canvas canvas) {
561
+ super.onDraw(canvas);
562
+
563
+ if (drawBubble && bubblePath != null) {
564
+ canvas.drawPath(bubblePath, bubblePaint);
565
+ if (borderPaint != null) {
566
+ canvas.drawPath(bubblePath, borderPaint);
567
+ }
568
+ }
569
+ }
570
+
571
+ public void setListenerDisplay(ListenerDisplay listener) {
572
+ this.listenerDisplay = listener;
573
+ }
574
+
575
+ public void setListenerHide(ListenerHide listener) {
576
+ this.listenerHide = listener;
577
+ }
578
+
579
+ public void setTooltipAnimation(TooltipAnimation tooltipAnimation) {
580
+ this.tooltipAnimation = tooltipAnimation;
581
+ }
582
+
583
+ protected void startEnterAnimation() {
584
+ tooltipAnimation.animateEnter(this, new AnimatorListenerAdapter() {
585
+ @Override
586
+ public void onAnimationEnd(Animator animation) {
587
+ super.onAnimationEnd(animation);
588
+ if (listenerDisplay != null) {
589
+ listenerDisplay.onDisplay(TooltipView.this);
590
+ }
591
+ }
592
+ });
593
+ }
594
+
595
+ protected void startExitAnimation(final Animator.AnimatorListener animatorListener) {
596
+ tooltipAnimation.animateExit(this, new AnimatorListenerAdapter() {
597
+ @Override
598
+ public void onAnimationEnd(Animator animation) {
599
+ super.onAnimationEnd(animation);
600
+ animatorListener.onAnimationEnd(animation);
601
+ if (listenerHide != null) {
602
+ listenerHide.onHide(TooltipView.this);
603
+ }
604
+ }
605
+ });
606
+ }
607
+
608
+ protected void handleAutoRemove() {
609
+ if (clickToHide) {
610
+ setOnClickListener(v -> {
611
+ if (clickToHide) {
612
+ remove();
613
+ }
614
+ });
615
+ }
616
+
617
+ if (autoHide) {
618
+ postDelayed(this::remove, duration);
619
+ }
620
+ }
621
+
622
+ public void remove() {
623
+ startExitAnimation(new AnimatorListenerAdapter() {
624
+ @Override
625
+ public void onAnimationEnd(Animator animation) {
626
+ super.onAnimationEnd(animation);
627
+ removeNow();
628
+ }
629
+ });
630
+ }
631
+
632
+ public void setDuration(long duration) {
633
+ this.duration = duration;
634
+ }
635
+
636
+ public void setAutoHide(boolean autoHide) {
637
+ this.autoHide = autoHide;
638
+ }
639
+
640
+ public void setupPosition(Rect rect) {
641
+
642
+ int x, y;
643
+
644
+ if (position == Position.LEFT || position == Position.RIGHT) {
645
+ if (position == Position.LEFT) {
646
+ x = rect.left - getWidth() - distanceWithView;
647
+ } else {
648
+ x = rect.right + distanceWithView;
649
+ }
650
+ y = rect.top + getAlignOffset(getHeight(), rect.height());
651
+ } else {
652
+ if (position == Position.BOTTOM) {
653
+ y = rect.bottom + distanceWithView;
654
+ } else { // top
655
+ y = rect.top - getHeight() - distanceWithView;
656
+ }
657
+ x = rect.left + getAlignOffset(getWidth(), rect.width());
658
+ }
659
+
660
+ setTranslationX(x);
661
+ setTranslationY(y);
662
+ }
663
+
664
+ private int getAlignOffset(int myLength, int hisLength) {
665
+ switch (align) {
666
+ case END:
667
+ return hisLength - myLength;
668
+ case CENTER:
669
+ return (hisLength - myLength) / 2;
670
+ }
671
+ return 0;
672
+ }
673
+
674
+ private Path drawBubble(RectF myRect, float topLeftDiameter, float topRightDiameter, float bottomRightDiameter, float bottomLeftDiameter) {
675
+ final Path path = new Path();
676
+
677
+ if (viewRect == null)
678
+ return path;
679
+
680
+ topLeftDiameter = topLeftDiameter < 0 ? 0 : topLeftDiameter;
681
+ topRightDiameter = topRightDiameter < 0 ? 0 : topRightDiameter;
682
+ bottomLeftDiameter = bottomLeftDiameter < 0 ? 0 : bottomLeftDiameter;
683
+ bottomRightDiameter = bottomRightDiameter < 0 ? 0 : bottomRightDiameter;
684
+
685
+ final float spacingLeft = this.position == Position.RIGHT ? arrowHeight : marginLeft;
686
+ final float spacingTop = this.position == Position.BOTTOM ? arrowHeight : marginTop;
687
+ final float spacingRight = this.position == Position.LEFT ? arrowHeight : marginRight;
688
+ final float spacingBottom = this.position == Position.TOP ? arrowHeight : marginBottom;
689
+
690
+ final float left = spacingLeft + myRect.left;
691
+ final float top = spacingTop + myRect.top;
692
+ final float right = myRect.right - spacingRight;
693
+ final float bottom = myRect.bottom - spacingBottom;
694
+ final float centerX = viewRect.centerX() - getX();
695
+
696
+ final float arrowSourceX = (Arrays.asList(Position.TOP, Position.BOTTOM).contains(this.position))
697
+ ? centerX + arrowSourceMargin
698
+ : centerX;
699
+ final float arrowTargetX = (Arrays.asList(Position.TOP, Position.BOTTOM).contains(this.position))
700
+ ? centerX + arrowTargetMargin
701
+ : centerX;
702
+ final float arrowSourceY = (Arrays.asList(Position.RIGHT, Position.LEFT).contains(this.position))
703
+ ? bottom / 2f - arrowSourceMargin
704
+ : bottom / 2f;
705
+ final float arrowTargetY = (Arrays.asList(Position.RIGHT, Position.LEFT).contains(this.position))
706
+ ? bottom / 2f - arrowTargetMargin
707
+ : bottom / 2f;
708
+
709
+ path.moveTo(left + topLeftDiameter / 2f, top);
710
+ //LEFT, TOP
711
+
712
+ if (position == Position.BOTTOM) {
713
+ path.lineTo(arrowSourceX - arrowWidth, top);
714
+ path.lineTo(arrowTargetX, myRect.top);
715
+ path.lineTo(arrowSourceX + arrowWidth, top);
716
+ }
717
+ path.lineTo(right - topRightDiameter / 2f, top);
718
+
719
+ path.quadTo(right, top, right, top + topRightDiameter / 2);
720
+ //RIGHT, TOP
721
+
722
+ if (position == Position.LEFT) {
723
+ path.lineTo(right, arrowSourceY - arrowWidth);
724
+ path.lineTo(myRect.right, arrowTargetY);
725
+ path.lineTo(right, arrowSourceY + arrowWidth);
726
+ }
727
+ path.lineTo(right, bottom - bottomRightDiameter / 2);
728
+
729
+ path.quadTo(right, bottom, right - bottomRightDiameter / 2, bottom);
730
+ //RIGHT, BOTTOM
731
+
732
+ if (position == Position.TOP) {
733
+ path.lineTo(arrowSourceX + arrowWidth, bottom);
734
+ path.lineTo(arrowTargetX, myRect.bottom);
735
+ path.lineTo(arrowSourceX - arrowWidth, bottom);
736
+ }
737
+ path.lineTo(left + bottomLeftDiameter / 2, bottom);
738
+
739
+ path.quadTo(left, bottom, left, bottom - bottomLeftDiameter / 2);
740
+ //LEFT, BOTTOM
741
+
742
+ if (position == Position.RIGHT) {
743
+ path.lineTo(left, arrowSourceY + arrowWidth);
744
+ path.lineTo(myRect.left, arrowTargetY);
745
+ path.lineTo(left, arrowSourceY - arrowWidth);
746
+ }
747
+ path.lineTo(left, top + topLeftDiameter / 2);
748
+
749
+ path.quadTo(left, top, left + topLeftDiameter / 2, top);
750
+
751
+ path.close();
752
+
753
+ return path;
754
+ }
755
+
756
+ public boolean adjustSize(Rect rect, int screenWidth) {
757
+
758
+ final Rect r = new Rect();
759
+ getGlobalVisibleRect(r);
760
+
761
+ boolean changed = false;
762
+ final ViewGroup.LayoutParams layoutParams = getLayoutParams();
763
+ if (position == Position.LEFT && getWidth() > rect.left) {
764
+ layoutParams.width = rect.left - MARGIN_SCREEN_BORDER_TOOLTIP - distanceWithView;
765
+ changed = true;
766
+ } else if (position == Position.RIGHT && rect.right + getWidth() > screenWidth) {
767
+ layoutParams.width = screenWidth - rect.right - MARGIN_SCREEN_BORDER_TOOLTIP - distanceWithView;
768
+ changed = true;
769
+ } else if (position == Position.TOP || position == Position.BOTTOM) {
770
+ int adjustedLeft = rect.left;
771
+ int adjustedRight = rect.right;
772
+
773
+ if ((rect.centerX() + getWidth() / 2f) > screenWidth) {
774
+ float diff = (rect.centerX() + getWidth() / 2f) - screenWidth;
775
+
776
+ adjustedLeft -= diff;
777
+ adjustedRight -= diff;
778
+
779
+ setAlign(ALIGN.CENTER);
780
+ changed = true;
781
+ } else if ((rect.centerX() - getWidth() / 2f) < 0) {
782
+ float diff = -(rect.centerX() - getWidth() / 2f);
783
+
784
+ adjustedLeft += diff;
785
+ adjustedRight += diff;
786
+
787
+ setAlign(ALIGN.CENTER);
788
+ changed = true;
789
+ }
790
+
791
+ if (adjustedLeft < 0) {
792
+ adjustedLeft = 0;
793
+ }
794
+
795
+ if (adjustedRight > screenWidth) {
796
+ adjustedRight = screenWidth;
797
+ }
798
+
799
+ rect.left = adjustedLeft;
800
+ rect.right = adjustedRight;
801
+ }
802
+
803
+ // setLayoutParams(layoutParams);
804
+ postInvalidate();
805
+ return changed;
806
+ }
807
+
808
+ private void onSetup(Rect myRect) {
809
+ setupPosition(myRect);
810
+ if(drawBubble)
811
+ bubblePath = drawBubble(new RectF(shadowPadding, shadowPadding, getWidth() - shadowPadding * 2f, getHeight() - shadowPadding * 2f), corner, corner, corner, corner);
812
+ startEnterAnimation();
813
+
814
+ handleAutoRemove();
815
+ }
816
+
817
+ public void setup(final Rect viewRect, int screenWidth) {
818
+ this.viewRect = new Rect(viewRect);
819
+ final Rect myRect = new Rect(viewRect);
820
+
821
+ final boolean changed = adjustSize(myRect, screenWidth);
822
+ if (!changed) {
823
+ onSetup(myRect);
824
+ } else {
825
+ getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
826
+ @Override
827
+ public boolean onPreDraw() {
828
+ onSetup(myRect);
829
+ getViewTreeObserver().removeOnPreDrawListener(this);
830
+ return false;
831
+ }
832
+ });
833
+ }
834
+ }
835
+
836
+ public void close() {
837
+ remove();
838
+ }
839
+
840
+ public void removeNow() {
841
+ if (getParent() != null) {
842
+ final ViewGroup parent = ((ViewGroup) getParent());
843
+ parent.removeView(TooltipView.this);
844
+ }
845
+ }
846
+
847
+ public void closeNow() {
848
+ removeNow();
849
+ }
850
+
851
+ public void setWithShadow(boolean withShadow) {
852
+ if (withShadow) {
853
+ bubblePaint.setShadowLayer(shadowWidth, 0, 0, shadowColor);
854
+ } else {
855
+ bubblePaint.setShadowLayer(0, 0, 0, Color.TRANSPARENT);
856
+ }
857
+ }
858
+
859
+ public void setDistanceWithView(int distanceWithView) {
860
+ this.distanceWithView = distanceWithView;
861
+ }
862
+
863
+ public void setBorderPaint(Paint borderPaint) {
864
+ this.borderPaint = borderPaint;
865
+ postInvalidate();
866
+ }
867
+
868
+ public void enableBubble(boolean visbile) {
869
+ drawBubble = visbile;
870
+ bubblePath = null;
871
+ postInvalidate();
872
+ }
873
+ }
874
+
875
+ public static class MyContext {
876
+ private Fragment fragment;
877
+ private Context context;
878
+ private Activity activity;
879
+
880
+ public MyContext(Activity activity) {
881
+ this.activity = activity;
882
+ }
883
+
884
+ public MyContext(Fragment fragment) {
885
+ this.fragment = fragment;
886
+ }
887
+
888
+ public MyContext(Context context) {
889
+ this.context = context;
890
+ }
891
+
892
+ public Context getContext() {
893
+ if (activity != null) {
894
+ return activity;
895
+ } else {
896
+ return ((Context) fragment.getActivity());
897
+ }
898
+ }
899
+
900
+ public Activity getActivity() {
901
+ if (activity != null) {
902
+ return activity;
903
+ } else {
904
+ return fragment.getActivity();
905
+ }
906
+ }
907
+
908
+
909
+ public Window getWindow() {
910
+ if (activity != null) {
911
+ return activity.getWindow();
912
+ } else {
913
+ if (fragment instanceof DialogFragment) {
914
+ return ((DialogFragment) fragment).getDialog().getWindow();
915
+ }
916
+ return fragment.getActivity().getWindow();
917
+ }
918
+ }
919
+ }
920
+ }
921
+