I want to add an onClickListener event for YouTube Player API
I tried many many solutions but all of them didn't work
Some of my attempts
YouTubePlayerView youTubePlayerView = findViewById(R.id.youtubePlayer);
youTubePlayerView.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
Log.d(TAG,"onClick");
}
});
YouTubePlayerView youTubePlayerView = findViewById(R.id.youtubePlayer);
youTubePlayerView.setOnTouchListener(new View.OnTouchListener()
{
#Override
public boolean onTouch(View v, MotionEvent event)
{
Log.d(TAG,"onTouch");
return false;
}
});
Also, I tried to add a layout above the YouTube player view and make it transparent then add a click listener to this layout but the player stops after few seconds every time
And my last attempt was working with GestureDetector class but also didn't work
Thank you in advance
I tried to add a layout above the YouTube player view and make it
transparent then add a click listener to this layout but the player
stops after few seconds
YouTube Player API does not allow any view above it be it a visible or not and will close with an ErrorReason.
It also consumes any and all touch events without sharing them. However you can Override dispatchTouchEvent(MotionEvent) method of the parent ViewGroup to the YouTubePlayerViewand steal back these touch events to kick you own onClick() callback.
What you have to do is, first create a container in the xml layout file where you've placed your YouTubePlayerView.
youtube_player_view_layout.xml
<MyCustomFrameLayout>
android:layout_width="match_parent"
android:layout_height="match_parent"
<YouTubePlayerView
android:layout_width="match_parent"
android:layout_height="match_parent"
>
</YouTubePlayerView>
</MyCustomFrameLayout>
MyCustomFrameLayout must be added with fully qualified name in layout xml i.e. with [my.class.package]+[ClassName]
MyCustomFrameLayout.java
public class MyCustomFrameLayout extends FrameLayout {
private boolean actionDownReceived = false;
#Override
public boolean dispatchTouchEvent(MotionEvent event) {
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN: {
actionDownReceived = true;
break;
}
case MotionEvent.ACTION_MOVE: {
// No longer a click, probably a gesture.
actionDownReceived = false;
break;
}
case MotionEvent.ACTION_UP: {
if (actionDownReceived) {
performClick();
}
break;
}
}
return super.dispatchTouchEvent(event);
}
}
and then all you need to do is set click listener on MyCustomFrameLayout.
Disclaimer : The above code is not tested in an IDE and will probably not run correctly if/when copied as is. However the essence
of the thought is properly projected here.
Related
I'm using a third party video player in my app. The library provides enough functionalities like scroll video, pause, play video etc. And all those features will auto-hide after a few seconds. I need a few more controls over the player. So I put a toolbar on it ( It consists of the back, favorite, share buttons ). I need to enable this toolbar only If someone clicks on the player or even taps on it. And it must hide after a few seconds like the video player's controller. I tried using this,
youtubePlayerView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_UP){
LogUtils.LOGE("youtubePlayerView.setOnClick", "called");
return true;
}
return false;
}
});
But in vain. Nothing is happening.
I want to detect If the user has clicked or tapped on the player.
Try Like this
public void onClickHandler(View v)
{
switch (v.getId()) {
case R.id.youtubePlayerView:
//Player Clicked
break;
}
}
This should work:
youtubePlayerView.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// enable toolbar here!
}
});
I'm trying to get the coordinates of X and Y of the pattern lock component. The code that i'm using to create the Pattern Lock component is from aritraroy/PatternLockView which can be found on Github. Firstly, i set the root view on a view variable like this:
and then i set the OnTouchListener on root view.
Finally i create the the PatterLockViewListener:
final PatternLockViewListener mPatternLockViewListener = new PatternLockViewListener() {
//do whatever
}
What i want is by clicking the PatternLock component to get the coordinates(X,Y) in correlation to the root view. Instead i get the coordinates in all other components except from the PatternLock (by clicking the PatternLock component the OnTouchListener doesnt trigger and as a result, the code is not working/running)
The solution that finally worked for me after searching for 3, 4 days is this:
public class Pattern extends AppCompatActivity
{
PatternLockView pattern_lock;
//x,y coordinates for when the finger touches the screen
//x,y coordinates for when the finger moves around the screen
#Override
protected void onCreate(Bundle savedInstanceState)
{
pattern_lock = (PatternLockView)findViewById(R.id.pattern_screen);
pattern_lock.setOnTouchListener(new View.OnTouchListener()
{
#Override
public boolean onTouch(View v, MotionEvent event)
{
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
//code
return Pattern.super.onTouchEvent(event);
case MotionEvent.ACTION_MOVE:
//code
return Pattern.super.onTouchEvent(event);
case MotionEvent.ACTION_UP:
//code
return Pattern.super.onTouchEvent(event);
}
return true;
}
});
}
}
I'm not really sure why to return that (return Pattern.super.onTouchEvent(event);) and not true as most posts say about onTouch.
I'm having problems dealing with a button and its two listeners.
My objective is swapping two listeners of a button using it.
It's not the behaviour I need. I need to release the button, and then click it again in a different way (with a different listener).
So.. I "onTouch" this button, and when I release my finger, I need to swap its "onTouch" listener to an "onClick()" one.
Now, I tried to accomplish my goal doing the following:
final View.OnClickListener play_listener = new View.OnClickListener() {
#Override
public void onClick(View v) { Utility.playRecording(mediaPlayer); } };
final View.OnTouchListener rec_listener = new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent event) {
if (Utility.checkPermission(view.getContext())) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Utility.startRecording(recorder, output_formats, currentFormat, file_exts, timer);
break;
case MotionEvent.ACTION_UP:
Utility.stopRecording(recorder, timer);
//disabling my onTouch Listener
recplay_button.setOnTouchListener(null);
//Setting a new listener for the same button
recplay_button.setOnClickListener(play_listener);
//Changing its color.
recplay_button.setBackground(getDrawable(R.drawable.coloranimreverse));
break;
}
} else {
Utility.requestPermission(view.getContext());
} return false; }};
So, the swapping works but I can't get the reason why after setting the onClickListener it also execute it, playing the sound I set in the other listener. Does the MotionEvent.ACTION_UP counts as a click?
Do you know how can I get through this? What I need is just not execute the onClick() listener in the same moment that I set it in the OnTouch() listener.
Thank you all.
Your OnClickListener is firing on ACTION_UP because you're unconditionally returning false from onTouch(). Returning false there tells the View that you've not consumed the event, and that it should handle it, as well. In this case, it means that the View will perform its click handling, and now that it's got an OnClickListener set, that gets called. (In fact, you could've set the OnClickListener from the start, and would've achieved the same behavior.)
Returning true in the ACTION_UP case will signal that you're consuming that event there, so the View won't end up calling its OnClickListener. This might be sufficient for your use case, however, it also means that the View won't perform any of the other state changes it would normally do for ACTION_UP; e.g., changing its Drawables to their not pressed state.
Rather than juggling listeners, and trying to decide which events to consume, and which to pass on, it might be preferable to handle everything in the OnTouchListener, track the current state in some sort of flag variable, and again return false unconditionally in onTouch(). In this way, we're simply "inserting" the desired behavior, and allowing the View to continue handling events and state as it normally would.
For example:
private boolean recordState = true;
final View.OnTouchListener rec_listener = new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent event) {
if (Utility.checkPermission(view.getContext())) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (recordState) {
Utility.startRecording(recorder, output_formats, currentFormat, file_exts, timer);
}
break;
case MotionEvent.ACTION_UP:
if (recordState) {
recordState = false;
Utility.stopRecording(recorder, timer);
recplay_button.setImageDrawable(getResources().getDrawable(R.drawable.coloranimreverse));
}
else {
Utility.playRecording(mediaPlayer);
}
}
} else {
Utility.requestPermission(view.getContext());
}
return false;
}
};
I am using custom animations at ACTION_DOWN and ACTION_UP events of my button.
However, right now, I am manually setting OnTouchListener to each Button manually with code like this:
myButton.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View yourButton, MotionEvent theMotion) {
Animation animation;
switch (theMotion.getAction()) {
case MotionEvent.ACTION_DOWN:
animation = AnimationUtils.loadAnimation(NickNameScreenActivity.this, R.anim.button_down);
myButton.startAnimation(animation);
break;
case MotionEvent.ACTION_UP:
animation = AnimationUtils.loadAnimation(NickNameScreenActivity.this, R.anim.button_up);
myButton.startAnimation(animation);
break;
}
return false;
}
});
This is cumbersome as I have to repeat this for all Buttons.
Is there a way to set it automatically for all buttons or a tidy XML way of doing this?
You can write a custom view extending Button and use it in xml. Maybe you can replace NickNameScreenActivity.this with getContext().
I have written these lines of code:
mVideoView = (VideoView) findViewById(R.id.video_view);
mVideoView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Log.v("LOG_TAG, click");
}
});
However, when I run my application, the click event is never called.
So I wonder, is it impossible to register an OnClickListener on a VideoView? And, if so, why is that the case?
use VideoView.setOnTouchListener(..) it works for VideoView
Here's how I solved the pause/play of VideoViews using onTouch:
// Class variables
private boolean bVideoIsBeingTouched = false;
private Handler mHandler = new Handler();
vvVideo.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (!bVideoIsBeingTouched) {
bVideoIsBeingTouched = true;
if (vvVideo.isPlaying()) {
vvVideo.pause();
} else {
vvVideo.resume();
}
mHandler.postDelayed(new Runnable() {
public void run() {
bVideoIsBeingTouched = false;
}
}, 100);
}
return true;
}
});
I know this is old but I used this:
mVideoView.setOnTouchListener(new View.OnTouchListener()
{
#Override
public boolean onTouch(View v, MotionEvent event) {
Log.i(TAG, "Video 1 clicked, starting playback");
return false;
}
});
I know this is and old question, but here is what I did:
Since setOnClickListener is not been triggered, I created my own class which extends VideoView
public class VideoViewCustom extends VideoView{
and Overrided the onTouchEvent
#Override
public boolean onTouchEvent(MotionEvent ev) {
if(ev.getAction() == MotionEvent.ACTION_DOWN){
Log.d(TAG, "ACTION_DOWN");
}
return super.onTouchEvent(ev);
}
and now I can get the onClick event with the MotionEvent.
Hope this helps someone!
This is probably long overdue, nonetheless of some help to those who may run into a similar problem. The way I got around this problem was by laying a transparent image view right on top of the video view, then listening to onClick events on the image view, and doing whatever it was I wanted to do with the video view afterwards.
I realize this is an old question but thought I'd chime in with an easy workaround. I can't answer why this doesn't work - seems like a big oversight in my opinion. But an easy workaround is to place your VideoView as the sole View inside a FrameLayout, and set an OnClickListener on the layout. Not ideal, but it works.
You can well use a button which is transparent on the video view if you want a specific part of the video on touch to do something.
You can solve this issue through cover layout.
I used the linearlayout.
<LinearLayout
android:id="#+id/video1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center">
<VideoView
android:id="#+id/video2"
android:layout_width="370dp"
android:layout_height="180dp"
android:layout_gravity="center"
app:elevation = "0dp"
android:background="#mipmap/video"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:visibility="visible"
/>
</LinearLayout>
and try it in source file.
video1.setOnClickListener {
if(Video.isPlaying) {
Video.pause()
}
else {
Video.start()
}
}
The VideoView is a wrapper containing MediaPlayer and SurfaceView. You can interact with through MediaController or writing your own SurfaceView and implement onClick events.
You might try Gesture Overlay View
You should be able to overlay this view on top of another view in order to get touch events.
Hope this helps!
It is possible I have did this with onSetClickListener. And Here's a code for your help:
mVideoView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
//Here you put a condition for playing a video when you click on your video view.//
if(my_video.isPressed())
{
my_video.start();
} else {
Toast.makeText(getApplicationContext(),
"Not able to run This Video!",
Toast.LENGTH_LONG).show();
}
}
});