Double Click Event - G1 Android Development

Hello everybody!
I do not know is this right place to ask this kind of question. If not, please move my topic to another forum.
I will be appreciate for explanation how to implement the double-click event for any object (eg. Button) from TextView class.
Thanks for any advice!

Your question doesn't really make much sense. Which control are you trying to catch the double-click event from? Button, or TextView? The control that is lowest in the view hierarchy that implements the method will catch it. Is the Button placed in an extended TextView? Or is the TextView in an extended Button?

Maybe my question wasn't precise. I would like to know how to implement the double-click listener for Button or TextView or EditText.

since you arent asking for a specific way to do it this is super rough and will not work; Just give you and idea. This is how I would do it atleast
Code:
private int numberOfClicks = 0;
....yada yada yada
//onClickListener {
numberOfClicks++;
if(numberOfClicks >= 2) {
// Call the method you want to call when the user double clicks
numberOfClicks = 0;
}
}
... yada yada yada

Burlyskink said:
since you arent asking for a specific way to do it this is super rough and will not work; Just give you and idea. This is how I would do it atleast
Code:
private int numberOfClicks = 0;
....yada yada yada
//onClickListener {
numberOfClicks++;
if(numberOfClicks >= 2) {
// Call the method you want to call when the user double clicks
numberOfClicks = 0;
}
}
... yada yada yada
Click to expand...
Click to collapse
This is a bad way to do it, since there is no timeout. If a user presses once and then waits 30 minutes and pesses again it will count as a double click. A better way would be log the millisecond timestamp when they click and then check it with the previous timestamp. If new_stamp-old_stamp < x milliseconds then it's a double tap, else it is a single tap.
That's assuming you can't just add a listener for a double tap even dispatch. I don't know if there is one because I've never needed it, but I will take a look.
Edit:
There is no double click event you can attach to, so you'd be wanting to do one of two things:
First is similar to previously posted code, but would be better to do this:
Code:
private double _millis = 0;
private static final int DOUBLE_TAP_TIMEOUT = 500; //half a second to wait for double tap
...etc...
//onClickListener {
if(0==_millis)
{
_millis = getTimeMillis();
setTimeout(DOUBLE_TAP_TIMEOUT,onTimeout);
}
else
{
cancelTimeout(); //This is second tap so cancel timeout until single tap is accepted
if(getTimeMillis()-_millis<=DOUBLE_TAP_TIMEOUT)
{
onDoubleTap(); //do double tap func
_millis=0; //reset millis
}
else
{
//millis is > 0 but this is first tap. Either millis wasn't reset or timeout func was not called
//Throw exception, handle error or do some default action
_millis = 0; //reset millis so next click is first
}
}
}
//onTimeout {
//User tapped, then didn't tap again before the timeout was over
_millis = 0; // reset millis
onClick(); // do single tap func
}
}
Problem with this method is that your millis, timeout and other double-tap centric functions are going to be in the parent class, therefore defeating the whole point of OOP. A far better way would be to create an inherrited class that is based on button/textview/whatever and override the code for detecting clicks. Then do pretty much the same thing as above but instead of calling your onClick/onDoubleclick internals, you'd call the callback that was passed in during setOnClickListener/setOnDoubleClickListener (you'd have to create the setOnDoubleClickListener yourself but if you look at setOnClickListener it'd be pretty much c&p)
Oh and note that the above is pseudocode - you can't run it.

Looking in Google, analysing, I found the best solution - I think. It's short and easy... It use not OnClickListener, but OnTouchListener, but is very similar to TomasTrek proposition. I will past it, maybe next time it will help somebody...
Code:
public class TestProject extends Activity {
private long lastTouchTime = -1;
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
Button button = (Button)findViewById(R.id.Button01);
button.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View arg0, MotionEvent mev) {
if(mev.getAction() == MotionEvent.ACTION_DOWN) {
long thisTime = System.currentTimeMillis();
if (thisTime - lastTouchTime < 250) {
lastTouchTime = -1;
//code to perform
} else {
lastTouchTime = thisTime;
}
}
return false;
}
});
}
}
What do you think?

