florent37 / tutoshowcase Goto Github PK
View Code? Open in Web Editor NEWA simple and Elegant Showcase view for Android
License: Apache License 2.0
A simple and Elegant Showcase view for Android
License: Apache License 2.0
I've tried to disable auto closing tutorial, and tried with setting TutoShowcase listener and onDismissed callback.Is there any other way to do this? Thanks for your effort and amazing lib!
public void showFeedTutorial(){
TutoShowcase.from(getActivity())
.setContentView(R.layout.tuto_sample)
.on(viewTutorial)
.addRoundRect(0)
.setListener(new TutoShowcase.Listener() {
@Override
public void onDismissed() {
Log.d("Tuto","onDismissed");
}
})
.show();
}
So I'd like to have a simple rectangle drawn instead the rounded corners one.
I am having trouble in finding any method to do this, and also tried to extend the TutoShowcase proved to be a hellish task, as its construction is almost non-extendable.
So is there any simple way other than actually downloading and manually changing the lib my self, which I'd like to avoid if possible.
Cheers
I'm using showOnce("key") but the animation is still running every time the application opens
TutoShowcase.from(this)
.on(R.id.preapproveTxtVw)
.displaySwipableLeft()
.animated(true)
.delayed(300)
.duration(2000)
.show()
.showOnce("key");
It is not possible to check if a tutorial was shown or not using showOnce. Since che sharedpreferences is private it is not possible to check if the key exists or not.
Hi,
It's dismiss method is not working for closing up this showcase window
Hi florent, Great job on this library, it really simplifies creating showcase views. However, is there any feature in this library where the showcase view can be shown once after the first launch!
Regards
i face some issue to highlight view . when i use this some device show it perfect. some device not show perfectly . so i make some adjustment to achieve this .
here i show code which i make adjustment.
private void addCircleOnView(float additionalRadiusRatio) {
Rect rect = new Rect();
int[] locations = new int[2];
view.getGlobalVisibleRect(rect);
view.getLocationOnScreen(locations);
Log.i(TAG, "addCircleOnView: rect values");
Log.i(TAG, "addCircleOnView:left " + rect.left);
Log.i(TAG, "addCircleOnView:top " + rect.top);
Log.i(TAG, "addCircleOnView:right " + rect.right);
Log.i(TAG, "addCircleOnView:bottom " + rect.bottom);
Log.i(TAG, "addCircleOnView: using view's method");
Log.i(TAG, "addCircleOnView:X " + view.getX());
Log.i(TAG, "addCircleOnView:Y " + view.getY());
Log.i(TAG, "addCircleOnView:get top " + view.getTop());
Log.i(TAG, "addCircleOnView: get left " + view.getLeft());
Log.i(TAG, "addCircleOnView: get right " + view.getRight());
Log.i(TAG, "addCircleOnView:get bottom " + view.getBottom());
Log.i(TAG, "addCircleOnView: loction on screen");
Log.i(TAG, "addCircleOnView:location X " + locations[0]);
Log.i(TAG, "addCircleOnView: location Y " + locations[1]);
view.getLocationOnScreen(locations);
int cx;
cx = (int) (rect.left + rect.top - view.getY());
int cy = rect.top;
// int cy = locations[1];
int radius = (int) (Math.max(rect.width(), rect.height()) / 2f * additionalRadiusRatio);
Circle circle = new Circle(cx, cy, radius);
circle.setDisplayBorder(settings.withBorder);
tutoShowcase.tutoView.addCircle(circle);
addClickableView(rect, settings.onClickListener, additionalRadiusRatio);
tutoShowcase.tutoView.postInvalidate();
}
private void addRoundRectOnView(float additionalRadiusRatio) {
Rect rect = new Rect();
int locations[] = new int[2];
view.getLocationOnScreen(locations);
view.getGlobalVisibleRect(rect);
int padding;
Log.i(TAG, "addRectOnView: rect values");
Log.i(TAG, "addRectOnView:left " + rect.left);
Log.i(TAG, "addRectOnView:top " + rect.top);
Log.i(TAG, "addRectOnView:right " + rect.right);
Log.i(TAG, "addRectOnView:bottom " + rect.bottom);
Log.i(TAG, "addRectOnView:width " + rect.width());
Log.i(TAG, "addRectOnView:height " + rect.height());
Log.i(TAG, "addRectOnView: using view's method");
Log.i(TAG, "addRectOnView:X " + view.getX());
Log.i(TAG, "addRectOnView:Y " + view.getY());
Log.i(TAG, "addRectOnView:get top " + view.getTop());
Log.i(TAG, "addRectOnView: get left " + view.getLeft());
Log.i(TAG, "addRectOnView: get right " + view.getRight());
Log.i(TAG, "addRectOnView:get bottom " + view.getBottom());
Log.i(TAG, "addRectOnView:width " + view.getWidth());
Log.i(TAG, "addRectOnView:height " + view.getHeight());
Log.i(TAG, "addRectOnView: loction on screen");
Log.i(TAG, "addRectOnView:location X " + locations[0]);
Log.i(TAG, "addRectOnView: location Y " + locations[1]);
int x, y, width, height;
if (Build.VERSION.SDK_INT < 20) {
x = view.getLeft() - view.getLeft() / 4;
y = locations[1] - 40;
width = view.getWidth() + view.getLeft() / 2;
height = rect.height();
} else {
x = view.getLeft() - view.getLeft() / 4;
y = rect.top;
width = view.getWidth() + view.getLeft() / 2;
height = rect.height();
}
RoundRect roundRect = new RoundRect(x, y, width, height);
roundRect.setDisplayBorder(settings.withBorder);
tutoShowcase.tutoView.addRoundRect(roundRect);
addClickableView(rect, settings.onClickListener, additionalRadiusRatio);
tutoShowcase.tutoView.postInvalidate();
}
In most of cases I have the same layout with the difference only in text. At this moment I see no way how to exclude layout files duplication. It is really annoying to have 20 almost equal layouts. Do you have any idea how to get rid of them? I can use reflection but it doesn't look like a good solution.
i also make animated item to non animated .
code
private void displayScrollableUpOnView() {
final Rect rect = new Rect();
view.getGlobalVisibleRect(rect);
final int height = rect.height();
final ImageView hand = new ImageView(view.getContext());
hand.setImageResource(R.drawable.ic_hand_finger_on_up_arrow);
ViewGroup.MarginLayoutParams layoutParams = new ViewGroup.MarginLayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
hand.setLayoutParams(layoutParams);
hand.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
int x = (int) (rect.centerX() - hand.getWidth() / 2f);
int y = (int) (rect.centerY() - hand.getHeight() / 2f) - getStatusBarOffset();
ViewCompat.setTranslationY(hand, y - 25);
ViewCompat.setTranslationX(hand, x);
//
// if (settings.animated)
// ViewCompat.animate(hand) // - height * 0.8f - getStatusBarOffset()
// .translationY(rect.top-50)
// .setStartDelay(settings.delay != null ? settings.delay : 1500)
// .setDuration(settings.duration != null ? settings.duration : 3000)
// .setInterpolator(new DecelerateInterpolator());
hand.getViewTreeObserver().removeOnPreDrawListener(this);
return false;
}
});
tutoShowcase.container.addView(hand, layoutParams);
tutoShowcase.container.invalidate();
}
Thanks for the library, is it possible to know the position of the circle/square so that we can change the position of the text accordingly? Something done in other libraries such as https://github.com/deano2390/MaterialShowcaseView
The issue with current version is that it is difficult to predict the margin/padding to be provided so as to prevent text coming inside/overlapping circles/squares. Also, as many other posted, since there is no way to even change the text of the TextViews, we end up creating same/similar layout files for individual screens. This all can be prevented, as done in mentioned library.
The circle or rect is displaced when the activity is in full screen.
I copied the project over and fixed it in the following way.
`public final class TutoShowcase {
public static final float DEFAULT_ADDITIONAL_RADIUS_RATIO = 1.5f;
private static final String SHARED_TUTO = "SHARED_TUTO";
private FrameLayout container;
private TutoView tutoView;
private SharedPreferences sharedPreferences;
private boolean isFullScreen = false;
private TutoShowcase(@NonNull Activity activity) {
this.sharedPreferences = activity.getSharedPreferences(SHARED_TUTO, Context.MODE_PRIVATE);
this.container = new FrameLayout(activity);
this.tutoView = new TutoView(activity);
Window window = activity.getWindow();
if (window != null) {
ViewGroup decorView = (ViewGroup) window.getDecorView();
if (decorView != null) {
ViewGroup content = (ViewGroup) decorView.findViewById(android.R.id.content);
if (content != null) {
content.addView(container, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
this.container.addView(tutoView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
}
}
}
int flg = activity.getWindow().getAttributes().flags;
if ((flg & WindowManager.LayoutParams.FLAG_FULLSCREEN) == WindowManager.LayoutParams.FLAG_FULLSCREEN) {
isFullScreen = true;
}
this.container.setVisibility(View.GONE);
ViewCompat.setAlpha(container, 0f);
}`
`public static class ViewActions {
private final TutoShowcase tutoShowcase;
private final View view;
private final ViewActionsSettings settings;
private final boolean isFullScreen;
public ViewActions(final TutoShowcase tutoShowcase, View view, boolean fullScreen) {
this.tutoShowcase = tutoShowcase;
this.view = view;
this.settings = new ViewActionsSettings();
this.isFullScreen = fullScreen;
}`
` private int getStatusBarHeight() {
int result = 0;
Context context = view.getContext();
Resources resources = context.getResources();
int resourceId = resources.getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = resources.getDimensionPixelSize(resourceId);
}
if( isFullScreen ) {
result = 0;
}
return result;
}`
HI, thanks for this library
how can i close this showcase with backpressbutton?
I'm having two fragments in ViewPager tab and when Showcase loads first layout it seems that at same time second layout is loaded.Screen gets darker and when clicked first time, it get some brightnest.
OnClick methods from second fragment works on first fragment.Bot methods are called inside onViewCreated lifecycle callback.
Do I need to dismiss instance of showcase when fragment is destroying?
Here is 1.st fragment:
public void showFeedTutorial() {
TutoShowcase.from(getActivity())
.setContentView(R.layout.tuto_sample)
.on(viewTutorial)
.addRoundRect(0)
.onClickContentView(R.id.imageall, new View.OnClickListener() {
@Override public void onClick(View view) {
Log.d("tuto", "clicking all view");
//dismissTutorial();
}
})
.onClickContentView(R.id.title, new View.OnClickListener() {
@Override public void onClick(View view) {
navigateTo(MarketFragment.class);
}
})
.show();
}
Here is second fragment:
public void showMarketTutorial() {
TutoShowcase.from(getActivity())
.setContentView(R.layout.tuto_sample2)
.show();
}
Is there any way we can show tutorial in the dialog ? Currently when I try to do, the tutorial is shown beneath the dialog. How can we show above the dialog?
Hi,
Thanks for the awesome library. How can i repeat the swipeleft animation in a loop? As of now the animation comes only once.
Can you please make borderColor customizable with setter? Last thing for me, to make it perfect.
Thanks
When we add showcase view with circle or rectangle how to add text on that for description.
i'm unable to find not animated down finger in you library. so i have make some adjustment in your code to get this functionality.
here code to make adjustment to get this functionality
private void displayScrollableDownOnView() {
final Rect rect = new Rect();
view.getGlobalVisibleRect(rect);
final int height = rect.height();
final ImageView hand = new ImageView(view.getContext());
hand.setImageResource(R.drawable.ic_tutoshowcase_finger_moving_down);
hand.setLayoutParams(new ViewGroup.MarginLayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
hand.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
int x = (int) (rect.centerX() - hand.getWidth() / 2f);
int y = (int) (rect.centerY() - hand.getHeight() / 2f) - getStatusBarOffset();
if (Build.VERSION.SDK_INT > 20) {
ViewCompat.setTranslationY(hand, y - 215);
} else {
ViewCompat.setTranslationY(hand, y - 150);
}
ViewCompat.setTranslationX(hand, x);
// if (settings.animated)
// ViewCompat.animate(hand) //- height * 0.8f - getStatusBarOffset()
// .translationY(x)
// .setStartDelay(settings.delay != null ? settings.delay : 500)
// .setDuration(settings.duration != null ? settings.duration : 600)
// .setInterpolator(new DecelerateInterpolator());
hand.getViewTreeObserver().removeOnPreDrawListener(this);
return false;
}
});
Show once logic should not contain show();
, if (!sharedPreferences.contains(key))
should be into show();
method
How can I animate apperance of ShowcaseView?I've tried static method from your samples (animate(true) ) but it doesn't work.
public void showFeedTutorial(){
TutoShowcase.from(getActivity())
.setContentView(R.layout.tuto_sample)
.on(viewTutorial)
.addRoundRect(0)
.onClickContentView(R.id.circleLogin, new View.OnClickListener() {
@Override
public void onClick(View view) {
navigateTo(MarketActivity.class);
}
})
.show();
}
Great library, thanks. It will be cool, if you add scrollable animation customization: repeat it and change image, for example.
i'm using recycler view in a fragment in my app and i need to say something about first recyclerview item
using this code :
TutoShowcase.from(getActivity())
.setContentView(R.layout.tuto)
.on(recyclerView.getChildAt(1))
.addCircle()
.show();
but when i use "recyclerView.getChildAt(1)"
returns me this error :
java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.ViewTreeObserver android.view.View.getViewTreeObserver()' on a null object reference
what can i do about this ?
thank's
Right now I would need to create a new layout for every Showcase I am showing - I would like to use the library for my changelog however, which means there should be an easy way to manipulate view like text once they have been inflated.
By making the function findViewById public this could be easily done.
Great lib and thanks for your effortl
I want to know can I set shapes on some custom layout dimensions?
I dont want to set shapes to views sometimes, need custom shapes for action bar items or anything else.
tutoshowcase can not work with dialog. when i try to display tutoshowcase above dialog then it not work.
any way to display above dialog?.
Hi,
It would be very nice including some default layouts in the library, to use with:
TutoShowcase.from(this) .setContentView(R.layout.tuto_sample)
Thanks & Regards,
Marcello
Hi, thanks for great plugin, but I want to disable auto close when clicking on TutoShowcase. That mean I just want to close it using custom button.
Maybe have a syntax i can use like
TutoShowcase.from(this)
.enableClose(false)
Hi,
Thanks for the lib.
Does anyone have an example using the latest version?
Things like this on(R.id.name) are no longer valid, there is a second parameter but I don't quite get how it works.
Thanks
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.