Anyone have a work around to get this set up? I have a spinner in my action bar where I'd like to capture a long click event, either OnLongClickListener, or for the individual item OnItemLongClickListener - so the user can edit the value.
I've read that spinner doesn't support long clicks, but I was hoping that something might have changed/someone might have a workaround.
It's the ideal solution for editing the string - there's not enough space in the action bar to put a dedicated button for editing, and my users intuitively try to long press to edit.
Here are some related questions (although quite old now):
Android spinner item long click/touch,
How can I use spinner setOnItemLongClickListener
You should be able to "simulate" a long click with the following code:
final Handler actionHandler = new Handler();
final Runnable runnable = new Runnable() {
#Override
public void run() {
Toast.makeText(Activity.this, "Long click performed", Toast.LENGTH_SHORT).show();
}
};
spinner.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
actionHandler.postDelayed(runnable, 1000);
} else if(event.getAction() == MotionEvent.ACTION_UP){
actionHandler.removeCallbacks(runnable);
}
return false;
}
});
Yo can play around with the time in order to get a more "real" feeling, but that's pretty it i believe.
I hope it helps
Related
I have a button that runs a code that changes the background to a random color on each click. I would also like to give the user the ability to keep on changing the background color as long as the button is clicked. I believe that the onTouchListener will be my best bet. However, I do not now how to implement the code correctly.
I tried on the onLongClickListener but found out that onLongClickListener doesn't work that way.
Incomplete code for the onTouchListener (randomize is the name of my button):
randomize.setOnTouchListener(new Button.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN){
// start the thread
return true;
} else if(event.getAction() == MotionEvent.ACTION_UP){
// stop the thread
return true;
}
return false;
}
});
So, what I aim to be able to do is to keep on pressing the button and having the background continuously change while still preserving the onclick method of the button. So, onclick changes the background once and continuous click changes the background continuously.
Thank you so much folks :)
Ps. I'm just a beginner to android so I'm sorry if I do not know much. :)
try this:
btn.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
count++;
Toast.makeText(getApplicationContext(),Integer.toString(count) , Toast.LENGTH_SHORT).show();
return true;
}
});
When i use an onTouchListener in the getView of my adapter the line
android:listSelector="#drawable/circle"
immediately stops working, if I set onTouch to return false it works again, however then the ACTION_DOWN ACTION_UP dosent work properly.
Heres what i have in onTouch
image.setOnTouchListener(new View.OnTouchListener() {
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
Assets.playMusic(songID, false);
} else if (event.getAction() == MotionEvent.ACTION_UP) {
Assets.mediaPlayer.stop();
Assets.mediaPlayer = null;
}
return true;
}
});
Its suppose to play music for as long as you have a finger held on the item and when you release it should stop the music. And it works well when returning true. However for some reason the circle stops appearing behind the tapped items. If it is set to false the circle appears, but then action_up dosent stop the music
ive tried using .setSelected .setActivated .setEnabled and none of them work
please help
Also i want it to work kinda like snapchats camera button, tap it and it does one thing, hold it and it does something for duration of your hold. I was going to use time variables in the Action up and down. but if anyone knows another way to do this id appreciate info about that too
In this situation is not encouraged to attach an OnTouchListener to the image, but to the items of the GridView instead.
You should have something like this:
GridView gridview = (GridView) findViewById(R.id.the_gridview_id);
gridview.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, final View v, int position, long id) {
doSomething();
}
});
EDIT:
In order to know how much time a view is pressed, you can do something like this:
// this goes somewhere in your class:
long lastDown;
long lastDuration;
...
// this goes wherever you setup your button listener:
gridview.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;
}
}
};
PROBLEM
I have a horizontalListView that is showing user all the images loaded to ViewPager. Its situated on the bottom of the screen.
What I want to do is for horizontalListView to hide when its not being used for more then 5 sec.
How it should work:
User taps screen horizontalListView appears
User scrolls, selects do stuff on horizontalListView and its blocking threads to be fired
After 5 sec of doing nothing on horizontalListView, it disappears
How its working right now:
User taps screen horizontalListView appears
User scrolls, selects ect. and postDelayed is getting fired making my horizontalListView dissappear.
CODE
HorizontalListView and Runnable
horizontalListView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
hideViewHandler.removeCallbacks(mRunnable);
hideViewHandler.postDelayed(mRunnable,5*1000);
return true;
}
});
mRunnable = new StoppableRunnable() {
#Override
public void stoppableRun() {
hideAnimation();
}
};
TapListener that is set on Image responsible for showing horizontalListView
private class TapGestureListener extends GestureDetector.SimpleOnGestureListener {
#Override
public boolean onSingleTapConfirmed(MotionEvent e) {
hListView.clearAnimation();
if (((ViewGroup.MarginLayoutParams) hListView.getLayoutParams()).bottomMargin < 0) {
expandAnimation();
hideViewHandler.postDelayed(mRunnable,5*1000);
} else {
hideAnimation();
}
return true;
}
}
You have to check inside the listener for the MotionEvent.ACTION_UP or MotionEvent.ACTION_CANCEL to only trigger the runnable after them.
Your current code is posting the runnable on any event, but you want to do it only when the user has stopped using the view.
BTW: If you return true from the TouchListener it means that you have consumed the event and the event chain will stop. Most likely the ScrollView will not even scroll, since the event will not be propagated to it.
You can do something like this..
yourScreenLayout.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (horizontalListView.getVisibility() == View.INVISIBLE) {
horizontalListView.setVisibility(View.VISIBLE);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
if (horizontalListView.getVisibility() == View.VISIBLE)
horizontalListView.setVisibility(View.INVISIBLE);
}
}, 5000);
} else {
horizontalListView.setVisibility(View.INVISIBLE);
}
}
});
I think the source of you problem might be calling removeCallbacks before postDelayed.
The thread itself is fired after u clear the queue.
I have managed to fix the problem myself.
FIX
The main reason why my onTouchListener did not work as intended was that it had not been triggered at all. OnClickListener inside horizontalListView adapter was consuming the trigger.
Now I am passing the info that the click occurred inside onClickListener and do all the things in different method.
I am trying to make some field with text (no button) what I click on to open datepicker dialog.
I am totally begginer and I am trying it on easy example.
firstbirth.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
Toast.makeText(getApplicationContext(), "ahooj", Toast.LENGTH_LONG).show();
return false;
}
});
firstbirth is spinner, I tried it with Edittext and the result was same.
Can anybody help me?
Thanks in advance!
Use an OnClickListener instead.
setOnClickListener(View.OnClickListener l)
OnTouchListeners will trigger on multiple touch events (like touch down, touch up etc.) whereas the OnClickListener will only get fired once (onClick :) )
If you, for some reason, want to use an OnTochListener you can make sure that its only called once.
Try:
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_UP { // another option would be ACTION_DOWN for example
Toast.makeText(getApplicationContext(), "ahooj", Toast.LENGTH_LONG).show();
return true;
}
return false;
}
Thanks it sounds logical but when I use OnClick event application felt down while initializing.
firstbirth.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
DialogFragment dd1 = new DatePickerFragment();
dd1.show(getFragmentManager(), "Select a date");
}
});
Problem is not with DialogFragment becasue it works when I use onTouch event.
Thanks :)
I'm using an opensource numberpicker I found somewhere (credit to Jeffrey F. Cole) but I just found a bug.
The numberpicker has a handler to increase the number faster when you touch the button
long`private Handler repeatUpdateHandler = new Handler();
`
class RepetetiveUpdater implements Runnable {
public void run() {
if (autoIncrement) {
increment();
repeatUpdateHandler.postDelayed(new RepetetiveUpdater(),
REPEAT_DELAY);
} else if (autoDecrement) {
decrement();
repeatUpdateHandler.postDelayed(new RepetetiveUpdater(),
REPEAT_DELAY);
}
}
}
.....
public class NumberPicker extends LinearLayout {
.....
// Auto increment for a long click
increment.setOnLongClickListener(new View.OnLongClickListener() {
public boolean onLongClick(View arg0) {
autoIncrement = true;
repeatUpdateHandler.post(new RepetetiveUpdater());
return false;
}
});
// When the button is released, if we're auto incrementing, stop
increment.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP && autoIncrement) {
autoIncrement = false;
}
return false;
}
});
The problem is when you longclick the button the counter starts to increase, but when you hold your finger down and drag your finger across the screen the counter keeps adding up, even when you lift your finger.
So how can I detect that the finger gets out of my numberpicker layout and stop the counter?
Thx :)
I'm not so sure that's a bug and I'm not even sure it's coming from changes that this number picker made on top of the numberpicker from the API itself. I'm assumings that the buttons that handles incrementing and decrementing the pickers are set up to keep going until an ACTION_UP MotionEvent is received, but this might be over-simplifying it.
EDIT:
I've tested this on stock Android 2.3.3 and this is precisely the result.
EDIT:
Based on your clarification in the comments, this does sound like a pretty bad bug. Looks like what you need to do is have the Handler removes the callbacks to that runnable in ACTION_UP. Can you link me to the project so I can try to submit a patch?
EDIT
The NumberPicker you provided wasn't using Handlers correctly, IMO. Instead of keeping a reference to the same Handler so that callbacks could later be removed, it was created a new one everytime it posted. I've made some changes and fixed the issues here: https://gist.github.com/3657989