gmadajczak said:
Looking in Google, analysing, I found the best solution - I think. It's short and easy... It use not OnClickListener, but OnTouchListener, but is very similar to TomasTrek proposition. I will past it, maybe next time it will help somebody...
Code:
public class TestProject extends Activity {
private long lastTouchTime = -1;
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
Button button = (Button)findViewById(R.id.Button01);
button.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View arg0, MotionEvent mev) {
if(mev.getAction() == MotionEvent.ACTION_DOWN) {
long thisTime = System.currentTimeMillis();
if (thisTime - lastTouchTime < 250) {
lastTouchTime = -1;
//code to perform
} else {
lastTouchTime = thisTime;
}
}
return false;
}
});
}
}
What do you think?
Click to expand...
Click to collapse
That looks like a winner, but I would suggest changing the code to look for the up event. Google engineers have changed the way some things work internally, and most of the new functions check on the up event. The reason this changed was to better work with soft buttons on the screen (such as the capacitive touch buttons on the face of the new Droid).
So, let me suggest changing:
Code:
if (mev.getAction() == MotionEvent.ACTION_DOWN)
to
Code:
if (mev.getAction() == MotionEvent.ACTION_UP)

rpcameron said:
That looks like a winner, but I would suggest changing the code to look for the up event. Google engineers have changed the way some things work internally, and most of the new functions check on the up event. The reason this changed was to better work with soft buttons on the screen (such as the capacitive touch buttons on the face of the new Droid).
So, let me suggest changing:
Code:
if (mev.getAction() == MotionEvent.ACTION_DOWN)
to
Code:
if (mev.getAction() == MotionEvent.ACTION_UP)
Click to expand...
Click to collapse
Thanks!
Another question. How to convert this code to custom Listener OnDoubleClickListener?

TomasTrek said:
This is a bad way to do it, since there is no timeout. If a user presses once and then waits 30 minutes and pesses again it will count as a double click. A better way would be log the millisecond timestamp when they click and then check it with the previous timestamp. If new_stamp-old_stamp < x milliseconds then it's a double tap, else it is a single tap.
That's assuming you can't just add a listener for a double tap even dispatch. I don't know if there is one because I've never needed it, but I will take a look.
Edit:
There is no double click event you can attach to, so you'd be wanting to do one of two things:
First is similar to previously posted code, but would be better to do this:
Code:
private double _millis = 0;
private static final int DOUBLE_TAP_TIMEOUT = 500; //half a second to wait for double tap
...etc...
//onClickListener {
if(0==_millis)
{
_millis = getTimeMillis();
setTimeout(DOUBLE_TAP_TIMEOUT,onTimeout);
}
else
{
cancelTimeout(); //This is second tap so cancel timeout until single tap is accepted
if(getTimeMillis()-_millis<=DOUBLE_TAP_TIMEOUT)
{
onDoubleTap(); //do double tap func
_millis=0; //reset millis
}
else
{
//millis is > 0 but this is first tap. Either millis wasn't reset or timeout func was not called
//Throw exception, handle error or do some default action
_millis = 0; //reset millis so next click is first
}
}
}
//onTimeout {
//User tapped, then didn't tap again before the timeout was over
_millis = 0; // reset millis
onClick(); // do single tap func
}
}
Problem with this method is that your millis, timeout and other double-tap centric functions are going to be in the parent class, therefore defeating the whole point of OOP. A far better way would be to create an inherrited class that is based on button/textview/whatever and override the code for detecting clicks. Then do pretty much the same thing as above but instead of calling your onClick/onDoubleclick internals, you'd call the callback that was passed in during setOnClickListener/setOnDoubleClickListener (you'd have to create the setOnDoubleClickListener yourself but if you look at setOnClickListener it'd be pretty much c&p)
Oh and note that the above is pseudocode - you can't run it.
Click to expand...
Click to collapse
Oh my, your right! I didn't even think about that lawl. Good catch, atleast it may have given him a path to start with xD

gmadajczak said:
Another question. How to convert this code to custom Listener OnDoubleClickListener?
Click to expand...
Click to collapse
The code I posted the change to had the OnTouchListener() method that was created. After the Button is created, it then has the OnTouchListener() method defined inline when setOnTouchListener() is called. This is the same method you use to handle any touch event event on that particular control.
How does it need to be converted to listen for double-taps, when that is what the example code is looking for?

Related

[Q] OnKey error

