I'm using MaterialShowcaseView:
https://github.com/deano2390/MaterialShowcaseView
How can I detect if a specific ShowcaseView has been touched (dismissed). In my activity, I have 3 ShowcaseViews.
I may have misunderstood your question, but here goes.
If you make a custom View that extends ShowcaseView, you might be able to override onTouchEvent(MotionEvent event) and then put whatever functionality you need inside that method.
See this page about Views: https://developer.android.com/reference/android/view/View.html
Related
I want to make a touch on a button in a layout and also that touch is done by program using injectinputevent method, so that button is clicked even without touching it.
You can use the performClick method on that button.
Call this view's OnClickListener, if it is defined. Performs all normal actions associated with clicking: reporting accessibility event, playing a sound, etc.
You can call if from another method:
your_button.performClick();
Consider this hypothetical hierarchy...
LinearLayoutA <-- I want to handle the touches here...
|
+-SomeViewX
+-SomeOtherViewY
+-LinearLayoutB
|
+-CustomView1 <-- for these three CustomView objects
+-CustomView2
+-CustomView3
What I would like to do is know which (grand)child view was touched and handle it from within LinearLayoutA. Also, I don't control those views so I can't simply make them handle the touch internally and delegate to their parent(s).
Currently I'm manually adding touch listeners to CustomViews 1-3 but that requires a lot of 'boilerplate' work and also means I won't get notified if someone clicks on SomeViewX or SomeOtherViewY, only the specific ones I've attached the listener to.
Now in other languages such as C# with WPF, if you handle the event at the equivalent of LinearLayoutA, part of the event payload is a source, which is the view that initiated the touch, but I'm not aware of any such thing in Android.
All the examples I've seen require looping through the children and hit-testing them, then disambiguating by z-order if there's an overlap, and when you've identified the one child, then you have to go through its children and repeat.
So, is there a built-in, or 'Androidy' way to know which child in a ViewGroup was touched without manually iterating and hit-testing, or manually attaching listeners to all its children?
The OnTouchListener for ViewGroups passes in the ViewGroup as its View argument and not the child within that View that was actually touched. Since you don't have control over the source of the Views in the layout, you'll have to add the OnTouchListener manually from outside of them.
As mentioned in my comments, you can reuse the same listener for all the Views by attaching it to each of the Views you want to listen on. If you're adding these Views dynamically, it should be trivial to also call setOnTouchListener() on them as you create them.
For more on the subject, check out Android's guide to managing touch events in a ViewGroup which provides a way for the parent to intercept touch events on the child, but not vice versa.
I am currently working on a Java SDK which gets installed by the original developer in his existing Android app. Now I need to set some event listeners e.g.:
public void registerTouchListener(ScrollView scrollview) {
scrollview.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
Log.d("SDK", event.toString());
return false;
}
});
}
The issue is that the passed in scrollview might already have a registered listener, so my question is how I can hook into the existing listener or register a second listener?
Maybe too hacky, but could you somehow "Steal" the touch event before it gets to the Scrollview by checking the coordinates of where the touch is going to land and if it's in your list of registered Scrollview. Then act as if you haven't handled the touch event -- that way you could act on that Scrollview prior to it being passed on the touch event?
Rather than providing the API like this, could you rather provide an API that had a function which would call onTouch directly at the end (or beginning) of their event? Not quite as friendly because it won't live in the initialization section, but it will be much clearer and less buggy.
My (OpenGL ES 2.0) app has a splashscreen which is basically an Android View displayed over my GLSurfaceView.
I do all my initial setup on an AsyncTask and then (out of necessity), load my bitmaps/textures on the GLRendering thread in onSurfaceCreated. Once everything has loaded, I dismiss my splashscreen.
Everything works as expected apart from one thing. The splashscreen still accepts input and if the screen is touched just after the app is launched, I (obviously) get an null pointer exception.
I simply create my view like so:
splashscreen = new SplashScreen(getApplication(), width, height); //Where SplashScreen is a custom class that extends View
I then add it to my layout like so:
layout.add(myView); //My GLSurfaceView
layout.add(splashscreen); //The splashscreen View
setContectView(layout);
Once everything has loaded, I simply remove the (splashscreen) View to reveal my GLSurfaceView underneath:
layout.removeView(splashscreen);
splashscreen=null; //Null it
currently, in my onTouch method, to get around the issue, I have put a check in place like so:
public boolean onTouchEvent(MotionEvent event) {
if(splashscreen==null){
//Do touch related stuff here
}
return true;
}
This does work, however, I'm sure it's not the cleanest way to achieve what I'm after.
I've tried this:
splashscreensetClickable(false);
and
layout.setClickable(false);
as well as setEnabled(false)
Nothing seems to work, but I'm sure there must be a way of doing this.......
Generally, you will want the splash screen to prevent the user from doing anything while it is present. You can actually do this, because views in android, as in other UI frameworks, have a hierarchy in which touch events cascade.
Even though you don't want the splash screen to be interactive, you can still steal all of the touch events that occur on it, and just do nothing with them. The answer itself is to override onTouchEvent in your SplashScreen class with:
#Override
public boolean onTouchEvent(MotionEvent event) {
return true; // Splash screen is consuming all touch events on it.
}
Returning true in this basically says that nothing under this view should receive a touch event. As long as it is visible and over top of the surface view, your surface view will not get any touch events. See here for details.
In pure Java there is MouseInputListener which I can use to work with those 2 events.
How do I do it with Android?
If I implement both events then only one is fired (onClickListener) and not the other.
Updated:
The question is not about detecting the finger movement.
I have a View (ImageView for example). I need to detect the click on this view which is onClickListener() and finger movement on this view (i.e. press, move then release the finger).
The problem here is that only onClickListener() is called and MotionEvent handler is not caught.
I need to be able to differentiate those 2 events as the main event should be finger movement and onClickListener() should just say "Don't click this view. Spin this view."
Hopefully this is more clear.
OnClickListener and OnTouchListener kinda obstruct each other, since they both consume the MotionEvents that get caught on the View.
Basically you can write a single OnTouchListener that checks for both things. You'll get supplied with the MotionEvent as an argument. Check it's action via MotionEvent.getAction(), e.g. if it equals MotionEvent.ACTION_DOWN (the user put the finger on the display). If the user releases the finger at approx. the same position (ACTION_UP), you may want to interpret that as a click. Otherwise interpret the positions that you get with the ACTION_MOVE event as a gesture.
But the framework already has some classes that do this interpreting work for you, check out the SimpleGestureDetector class and it's SimpleOnGestureListener. That has some callbacks for common events, e.g. onSingleTapConfirmed() and onFling(). All you need to do is supply the MotionEvents from your OnTouchListener to the GestureDetector.