I'm trying to use setontouchlistener. What I would like to do if I hold an imagebutton for an example 5 seconds, I get alerted... this is how I would do it:
final ImageButton imageButton1 = (ImageButton) findViewById(R.id.imageButton1);
imageButton1.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
// do something
return false;
}
});
How can I implement something like this with setontouchlistener after x seconds?
Working solution:
imageButton1.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
mTouchDownTime = event.getEventTime();
Log.v("CustomDebug", "Message: " + mTouchDownTime);
}
if (event.getAction() == MotionEvent.ACTION_UP) {
long elapsedTime = event.getEventTime() - mTouchDownTime;
Log.v("CustomDebug", "Message: " + elapsedTime);
}
return false;
}
});
onTouch gets called twice, the first time with a MotionEvent ACTION_DOWN and a second time with the MotionEvent ACTION_UP
so pseudocode:
if Event == ACTION_DOWN
saveTime = time();
elseif Event == ACTION_UP and time()-savetime > 5
doStuff because the guy hold it for 5sec.
Related
I want to get the X & Y coordinates of the location where i long click and set the button to this location, but i don't get it because there is no MotionEvent as with the onClick method.
private View.OnLongClickListener layoutOnTouchListener(){
return new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
RelativeLayout.LayoutParams positionRules = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
positionRules.leftMargin = (int) v.getX();
positionRules.topMargin = (int) v.getY();
mainButton.setLayoutParams(positionRules);
Log.d("X", String.valueOf(v.getX()));
return true;
}
};
}
Thats the code i tried.
You can try setonkeyListener and check whether it's long click or not
#Override
public boolean onKey(View view, int i, KeyEvent keyEvent) {
if (null != keyEvent && keyEvent.getAction() == KeyEvent.ACTION_DOWN) {
if (System.currentTimeMillis() - mLastClickedTime > DEFAULT_PRESSED_DELAY) {
Log.d(TAG, "onKey: single presed");
onKeyPressed(view, keyEvent);
} else {
Log.d(TAG, "onKey: repeat pressed");
onKeyRepeatPressed(view);
}
mLastClickedTime=System.currentTimeMillis();
}
return false;
}
If it's long click take the x and y points
I have an ImageView which fills my whole Activity. I need to be able to detect 4 touch events :
Hold (longer than 400 ms)
Click
Swipe Left
Swipe Right
At the moment I am able to detect the first two using the following code :
imageView.setOnTouchListener(new View.OnTouchListener() {
private Timer timerr = new Timer();
private long LONG_PRESS_TIMEOUT = 400; // TODO: your timeout here
private boolean wasLong = false;
#Override
public boolean onTouch(View v, MotionEvent event) {
Log.d(getClass().getName(), "touch event: " + event.toString());
if (event.getAction() == MotionEvent.ACTION_DOWN) {
// HOLD DETECTED
timerr.schedule(new TimerTask() {
#Override
public void run() {
SlideShow.this.runOnUiThread(new Runnable() {
#Override
public void run() {
}, LONG_PRESS_TIMEOUT);
return true;
}
if (event.getAction() == MotionEvent.ACTION_UP) {
if (!isPaused && !wasLong) {
// CLICK DETECTED
timerr.cancel();
timerr = new Timer();
if (!wasLong) {
return false;
}
});
Now I am trying to use the code from this question to implement the swipe right and swipe left actions. Android Swipe on List The problem with this is that this works on listview, where you can implement an onTouchListener for the whole listview, and a seperate onItemClickListener for the list item. I do not know how to adapt this to this situation though where only one Listener is available.
Gesture Detector is the way to go.
Alternatively,
image.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
x1 = event.getX();
y1 = event.getY();
t1 = System.currentTimeMillis();
return true;
case MotionEvent.ACTION_UP:
x2 = event.getX();
y2 = event.getY();
t2 = System.currentTimeMillis();
if (x1 == x2 && y1 == y2 && (t2 - t1) < CLICK_DURATION) {
Toast.makeText(getActivity(), "Click", Toast.LENGTH_SHORT).show();
} else if ((t2 - t1) >= CLICK_DURATION) {
Toast.makeText(getActivity(), "Long click", Toast.LENGTH_SHORT).show();
} else if (x1 > x2) {
Toast.makeText(getActivity(), "Left swipe", Toast.LENGTH_SHORT).show();
} else if (x2 > x1) {
Toast.makeText(getActivity(), "Right swipe", Toast.LENGTH_SHORT).show();
}
return true;
}
return false;
}
In my activity I have an ImageView. It has pinch-zoom feature.
When I touch on ImageView I show thumbnails layout.
But when I pinch on ImageView thumbnail layout shows. I want to block it?
How can I do it?
Here is my code to show thumbnail layout:
image.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
Boolean openThumbnails=true;
if(event.getAction() == MotionEvent.ACTION_UP && openThumbnails){
Log.e("event.getAction()", "MotionEvent.ACTION_UP");
if(thumbnailsLayout.getVisibility()==View.GONE && header.getVisibility()==View.GONE && openThumbnails){
thumbnailsLayout.setVisibility(View.VISIBLE);
header.setVisibility(View.VISIBLE);
header.bringToFront();
}
else{
thumbnailsLayout.setVisibility(View.GONE);
header.setVisibility(View.GONE);
}
}
else if(event.getAction() == MotionEvent.ACTION_DOWN){
Log.e("event.getAction()", "MotionEvent.ACTION_DOWN");
return true;
}
else if(event.getAction()==MotionEvent.ACTION_MOVE){
Log.e("openThumbnails before", openThumbnails.toString());
openThumbnails=false;
Log.e("openThumbnails and after", openThumbnails.toString());
}
return false;
}
});
Your openThumbnails is always true. You set it at the start of method. Every touch event (e.g. Action_up, action_move) you set openThumbnail to true. That's why you always show it.
image.setOnTouchListener(new OnTouchListener() {
Boolean openThumbnails=true;
#Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_UP && openThumbnails){
Log.e("event.getAction()", "MotionEvent.ACTION_UP");
if(thumbnailsLayout.getVisibility()==View.GONE && header.getVisibility()==View.GONE && openThumbnails){
thumbnailsLayout.setVisibility(View.VISIBLE);
header.setVisibility(View.VISIBLE);
header.bringToFront();
}
else{
thumbnailsLayout.setVisibility(View.GONE);
header.setVisibility(View.GONE);
}
}
else if(event.getAction() == MotionEvent.ACTION_DOWN){
Log.e("event.getAction()", "MotionEvent.ACTION_DOWN");
return true;
}
else if(event.getAction()==MotionEvent.ACTION_MOVE){
Log.e("openThumbnails before", openThumbnails.toString());
openThumbnails=false;
Log.e("openThumbnails and after", openThumbnails.toString());
}
return false;
}
});
I have an application that has a layout with ~150 editText's and a mainActivity that has an onClickListener for each of these editTexts, and a button which loops through them all and clears them.
The application was running fine, and without making any significant changes I am now getting the following logCat error everytime i start up the application:
Out of memory on a 2903056-byte allocation.
Is there any obvious bad practices I am doing here that is causing the memory loss?
Some of my code below as illustration (this is repeated many times obviously)
box0101.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
txtHint.setText(hintPrefix + onOneClick);
return false;
}
});
box0301.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
txtHint.setText(hintPrefix + onOneClick);
return false;
}
});
box0401.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
txtHint.setText(hintPrefix + onOneClick);
return false;
}
});
box0501.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
txtHint.setText(hintPrefix + onOneClick);
return false;
}
});
box0601.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
txtHint.setText(hintPrefix + onOneClick);
return false;
}
});
and also some buttonclick listeners that set off some loops
btnClear.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
clearBoard();
}
});
public void clearBoard() {
final int ROW_COUNT = 14;
final int COL_COUNT = 9;
final String ROWS[] = {"01","02","03","04","05","06","07","08","09","10","11","12","13","14","15"};
final String COLS[] = {"01","02","03","04","05","06","07","08","09","10"};
for(int i=0; i<ROW_COUNT; i++) {
for(int j=0; j<COL_COUNT; j++) {
String a = ROWS[i];
String b = COLS[j];
int editTextId = getResources().getIdentifier("box" + a + b , "id", getPackageName());
EditText et=(EditText)findViewById(editTextId);
et.setText("");
}
}
}
As #alex.veprik mentioned: try to use one OnClickListener, and assign it to all your EditText-objects. If you create a new OnClickListener for every EditText-object, although they all do the same, this will eat a lot of your memory.
Example)
View.OnTouchListener boxListener = new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
txtHint.setText(hintPrefix + onOneClick);
return false;
}
});
//boxes is a list of all your boxes
for(int i=0; i < boxes.size(); i++) {
boxes.get(i).setOnTouchListener(boxListener);
}
It might also be wise to put the creation of your EditText-objects in a loop, and to store only the list of all boxes in a member variable. So instead of having 150 variables, you now only need one for the list, while at the same time keeping all the references. (this doesn't affect your memory problem, but it's good code style)
List<EditText> boxes = new ArrayList<EditText>();
for (int i = 0; i < NBR_OF_BOXES; i++) {
boxes.add(new EditText());
}
As #zapl recommended, it might also be good to use a memory profiler.
Instead of having a onTouch() method for each EditText, use a switch statement to create a case for each EditText, using the EditText ID
public boolean onTouch(View v, MotionEvent event) {
switch(v.getId())
{
case R.id.editTextID:
//Do something, etc
}
return false;
}
I'm trying to call the onTouch method from a different class but I have no idea what to pass in for MotionEvent. Using null makes the app force close. Heres the code
public final class Touch {
private static final String TAG = Touch.class.getSimpleName();
public boolean onTouchEvent(MotionEvent event, Droid droid, Thread thread) {
if (event.getAction() == MotionEvent.ACTION_DOWN)
{
droid.handleActionDown((int)event.getX(), (int)event.getY());
/*if (event.getY() > getHeight() - 50)
{
thread.setRunning(false);
((Activity)getContext()).finish();
}
else
{
Log.d(TAG, "Coords: x=" + event.getX() + ",y=" + event.getY());
}*/
}
if (event.getAction() == MotionEvent.ACTION_MOVE)
{
// the gestures
if (droid.isTouched())
{
// the droid was picked up and is being dragged
droid.setX((int)event.getX());
droid.setY((int)event.getY());
}
}
if (event.getAction() == MotionEvent.ACTION_UP)
{
// touch was released
if (droid.isTouched())
{
droid.setTouched(false);
}
}
return true;
}
}
Thats the class, how would I call that in the main thread? Currently I'm trying:
public void Touch()
{
MotionEvent event = null;
touch.onTouchEvent(event, droid, thread);
}
As null is the only thing that I can think of to pas in.
Try:
MotionEvent event = MotionEvent.obtain(downTime, eventTime, action, x, y, metaState);