Check this class below,
______ My Code _______
public class Main extends Activity implements OnKeyListener {
DisplayWord currentWord;
TextView wordStatus;
EditText inputWord;
Button okBtn;
int pos = 1;
char currentChar;
char inputChar;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
currentWord = (DisplayWord) this.findViewById(R.id.trueWord);
currentWord.setText("Bonjure"); // word from database
wordStatus = (TextView) this.findViewById(R.id.wordStatus);
inputWord = (EditText) this.findViewById(R.id.wordInput);
inputWord.setOnKeyListener(this);
}
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (inputWord.getText().toString().length() <= currentWord.getText().toString().length()) {
pos = inputWord.getText().toString().length();
currentChar = currentWord.getText().toString().charAt(pos);
inputChar = inputWord.getText().toString().charAt(pos);
} return false;
}
}
_____ END _____
When running this code, upon entering data into the input box it causes an exception straight away and for the program exit unexpectedley.
I am trying to extract the input word from EditText field and the word stored in a TextView and to compare them char by char as those chars are entered into the input box, sort of a word game, where the character will be highlighted green if it is correct and red if it is not.
I have no idea why this behaviour happens, I can see in debugger an StringIndexOutOfBounds exception, and a ResourceNotFound when I have been tampering with different ways of attempting this, access position or the char array, it always seems to throw an exception.
Any advice or links appreciated,
AnthonyI am trying to post a copy and paste of just text, no links but validation error on starting a new thread is telling me that I cannot submit a message with a link in it? I want to show everyone a simple class because of some problem's i'm having.. any ideas?

[Q] Alarm app [eternal cycle]

Hi,
I programming with Alarm app from zero. Need help with time check:
I want:
Minute (mm) is alarm time. In textBox is text "Silent", when is mm time, then in textBox need show "Alarm!!!". Ok.
I added button to set alarm time, when button_click:
Code:
private void Button_Click(object sender, RoutedEventArgs e)
{
DateTime myValue = DateTime.Now;
if (myValue.Minute.ToString() == mm)
textBox.Text = "Alarm!!!";
}
This working, when I click button, but need set to all time (eternal cycle).
If use cycle "while":
Code:
private void Button_Click(object sender, RoutedEventArgs e)
{
DateTime myValue = DateTime.Now;
while (myValue.Minute.ToString() != mm)
{ textBox.Text = "Silent"; }
textBox.Text = "Alarm!!!";
}
Working, but while != mm I can't do anything else - Button is pressed.
Question:
where need input first code or otherwise need do this cycle?
No ideas?

[Q] Android Dev - Handling Enter...

