Hi I'm using the Soundpool Android to play a sound when I press a button. I wonder if it is possible to maintain this sound playing while the button is pressed.
Here you need to identify the touch events I mean ACTION_DOWN when the button is pressed and ACTION_UP when the user has lifted his finger. You can start playing the sound in when the ACTION_DOWN event occurs and stop it when the ACTION_UP events occur.
Now for catching these events on a button you will have to set onTouch listener on the button and implement it's onTouch() method. onTouch() method is where you will have to catch those events and play/pause the sound.
Here is a sample how you can implement this onTouch() method of the button:
btn.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch (View v, MotionEvent event)
{
switch(event.getAction() & MotionEvent.ACTION_MASK)
{
case MotionEvent.ACTION_DOWN:
//here you can start playing song
break;
case MotionEvent.ACTION_UP:
//here you can stop playing song
break;
}
return false;
}
});
Here you can notice that I have returned false to indicate the os that I am finished with the event and now you can handle the event. If you do not want the os to handle the touch event then return true which indicates that you have consumed the touch event.
I hope this will help.
Related
I need to play a certain sound as long as the user holds an ImageView pressed and pause it when the user stop holding it. Before doing anything with the MediaPlayer, I tried to test it with a Vibrator(please don't laugh at this point) object. I've implemented and set an OnTouchListener:
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
vib.vibrate(50);
break;
case MotionEvent.ACTION_MOVE:
/*--- no action required ---*/
break;
case MotionEvent.ACTION_UP:
vib.cancel();
break;
}
return false;
}
However, the vibrate action is only performed once, no matter how long I hold the ImageView pressed. I guess a MediaPlayer will react the same way. What am I doing wrong?
P.S. the press is detected correctly, because the Vibrator logs "cancel()" only after I release my finger.
It's stop because in function
vib.vibrate(50);
you set to 50 ms time in vibration check
void vibrate(long milliseconds)
Vibrate constantly for the specified period of time.
I think rest of your code is correct.
I am having trouble detecting the MotionEvent.ACTION_MOVE & MotionEvent.ACTION_UP events. I am intending to have a button when you press and hold, it automatically decreases an associated value, however I have not gotten to that point in coding because I cannot detect the UP event.
for (int position = 0; position < mListItems.size(); position++) {
LayoutInflater inflater = getLayoutInflater();
PilotSkillRow row = (PilotSkillRow) inflater.inflate(R.layout.pilotskillrow, mSkillListView, false);
Button skillminus = (Button) row.findViewById(R.id.skillminus);
skillminus.setOnTouchListener(new SkillButtonTouchListener(position, false));
....
}
I understand returning true on the on touch events means that the later ontouch events such as ACTION_MOVE and ACTION_UP should fire.
private class SkillButtonTouchListener implements OnTouchListener {
public SkillButtonTouchListener(int pos, boolean plus) {
...
}
public boolean onTouch(View view, MotionEvent motionevent) {
int action = motionevent.getActionMasked();
switch (action)
{
case MotionEvent.ACTION_MOVE:
Log.e("a", "MOVE EVENT");
....
return true;
case MotionEvent.ACTION_UP:
Log.e("a", "UP EVENT");
....
break;
case MotionEvent.ACTION_DOWN:
Log.e("a", "DOWN EVENT");
....
return true;
default:
break;
}
return false;
}
}
However, when I run the code, the DOWN even it displayed, but the MOVE and UP EVENTS simply are never displayed. Could it be related to the fact I have an inflated layout?
Anyone have any ideas what I am doing wrong?
Update: If I use the android debugger to connect to the button to check what is happening, the UP event fires when I step through after pressing the button. Probably because there is another process consuming the UP event?
Update 2: The problem is that the textview inside an inflated layout refuses to update. When I perform an invalidate event on the adapter, it will stop the currently processing touch events (no errors). I have another textview which I am able to manually update without the need of the adapter and this does not cause any problems. So it seems to be a problem specific towards RelativeLayout. I have a workaround to only invalidate the data during the ACTION_UP event but I'd rather update the textview on the fly.
The problem that i am having is I am using a touch listener for the onTouch event it seems that the touch is being called more than once when i just touch it once.
The following is my code
final TextView tv = (TextView)findViewById(R.id.TextView01);
tv.setOnTouchListener(new View.OnTouchListener() {
int count1 =0;
int count2=0;
public boolean onTouch(View arg0, MotionEvent event) {
Log.d("Code777","Touch is being called finger");
int i = event.getPointerCount();
if(i==1 )
{
if(count1==0)
{
Log.d("Code777","Touched with 1 finger");
count1++;
count2=0;
}
}
if (i==2 )
{
if(count2==0)
{
Log.d("Code777","Touched with 2 fingers");
edit.append(tv.getText());
count2++;
count1=0;
}
}
return true;
}
});
Am i doing something wrong ??
It prints the log more than 3-4 times for both single touch and double touch
The problem updated problem is that both the events are getting fired now
if(event.getAction() == MotionEvent.ACTION_POINTER_2_DOWN)
{
Log.d("Code777","2 finger touch");
return true;
}else if(event.getAction() == MotionEvent.ACTION_DOWN)
{
Log.d("Code777","Touched with 1 finger");
return true;
}
You're code will execute during every touch event. The first time it activates, it's likely do to an ACITON_DOWN event (when the user first touches the screen). The second time, it is likely do to an ACTION_UP event (when the user lifts the finger from the screen). Likewise, if you were to swipe your finger around the screen, the same code will execute many times for an ACTION_MOVE event. You have to check for the types of touches that it is. Do something like this:
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
// Do something that should only happen when the user first touches the screen
break;
case MotionEvent.ACTION_MOVE:
// Do something that should only happen when the user is touching the screen
break;
case MotionEvent.ACTION_UP:
// Do something that should only happen when the user stops touching the screen
break;
}
EDIT:
Multitouch in Android is odd at best. Not all devices can handle it. Not all device can handle more than x number of touches, etc. If you want to handle DOWN cases for individual fingers, then you can use the ACTION_POINTER_X items. If you were to have this series of events like so:
1. User touches screen
2. User touches screen with second finger
3. User lifts finger 1
4. User touches screen with finger 1
5. User lifts finger 2
6. User touches screen with finger 2
7. User lifts both finger 1 and finger 2
8. User touches screen with only finger 2
9. User touches screen with finger 1
The events that will be fired will be like this:
1. ACTION_DOWN
2. ACTION_POINTER_2_DOWN
3. ACTION_POINTER_1_UP
4. ACTION_POINTER_1_DOWN
5. ACTION_POINTER_2_UP
6. ACTION_POINTER_2_DOWN
7. ACTION_UP (also, one of the pointers actions will fire depending on which finger was lifted first)
8. ACTION_DOWN
9. ACTION_POINTER_2_DOWN
And so on.
An onTouchListener sends you multiple actions via MotionEvents. You can get the action for the current event with MotionEvent.getAction().
What you notice here is most likely that you get one ACTION_DOWN (a finger has been placed on the display) event followed by some small ACTION_MOVE events when you move the finger(s) slightly. In the end you will get ACTION_UP (a finger has been lifted) You can filter these out by ignoring events with the wrong action.
For example just return from onTouch() when a move event occured.
public boolean onTouch(View arg0, MotionEvent event) {
Log.d("Code777","Touch is being called finger");
if(event.getAction() == MotionEvent.ACTION_MOVE) {
Log.d("Code777", "Move event detected, ignored!");
return false;
}
// Further processing ..
}
or use a switch to differentiate between all relevant events.
See the MotionEvent class documentation for a list of possible actions.
.
How could I make my button to do the on click action even if the button is pressed and the finger is still on the screen (the button is not released). Or I would accept the solution that when a button is pressed and is not release, the other buttons on the layout to not be blocked.
Instead of using an OnClickListener consider using an OnTouchListener. You can then detect when the user's finger touches:ACTION_DOWN and releases ACTION_UP the button.
A method like this would probably work fine:
public boolean onTouch(View v, MotionEvent event)
{
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
//DISABLE THE OTHER BUTTONS
break;
case MotionEvent.ACTION_UP:
// RE-ENABLE THE OTHER BUTTONS
break;
}
return true;
}
One option would be to use the onmousedown event rather than the onclick event in your javascript:
myButton.onmousedown = myOnClickFunction;
Application have a GridView with a images. When user press image - looped sound start playing. When user releases image - sound must stop playing.
I cannot find the way to handle release event.
write touch event in getview method of adapter class. it will work.
public boolean onTouch(View arg0, MotionEvent e) {
switch(e.getAction()){
case(MotionEvent.ACTION_DOWN):
//the user put his finger down on screen
break;
case(MotionEvent.ACTION_MOVE):
//the user is moving with his finger down
break;
case(MotionEvent.ACTION_UP):
//the users finger is off the screen
break;
}
}