diff --git a/README.md b/README.md index c28cefc..0c404e5 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,7 @@ ViewTooltip .textColor(Color.WHITE) .color(Color.BLACK) + .overlayColor(0x80000000) .corner(10) @@ -71,6 +72,24 @@ ViewTooltip } }) + .onClick(new ViewTooltip.OnClickListener() { + @Override + public void onClick(int position, ViewTooltip view) { + switch (position){ + case ViewTooltip.POSITION_OVERLAY: + view.hide(); + //Clicked on Overlay + break; + case ViewTooltip.POSITION_TOOLTIP: + view.hide(); + //Clicked on Tooltip + break; + case ViewTooltip.POSITION_TARGET: + //Clicked on Target + break; + } + } + }) .show(); ``` diff --git a/app/build.gradle b/app/build.gradle index 41ed276..41ece51 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,10 +11,11 @@ android { versionCode 1 versionName "1.0" } + } dependencies { - implementation 'androidx.appcompat:appcompat:1.0.2' - implementation 'com.github.florent37:viewtooltip:1.1.8' - //implementation project(path: ':viewtooltip') + implementation 'com.android.support:appcompat-v7:'+project.supportVersion +// implementation 'com.github.florent37:viewtooltip:1.1.8' + implementation project(':viewtooltip') } diff --git a/app/src/main/java/florent37/github/com/viewtooltip/MainActivity.java b/app/src/main/java/florent37/github/com/viewtooltip/MainActivity.java index afd6424..9aa7503 100644 --- a/app/src/main/java/florent37/github/com/viewtooltip/MainActivity.java +++ b/app/src/main/java/florent37/github/com/viewtooltip/MainActivity.java @@ -11,6 +11,7 @@ import android.util.Log; import android.view.View; import android.widget.EditText; +import android.widget.Toast; import com.github.florent37.viewtooltip.ViewTooltip; @@ -109,8 +110,15 @@ public void onClick(View v) { ViewTooltip .on(v) .color(Color.BLACK) + .overlayColor(0x80000000) .position(ViewTooltip.Position.TOP) .text("bottomRight bottomRight bottomRight") + .onClick(new ViewTooltip.OnClickListener() { + @Override + public void onClick(int position, ViewTooltip view) { + view.hide(); + } + }) .show(); } }); @@ -121,8 +129,27 @@ public void onClick(View v) { ViewTooltip .on(v) .color(Color.BLACK) + .overlayColor(0x80000000) .position(ViewTooltip.Position.TOP) .text("bottomLeft bottomLeft bottomLeft") + .onClick(new ViewTooltip.OnClickListener() { + @Override + public void onClick(int position, ViewTooltip view) { + switch (position){ + case ViewTooltip.POSITION_OVERLAY: + view.hide(); + Toast.makeText(getBaseContext(), "Clicked on Overlay", Toast.LENGTH_SHORT).show(); + break; + case ViewTooltip.POSITION_TOOLTIP: + view.hide(); + Toast.makeText(getBaseContext(), "Clicked on Tooltip", Toast.LENGTH_SHORT).show(); + break; + case ViewTooltip.POSITION_TARGET: + Toast.makeText(getBaseContext(), "Clicked on Target", Toast.LENGTH_SHORT).show(); + break; + } + } + }) .show(); } }); diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 5fc1888..bc7ce45 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -77,6 +77,6 @@ android:layout_margin="32dp" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="br"/> + android:text="bl"/> diff --git a/build.gradle b/build.gradle index 2fb65b5..6cedecf 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,6 @@ buildscript { repositories { + maven { url 'https://maven.google.com' } jcenter() google() } @@ -12,6 +13,7 @@ buildscript { allprojects { repositories { + maven { url 'https://maven.google.com' } jcenter() google() } diff --git a/viewtooltip/src/main/java/com/github/florent37/viewtooltip/ViewTooltip.java b/viewtooltip/src/main/java/com/github/florent37/viewtooltip/ViewTooltip.java index 3d40ec1..88a71da 100644 --- a/viewtooltip/src/main/java/com/github/florent37/viewtooltip/ViewTooltip.java +++ b/viewtooltip/src/main/java/com/github/florent37/viewtooltip/ViewTooltip.java @@ -5,29 +5,30 @@ import android.app.Activity; import android.content.Context; import android.content.ContextWrapper; +import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; -import android.graphics.Point; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Typeface; - -import androidx.annotation.ColorInt; -import androidx.annotation.StringRes; -import androidx.core.widget.NestedScrollView; -import androidx.fragment.app.DialogFragment; -import androidx.fragment.app.Fragment; - +import android.graphics.drawable.Drawable; +import android.support.annotation.ColorInt; +import android.support.annotation.IntDef; +import android.support.annotation.StringRes; +import android.support.v4.widget.NestedScrollView; +import android.support.v7.widget.AppCompatImageView; import android.text.Html; +import android.util.DisplayMetrics; import android.view.View; import android.view.ViewGroup; import android.view.ViewTreeObserver; -import android.view.Window; import android.widget.FrameLayout; import android.widget.TextView; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.Arrays; /** @@ -35,29 +36,32 @@ */ public class ViewTooltip { - + public static final int POSITION_OVERLAY = 1; + public static final int POSITION_TOOLTIP = 2; + public static final int POSITION_TARGET = 3; private View rootView; private final View view; private final TooltipView tooltip_view; + private final FrameLayout overlay; + private OnClickListener onClickListener; - private ViewTooltip(MyContext myContext, View view) { - this.view = view; - this.tooltip_view = new TooltipView(myContext.getContext()); - final NestedScrollView scrollParent = findScrollParent(view); - if (scrollParent != null) { - scrollParent.setOnScrollChangeListener(new NestedScrollView.OnScrollChangeListener() { - @Override - public void onScrollChange(NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) { - tooltip_view.setTranslationY(tooltip_view.getTranslationY() - (scrollY - oldScrollY)); - } - }); - } + @IntDef({POSITION_OVERLAY, POSITION_TOOLTIP, POSITION_TARGET}) + @Retention(RetentionPolicy.SOURCE) + private @interface ViwPosition {} + + private ViewTooltip(View view) { + this(view.getContext(), view); } - private ViewTooltip(MyContext myContext, View rootView, View view) { + private ViewTooltip(Context context, View view) { + this(context, null, view); + } + + private ViewTooltip(Context context, View rootView, View view) { this.rootView = rootView; this.view = view; - this.tooltip_view = new TooltipView(myContext.getContext()); + this.tooltip_view = new TooltipView(context); + this.overlay = new FrameLayout(context); final NestedScrollView scrollParent = findScrollParent(view); if (scrollParent != null) { scrollParent.setOnScrollChangeListener(new NestedScrollView.OnScrollChangeListener() { @@ -67,26 +71,40 @@ public void onScrollChange(NestedScrollView v, int scrollX, int scrollY, int old } }); } - } - private ViewTooltip(View view) { - this(new MyContext(getActivityContext(view.getContext())), view); + tooltip_view.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if(onClickListener != null) onClickListener.onClick(POSITION_TOOLTIP, ViewTooltip.this); + if (tooltip_view.clickToHide) { + tooltip_view.remove(); + } + } + }); } - public static ViewTooltip on(final View view) { - return new ViewTooltip(new MyContext(getActivityContext(view.getContext())), view); + private void initTargetClone(){ + TargetGhostView targetGhostView = new TargetGhostView(view.getContext()); + targetGhostView.setTarget(view); + overlay.addView(targetGhostView); + targetGhostView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if(onClickListener != null) onClickListener.onClick(POSITION_TARGET, ViewTooltip.this); + } + }); } - public static ViewTooltip on(Fragment fragment, final View view) { - return new ViewTooltip(new MyContext(fragment), view); + public static ViewTooltip on(final View view) { + return new ViewTooltip(view); } - public static ViewTooltip on(Activity activity, final View view) { - return new ViewTooltip(new MyContext(getActivityContext(activity)), view); + public static ViewTooltip on(Context context, final View view) { + return new ViewTooltip(context, view); } - public static ViewTooltip on(Activity activity, final View rootView, final View view) { - return new ViewTooltip(new MyContext(getActivityContext(activity)), rootView, view); + public static ViewTooltip on(Context context, final View rootView, final View view) { + return new ViewTooltip(context, rootView, view); } private NestedScrollView findScrollParent(View view) { @@ -159,6 +177,27 @@ public ViewTooltip align(ALIGN align) { return this; } + public ViewTooltip overlayColor(@ColorInt int color){ + overlay.setBackgroundColor(color); + initTargetClone(); + overlay.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if(onClickListener != null) onClickListener.onClick(POSITION_OVERLAY, ViewTooltip.this); + } + }); + return this; + } + + public ViewTooltip onClick(OnClickListener onClickListener){ + this.onClickListener = onClickListener; + return this; + } + + public void hide(){ + tooltip_view.remove(); + } + public TooltipView show() { final Context activityContext = tooltip_view.getContext(); if (activityContext != null && activityContext instanceof Activity) { @@ -170,17 +209,16 @@ public TooltipView show() { @Override public void run() { final Rect rect = new Rect(); - final Point offset = new Point(); - view.getGlobalVisibleRect(rect, offset); + view.getGlobalVisibleRect(rect); int[] location = new int[2]; view.getLocationOnScreen(location); rect.left = location[0]; - if (offset != null) { - rect.top -= offset.y; - } + //rect.left = location[0]; + + overlay.addView(tooltip_view, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); - decorView.addView(tooltip_view, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); + decorView.addView(overlay, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); tooltip_view.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override @@ -351,6 +389,103 @@ public void animateExit(View view, Animator.AnimatorListener animatorListener) { } } + public interface OnClickListener{ + void onClick(@ViwPosition int position, ViewTooltip view); + } + + /** + * Target Image View + * + */ + private static class TargetGhostView extends AppCompatImageView { + private int[] position = new int[4]; + private int[] size = new int[2]; + + public TargetGhostView(Context context) { + super(context); + } + + private void setLayoutLikeAsView(View target){ + target.getLocationOnScreen(position); + position[2] = position[0] + target.getWidth(); + position[3] = position[1] + target.getHeight(); + } + + @Override + public void layout(int l, int t, int r, int b) { + super.layout(position[0], position[1], position[2], position[3]); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(size[0], size[1]); + } + + public void setTarget(View target){ + if(target == null) return; + setLayoutLikeAsView(target); + Bitmap bitmap = getBitmapFromView(target); + setImageBitmap(bitmap); + size[0] = bitmap.getWidth(); + size[1] = bitmap.getHeight(); + } + + public static Bitmap createDrawableFromView(Activity activity, View view) { + DisplayMetrics displayMetrics = new DisplayMetrics(); + activity.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); + view.setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT)); + view.measure(displayMetrics.widthPixels, displayMetrics.heightPixels); + view.layout(0, 0, displayMetrics.widthPixels, displayMetrics.heightPixels); + view.buildDrawingCache(); + Bitmap bitmap = Bitmap.createBitmap(view.getMeasuredWidth(), view.getMeasuredHeight(), Bitmap.Config.ARGB_8888); + + Canvas canvas = new Canvas(bitmap); + view.draw(canvas); + + return bitmap; + } + + public static Bitmap loadBitmapFromView(View v) { + if (v.getMeasuredHeight() <= 0) { + int specWidth = View.MeasureSpec.makeMeasureSpec(0 /* any */, View.MeasureSpec.UNSPECIFIED); + v.measure(specWidth, specWidth); + int questionWidth = v.getMeasuredWidth(); + + int specHeight = View.MeasureSpec.makeMeasureSpec(0 /* any */, View.MeasureSpec.UNSPECIFIED); + v.measure(specHeight, specHeight); + int questionHeight = v.getMeasuredHeight(); + + v.measure(questionWidth, questionHeight); + + Bitmap b = Bitmap.createBitmap(v.getMeasuredWidth(), v.getMeasuredHeight(), Bitmap.Config.ARGB_8888); + Canvas c = new Canvas(b); + v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight()); + v.draw(c); + return b; + } + + Bitmap b = Bitmap.createBitmap( v.getLayoutParams().width, v.getLayoutParams().height, Bitmap.Config.ARGB_8888); + Canvas c = new Canvas(b); + v.layout(v.getLeft(), v.getTop(), v.getRight(), v.getBottom()); + v.draw(c); + + + return b; + } + + public static Bitmap getBitmapFromView(View view) { + Bitmap returnedBitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(),Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(returnedBitmap); + Drawable bgDrawable =view.getBackground(); + if (bgDrawable!=null) + bgDrawable.draw(canvas); + else + canvas.drawColor(Color.WHITE); + view.draw(canvas); + return returnedBitmap; + } + } + public static class TooltipView extends FrameLayout { private static final int MARGIN_SCREEN_BORDER_TOOLTIP = 30; @@ -359,7 +494,7 @@ public static class TooltipView extends FrameLayout { private int arrowSourceMargin = 0; private int arrowTargetMargin = 0; protected View childView; - private int color = Color.parseColor("#1F7C82"); + private int color = 0xff1F7C82; private Path bubblePath; private Paint bubblePaint; private Paint borderPaint; @@ -387,7 +522,7 @@ public static class TooltipView extends FrameLayout { private Rect viewRect; private int distanceWithView = 0; - private int shadowColor = Color.parseColor("#aaaaaa"); + private int shadowColor = 0xffaaaaaa; public TooltipView(Context context) { super(context); @@ -575,7 +710,7 @@ public void setTooltipAnimation(TooltipAnimation tooltipAnimation) { } protected void startEnterAnimation() { - tooltipAnimation.animateEnter(this, new AnimatorListenerAdapter() { + tooltipAnimation.animateEnter((View) this.getParent(), new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); @@ -587,7 +722,7 @@ public void onAnimationEnd(Animator animation) { } protected void startExitAnimation(final Animator.AnimatorListener animatorListener) { - tooltipAnimation.animateExit(this, new AnimatorListenerAdapter() { + tooltipAnimation.animateExit((View) this.getParent(), new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); @@ -600,17 +735,6 @@ public void onAnimationEnd(Animator animation) { } protected void handleAutoRemove() { - if (clickToHide) { - setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - if (clickToHide) { - remove(); - } - } - }); - } - if (autoHide) { postDelayed(new Runnable() { @Override @@ -839,8 +963,8 @@ public void close() { public void removeNow() { if (getParent() != null) { - final ViewGroup parent = ((ViewGroup) getParent()); - parent.removeView(TooltipView.this); + final ViewGroup parent = ((ViewGroup) getParent().getParent()); + parent.removeView((ViewGroup) TooltipView.this.getParent()); } } @@ -865,50 +989,4 @@ public void setBorderPaint(Paint borderPaint) { postInvalidate(); } } - - public static class MyContext { - private Fragment fragment; - private Context context; - private Activity activity; - - public MyContext(Activity activity) { - this.activity = activity; - } - - public MyContext(Fragment fragment) { - this.fragment = fragment; - } - - public MyContext(Context context) { - this.context = context; - } - - public Context getContext() { - if (activity != null) { - return activity; - } else { - return ((Context) fragment.getActivity()); - } - } - - public Activity getActivity() { - if (activity != null) { - return activity; - } else { - return fragment.getActivity(); - } - } - - - public Window getWindow() { - if (activity != null) { - return activity.getWindow(); - } else { - if (fragment instanceof DialogFragment) { - return ((DialogFragment) fragment).getDialog().getWindow(); - } - return fragment.getActivity().getWindow(); - } - } - } }