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?
Hello,
i created a widget that uses a service with wakelock to update and parse data from an xml and update the widget's ui so that items would rotate every few seconds (standard news feed widget).
the problem is that the ui stops updating after a few hours although the data keeps updating.
here's the code i am using to update the ui
Code:
mUpdateTimeTask = null;
mUpdateTimeTask = new Runnable()
{
public void run()
{
if(which_item+1 < Widget_titles.length)
which_item++;
else
which_item = 0;
if(Widget_which_item_ed != null)
{
Widget_which_item_ed.putInt("WIDGET_WHICH_ITEM", which_item);
Widget_which_item_ed.commit();
}
else
{
Widget_which_item = context.getSharedPreferences("WIDGET_WHICH_ITEM", Context.MODE_WORLD_WRITEABLE);
Widget_which_item_ed = Widget_which_item.edit();
Widget_which_item_ed.putInt("WIDGET_WHICH_ITEM", which_item);
Widget_which_item_ed.commit();
}
updateViews.setTextViewText(R.id.WidgetText, Widget_titles[which_item]);
updateViews.setTextViewText(R.id.WidgetPostTime, rightNow.get(Calendar.MONTH)+"/"+rightNow.get(Calendar.DATE)+"/"+rightNow.get(Calendar.YEAR));
manager = AppWidgetManager.getInstance(context);
manager.updateAppWidget(WidgetId, updateViews);
mHandler.removeCallbacks(mUpdateTimeTask);
mHandler.postDelayed(this, widget_interval * 1000);
}
};
mHandler.postDelayed(mUpdateTimeTask, widget_interval * 1000);
Log.i(TAG, "sliding update handler was configed");
i am really stuck and could really use help
Edit:
i managed to go around this problem by implementing the BroadCastReciever for the screen on/off intents as shown in a tutorial i found (i can't post it here - the forum won't let me-sorry)
and therefore the amount of time that the widget needs to run is much smaller.
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?
// This method is called at button click because we assigned the name to the
// "On Click property" of the button
public void myClickHandler(View view) {
switch (view.getId()) {
case R.id.button1:
RadioButton celsiusButton = (RadioButton) findViewById(R.id.radio0);
RadioButton fahrenheitButton = (RadioButton) findViewById(R.id.radio1);
RadioButton KelvinButton = (RadioButton) findViewById(R.id.radio2);
if (text.getText().length() == 0) {
Toast.makeText(this, "Please enter a valid number",
Toast.LENGTH_LONG).show();
return;
}
float inputValue = Float.parseFloat(text.getText().toString());
if (celsiusButton.isChecked()) {
text.setText(String
.valueOf(convertFahrenheitToCelsius(inputValue)));
celsiusButton.setChecked(false);
fahrenheitButton.setChecked(true);
} else {
text.setText(String
.valueOf(convertCelsiusToFahrenheit(inputValue)));
fahrenheitButton.setChecked(false);
celsiusButton.setChecked(false);
text.setText(String
.valueOf(convertCelsiusToKelvin(inputValue)));
KelvinButton.setChecked(true);
celsiusButton.setChecked(false);
Can anyone assist me with this? The error message I keep getting is "kelvinbutton is not resolved" and the second I need to have another else if statement but where do i put that at.
Thanks.
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.