Android - BottomSheet not closing properly - java

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;
}
});
}

Related

KEYCODE_BACK doesn't work when pressed for the very first time

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;
}
});

Android: button fade out issue

I have created a button that fades in when it is being touched and fades out when it isn't. I was able to achieve this by using setAlpha in java. The code and the problem is shown below:
buttonPressed.getBackground().setAlpha(0);
buttonPressed.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View view, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
buttonPressed.getBackground().setAlpha(255);
buttonPressed.startAnimation(animationFadeIn);
return true;
} else if (event.getAction() == MotionEvent.ACTION_UP) {
buttonPressed.startAnimation(animationFadeOut);
return true;
}
return false;
}
});
The issue I have is whenever I release the button, the alpha is set to 0 before animationFadeOut is able to fully play, so the button does not fade back.
If I remove the line:
buttonPressed.getBackground().setAlpha(0);
then animationFadeOut will play but it will immediately go back to setAlpha(255).
How can I get animationFadeOut to play fully and have the button alpha be 0 when the user stops touching the button?
I think using setInterpolator() for fadeIn and fadeOut animation solves your problem.
eg:
Animation animationFadeIn = new AlphaAnimation(0, 1);
animationFadeIn.setInterpolator(new DecelerateInterpolator());
animationFadeIn.setDuration(1000);
Animation animationFadeOut = new AlphaAnimation(1, 0);
animationFadeOut.setInterpolator(new AccelerateInterpolator());
animationFadeOut.setDuration(1000);
I got his solution from this link and you can know more about AccelerateInterpolator here.
Currently unable to test it. But seems to be promising. Hope this helps!
Better not to set the alpha manually, use animators to set the alpha
// Define the animators
Animation fadeInAnimation = new AlphaAnimation(0.0f, 1.0f);
Animation fadeOutAnimation = new AlphaAnimation(1.0f, 0.0f);
// Duration of animation
fadeInAnimation.setDuration(1000);
fadeOutAnimation.setDuration(1000);
public boolean onTouch(View view, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
buttonPressed.startAnimation(fadeInAnimation);
return true;
} else if (event.getAction() == MotionEvent.ACTION_UP) {
buttonPressed.startAnimation(fadeOutAnimation);
return true;
}
return false;
}

Pressing multiple buttons at same time not detected

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

How to detect when button pressed and released on android

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.

How do I set an OnTouchListener for a relativeLayout?

I want to capture two events from a relativeLayout. When the user clicks it and when the user releases his click (like mousedown/mouseup)
rl.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
//
}
});
I tried setting up something like:
if(event == MotionEvent.ACTION_DOWN) {
}
But eclipse just throws an error about an incompatible operand type. Anyone who knows how to do this?
Try...
if (event.getAction() == MotionEvent.ACTION_DOWN) {
...
}

Categories