I must catch in an android project, if two buttons are pressed or not. I have created an OnTouchListener and implemented onTouch(). However, only the first pressed button is detected, when I press two buttons at same time.
#Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.game_layout);
mShootButton = (Button) findViewById(R.id.btn_shoot);
mAccelerateButton = (Button) findViewById(R.id.btn_accelarate);
MyTouchListener touchlistener = new MyTouchListener();
MyTouchListener touchlistener2 = new MyTouchListener();
mShootButton.setOnTouchListener(touchlistener);
mAccelerateButton.setOnTouchListener(touchlistener2);
super.onCreate(savedInstanceState);
}
public class MyTouchListener implements OnTouchListener {
#SuppressLint("ClickableViewAccessibility")
#Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN && v.getId() == R.id.btn_shoot){
setmShootButtonPressed(true);
}
else if(event.getAction() == MotionEvent.ACTION_UP && v.getId() == R.id.btn_shoot){
setmShootButtonPressed(false);
}
if(event.getAction() == MotionEvent.ACTION_DOWN && v.getId() == R.id.btn_accelarate){
setmAccelerateButtonPressed(true);
}
else if(event.getAction() == MotionEvent.ACTION_UP && v.getId() == R.id.btn_accelarate){
setmAccelerateButtonPressed(false);
}
return true;
}
}
N.B.: My phone is multitouch, I've checked.
Try android:splitMotionEvents="true" on the layout that contains the buttons.
Explaination: Android buttons are not designed to be touched at the same time. One of them will consume the touch event and the layout container will not call the onTouch event of the other button.
As an alternative you could create a custom view that handles the click detection logic for both buttons.
See: Android work multitouch button
Related
I'm banging my head with this problem which probably is simple but since I'm new to this topic I somehow haven't been able to figure it out yet.
I've successfully implemented dragging a view with onTouch method. I've also successfully implemented onLongClick and onClick methods. But both of these functionalities were implemented separately.
The problem, like the title says is when I want to join these functionalities. I want the onTouch method to be called when a user long clicks a view and I want a new activity to start when a user clicks a view.
Here is the pseudo code:
public class Website extends AppCompatActivity implements View.OnTouchListener{
TextView longpress;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_website);
longpress = (TextView) findViewById(R.id.longpress);
longpress.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View view){
//I don't really know how to do this part
onTouch(View view, Motion Event event);
return true;
}
});
longpress.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
//Code for new activity comes here (I know how to do this part)
}
});
}
public boolean onTouch(View view, MotionEvent event) {
switch(event.getAction(){
case MotionEvent.ACTION_DOWN:
//Save initial coordinates of view <-- view.getX(), view.getY()
break;
case MotionEvent.ACTION_MOVE:
//Calculate dX and dY and setX and Y of the view (move view)
break;
case MotionEvent.ACTION_UP:
//If view is certain distance away from initial points do something
break;
}
}
}
Like I said, onTouch works on itself if I don't try to call it from onLongClick method. If I try to call onTouch(View view, MotionEvent event) from onLongClick method the problem occurs because onLongClick only receives one out of two arguments onTouch method should receive (onLongClick only receives view argument but it should also receive event argument).
Maybe I'm trying to do this in a totally wrong way but I have been looking at some documentation e.g. https://developer.android.com/training/gestures/ but still won't get an idea what to do.
(I would like to have a similar functionality to notifications on android phones)
So I've come to a solution which might or might not be a good one but for now it serves my functionality. If someone has a better solution and thinks mine is bad in some way please say so.
Here is the code:
boolean flag;
public boolean onTouch(View view, MotionEvent event){
int action = event.getAction() & MotionEvent.ACTION_MASK;
if(action == MotionEvent.ACTION_DOWN){
//do something on a down press
flag = true;
return true;
}
if(action == MotionEvent.ACTION_UP && flag == true){
//do something if we move finger away from screen we
//didn't move the view first
return true;
}
if(action == MotionEvent.ACTION_UP && flag == false){
//do something if we move finger away from screen and we moved
//the view before we moved the finger away from screen
}
if(action == MotionEvent.ACTION_MOVE){
//do something when moving the view
flag = false;
}
I'm having trouble overriding the Back Button press on Android.
The thing is, everything works perfectly except for the very first time.
When I load the app and press the back button for the first time, it pauses the app, which is NOT what I want. Other than that, it works as expected.
My code:
private void setupDeviceButtons(){ // this is ran at the very beginning (onViewCreated())
// setting up a listener to close the menus when the back button is pressed
View view = getView();
Log.e(TAG, "This happens when I load the app" );
if (view != null) {
Log.e(TAG, "This also happens when I load the app");
view.setOnKeyListener((v, keyCode, event) -> {
if (keyCode == KeyEvent.KEYCODE_BACK) {
Log.e(TAG, "But this doesn't happen when I press the back button for the first time.");
// we filter all actions that are not key down
if (event.getAction() != KeyEvent.ACTION_DOWN)
return true;
...
}
return false;
});
} else {
Log.e(TAG, "ERROR on setupDeviceButtons(): Unable to set back button behaviour. View is null.");
}
}
Any thoughts?
Thank you in advance
Use the below code working perfectly in fragments.
//on fragment back pressed
view.setFocusableInTouchMode(true);
view.requestFocus();
view.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction()== KeyEvent.ACTION_DOWN) {
// do your code on back pressed
return true;
}
return false;
}
});
Situation : I have a BottomSheet that expands on a button click (fig. 1), on the upper right corner of the BottomSheet I put an ImageView that works as a closing button, in other words when the ImageView is clicked the Bottomsheet state will be changed to HIDDEN
what I tried :
I tried to assign the imageview an onTouchListener (check code take #1) but I got a NullPointerException mainly because the bottomsheet was hidden and the imageview is not visible to user so I tried adding an if to check if the bottomsheet state is expanded and if so do the closing stuff (check code take #2)
Code take #1
//this is where I got the NullPointerException
CloseSheet.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN){
}
else if(event.getAction() == MotionEvent.ACTION_UP){
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
}
else if(event.getAction() == MotionEvent.ACTION_CANCEL){
}
return true;
}
});
Code take #2
//this is where I dont get a response on click
if(bottomSheetBehavior.getState() == BottomSheetBehavior.STATE_EXPANDED ){
CloseSheet.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN){
}
else if(event.getAction() == MotionEvent.ACTION_UP){
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
}
else if(event.getAction() == MotionEvent.ACTION_CANCEL){
}
return true;
}
});
}
I would like to start a timer that begins when a button is first pressed and ends when it is released (basically I want to measure how long a button is held down). I'll be using the System.nanoTime() method at both of those times, then subtract the initial number from the final one to get a measurement for the time elapsed while the button was held down.
(If you have any suggestions for using something other than nanoTime() or some other way of measuring how long a button is held down, I'm open to those as well.)
Thanks!
Andy
Use OnTouchListener instead of OnClickListener:
// this goes somewhere in your class:
long lastDown;
long lastDuration;
...
// this goes wherever you setup your button listener:
button.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN) {
lastDown = System.currentTimeMillis();
} else if (event.getAction() == MotionEvent.ACTION_UP) {
lastDuration = System.currentTimeMillis() - lastDown;
}
return true;
}
});
This will definitely work:
button.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN) {
increaseSize();
} else if (event.getAction() == MotionEvent.ACTION_UP) {
resetSize();
}
return true;
}
});
In onTouchListener start the timer.
In onClickListener stop the times.
calculate the differece.
I am setting OnTouchListener to a Button, I can check if motion type is MotionEvent.ACTION_MOVE. On the other hand if it is TextView, I cannot get any moment of MotionEvent.ACTION_MOVE
For example take a look at the code below:
public boolean onTouch(View view, MotionEvent me) {
if (me.getAction() == MotionEvent.ACTION_DOWN) {
Log.e(TAG,"1");
}
if (me.getAction() == MotionEvent.ACTION_UP) {
Log.e(TAG,"2");
} else if (me.getAction() == MotionEvent.ACTION_MOVE) {
Log.e(TAG,"3");
}
return false;
}
if I bind this listener to a Button, I can see "3" in my logs, on the other hand, if I bind this to an ImageView or etc. I cannot see any "3". but "1" and "2" are acting normal for both situation.
So the question is (if I am not mistaken) which items are MotionEvent.ACTION_MOVE sensitive?
Try implementing OnClickListener also..like this..and put onClick empty.. I think it then detects ACTION_MOVE, along with ACTION_UP and ACTION_DOWN..
class MyActivity implements View.OnTouchListerner, View.OnClickListener{
.....
public void onClick(View v) {}
.....
}
Textview doen't hava any MotionEvent ActionMove, http://developer.android.com/reference/android/widget/TextView.html..
Thanks...