Since I don't have access to the android software forum yet, and searching hasn't come up with any results (maybe I'm missing something) I'm going to post here...
I'm developing an app and I'm in a testing phase with about 6 testers all using different devices. I've run into an issue with one tester where the code that handles the use of the Enter key in an EditText box doesn't work. I've gone about this three different ways but with no luck. All three methods work fine on my device:
Method 1:
Code:
TextView.OnEditorActionListener keyListener = new TextView.OnEditorActionListener(){
public boolean onEditorAction(TextView view, int actionId, KeyEvent event) {
if(actionId == EditorInfo.IME_NULL){
if(((EditText)findViewById(view.getId())) == ((EditText)findViewById(R.id.etUser))){
((EditText) findViewById(R.id.etPass)).requestFocus();
}
if(((EditText)findViewById(view.getId())) == ((EditText)findViewById(R.id.etPass))){
logon();
}
}
return true;
}
};
Method 2:
Code:
EditText etUserName = (EditText) findViewById(R.id.etUser);
etUserName.setOnKeyListener(new OnKeyListener() {
public boolean onKey(View view, int keyCode, KeyEvent event){
if (event.getAction() == KeyEvent.ACTION_DOWN){
switch (keyCode)
{
case KeyEvent.KEYCODE_DPAD_CENTER:
case KeyEvent.KEYCODE_ENTER:
if(((EditText)findViewById(view.getId())) == ((EditText)findViewById(R.id.etUser))){
((EditText) findViewById(R.id.etPass)).requestFocus();
}
return true;
default:
break;
}
}
return false;
}
});
Method 3:
Code:
TextView.OnEditorActionListener keyListener = new TextView.OnEditorActionListener(){
public boolean onEditorAction(TextView view, int actionId, KeyEvent event) {
if(actionId == EditorInfo.IME_ACTION_NEXT) {
((EditText) findViewById(R.id.etPass)).requestFocus();
}
if (actionId == EditorInfo.IME_ACTION_DONE) {
logon();
}
return true;
}
};
Since I don't have physical access to the device, after the last method I wrote some code into the app to notify the tester if the event's actually being triggered. Nothing. So what the hell is going on here? The tester's handset is an Xperia Arc with stock 2.3.2 and she doesn't have an issue with the enter key in other apps. Is there another method that is more fool proof then relying on inconsistent IME action ids or key codes?

[Q] Control cursor PC by WP7

I want to control the PC cursor by WP7, so I try to use the ManipulationDelta in WP7 that can help me to calculate the difference between he star tap and the end tap
Code:
public MainPage()
{
InitializeComponent();
this.ManipulationDelta += new EventHandler<ManipulationDeltaEventArgs>(MainPage_ManipulationDelta);
transformG = new TransformGroup();
translation = new TranslateTransform();
transformG.Children.Add(translation);
RenderTransform = transformG; // you see I don't use any transform here because I don't know where I put. If I use the image.RenderTransform of it will move also for the screen of WP if I put this.RenderTransform, So anyone have a solution
SenderSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
}
void MainPage_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)
{
startX = e.ManipulationOrigin.X;
startY = e.ManipulationOrigin.Y;
DeltaX = e.DeltaManipulation.Translation.X;
DeltaY = e.DeltaManipulation.Translation.Y;
translation.X += e.DeltaManipulation.Translation.X;
translation.Y += e.DeltaManipulation.Translation.Y;
EndX = Convert.ToDouble(translation.X);
EndY = Convert.ToDouble(translation.Y);
}
I am juste want to send DeltaX and DeltaY to the server to calculate them to the mouse position in the screen, So I write this code
Code:
void StartSending()
{
while (!stop)
try
{
SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs();
byte[] buffer = Encoding.UTF8.GetBytes(DeltaX.ToString() + "/" + DeltaY.ToString());
socketEventArg.SetBuffer(buffer, 0, buffer.Length);
SenderSocket.SendToAsync(socketEventArg);
}
catch (Exception) { }
}
I concatenate them in 1 buffer with separate by "/" and in server I use this code to separate
Code:
void Receive(byte[] buffer)
{
string chaine = "";
if (SenderSocket != null)
{
SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs();
socketEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(delegate(object s, SocketAsyncEventArgs e)
{
if (e.SocketError == SocketError.Success)
{
chaine = Encoding.UTF8.GetString(e.Buffer, e.Offset, e.BytesTransferred);
chaine.Trim('\0');
string[] pos = chaine.Split('/');
for (int i = 0; i < pos.Length; i++)
{
pX = Convert.ToInt32(pos[0]);
pY = Convert.ToInt32(pos[1]);
this.Cursor = new Cursor(Cursor.Current.Handle);
Cursor.Position = new Point(Cursor.Position.X + pX, Cursor.Position.Y + pY);
}
}
else
{
}
});
SenderSocket.ReceiveFromAsync(socketEventArg);
}
Just I want to control the cursor, if you have any other methods so plz help me and I am really grateful
Didn't you already have a thread about this? Please re-use existing threads instead of starting new ones. Even if it wasn't you, *somebody* was working on this problem already, and very recently. Always use the Search button before starting a thread.
So... what are you looking for from us? Does your current code work? If not, in what way does it fail? Without knowing what your question is, we can't provide answers.
If you want some advice, though...
Sending as strings is very inefficient on both ends; it would be better to use arrays (which you could convert directly to byte arrays and back again).
You're sending as TCP, which is OK but probably not optimal. For this kind of data, UDP is quite possibly better. If nothing else, it provides clearly delineated packets indicating each update.

Popup box Help

So i have created a pop up window with the source code below. I also have designed the popup really good. and it displays right. The only problem i have is the damn button to close it. lol I had it so it closed fine before. Then i started adding stuff in to make the app work the way i want it to.
So What i have done is this, I have the popup created i want to be able to have the Text box checked for a string if this string exists then I need to go to thread allApps which then launches my 2nd Activity which that works fine as well. But the problem is the damn pop uup is still up so i need to close this. Any way of doing this with using the code I have or do i need to redo something. Please Any help thanks
PHP:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
final Button btnOpenPopup = (Button)findViewById(R.id.apps_button);
btnOpenPopup.setOnClickListener(new Button.OnClickListener(){
@Override
public void onClick(View arg0) {
LayoutInflater layoutInflater
= (LayoutInflater)getBaseContext()
.getSystemService(LAYOUT_INFLATER_SERVICE);
View popupView = layoutInflater.inflate(R.layout.popup, null);
final PopupWindow popupWindow = new PopupWindow(
popupView,
LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
popupWindow.showAtLocation(btnOpenPopup, Gravity.CENTER, 0, 0);
}});
}
public void allApps(View arg)
{
Intent intent = new Intent(arg.getContext(), AppList.class);
startActivity(intent);
}

Categories

Resources