I have a simple button onClickListener in my android application, and all it does is write some stuff to the database. It looks something like this
private void setEventListeners(){
mSpecialViewClass.getSubmitButton().setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
handleSubmitClick();
}
});
}
private void handleSubmitClicks(){
if (counter<0){
writeCounterToDb();
} else {
//do some stuff
closeDatabase();
}
}
now this works nicely, but if I tap the button fast enough, I get a closed DB error
java.lang.IllegalStateException: database not open
How can I prevent the key listener from doing anything, before the previous key event has been handeled?
Edit: some user suggested closing my database on Activity.onDestroy() which is quite nice, and he deleted the answer. That is a nice workaround for my problem, but still not the solution I am looking for.
I also tried disabling the button and enabling the button on various positions, and the problem remains. It seems I can always achieve that the function gets called one too many times, if I tap the button too fast.
A good UI trick, that you could possibly use here, is to disable the button once the user clicks. Just do something like this:
#Override
public void onClick(View arg0) {
arg0.setEnabled(false);
handleSubmitClick();
}
You can of course enable the button at the end of your onClick function if you need to.
While the button is disabled the user won't be able to click on it, so you will never get two onClick events. What is more, the style of the button changes, so the user will know that clicking won't do anything.
This technique is used all over the place (Gmail's send button for instance) and I consider it good UI design.
Now if you want to permit your user to press a button multiple times, really really fast and never loose or skip a single press, you'll need to implement some sort of a queuing mechanism. But I can only imagine this being necessary in games where there is a matter of life and death :)
Related
a simple issue here, but one I haven't been able to find a simple solution for. My Android app has a button that calls a calculations-heavy method which may take a while to return results. I want the user to know that the app is working, not frozen, so upon hitting that button I want to display a textView with a loading message, then call the method and load its results to another textView (while also hiding the first one). How can I make sure the method is started only AFTER the loading message becomes visible, because the code below fires the method when it's still not visible?
buttonCalculate.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
loadingMessage.setVisibility(View.VISIBLE);
findSolution();
}
});
you are looking for a Progress Bar, it's a an android feature that android made for you.
Here is a link for the official google site: https://developer.android.com/reference/android/widget/ProgressBar
I usually would just throw a Toast message to let them know they should wait, without having to use progress bar, for example when button is clicked it will display a message saying"please wait,loading"
inside the button Toast.makeText(this, "Loading,Please Wait", Toast.LENGTH_SHORT).show();
and you then can change the lenght of how long it should appear, lenghtshort is just 2 seconds
I have an app where I animate some views on click.
However while the animation is going on it's still possible to initiate other on click events, which in the end cause multiple problems with the animations. I would need to make it so that no new animation starts while a certain one is going on.
Let's say the animation shuffles clickable views on screen. How do I make it so that the user can't initiate a new click command for x amount of time, where x could be the duration of the animation, or some other solution with similar results.
I'm just not even sure what I'm looking for when it comes to terminology. What areas should I look into to manipulate user inputs like this? Any good source on the topic would also be welcome.
You can always disable the click event with a flag and enable it again when the animation has finished. It isn't a perfect solution, but it does the trick quite well in most cases.
For example, if you are using an Animator for your animation, you can do something like this:
private boolean isClickEnabled = true;
...
#Override
public synchronized void onClick(View v) {
if (isClickEnabled) {
// We disable the click, which will be enabled again when the animation ends
isClickEnabled = false;
...
animator.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
// We enable the click again now that the animation has finished
isClickEnabled = true;
}
});
animator.start();
}
}
The same applies for when you use the Animation class, but with the AnimationListener instead.
Please note that, instead of saving a local boolean, you could just disable and enable the click on the view using view.setClickable(true/false) – it really depends on what you need and on your implementation, but the basic idea remains the same.
if you want to block the touch for some time try to Implement Runnable or runonuithread and than whatever view you want to block use mathod called view.setClickable(false).
I'm trying to develop a feature for my app that pulls a string of text off of the internet (sort of like twitter, but a lot more basic) and displays it on the screen in a permeanent window. The user sees a large box with a refresh button next to it, and a small space below both where I would like to have a little progress monitor (just a TextView) which displays "Refreshing..." as soon as the refresh button is clicked, and then "Refresh successful!" once the string of text has been successfully pulled from the internet and displayed. This is just to reassure the user that something is actually happening when they press the button.
After a lot of research I've come to the conclusion that the way to update the TextView is to use a handler to execute a runnable which will update the text in the TextView. So my code looks like this:
refreshbutton.setOnClickListener(new View.OnClickListener()
{
public void onClick(View abc)
{
//display "Refreshing..."
refreshhandler.post(refreshingmsg);
/*Code to pull the string of text from the internet goes here (not shown)*/
//display "Refresh successul!"
successfulhandler.post(successfulmsg);
//clear the "Refresh successful" message after 2 seconds
clearhandler.postDelayed(clearmsg, 2000);
}
});
I hope that sort of makes sense. My issue is that these things all happen at once: I want the "Refreshing..." message to display, THEN for the phone to connect to the internet to find the string of text for the update, and THEN for the "Refresh Successful" message to display once the internet string has been successfully displayed. But what actually happens is that none of the commands in the onClick method actually happen until the phone has already pulled the message from the internet so the "Refreshing..." message isn't displayed at all. So what actually happens when the user clicks the button is that nothing happens for a second or two (presumably because the phone is busy pulling the string from the internet), then the string from the internet is suddenly displayed along with the message saying "Refresh Successful!".
So why is this happening? Is onClick supposed to work this way? If so, is there a workaround? I haven't posted my runnable and handler statements because I'm not sure it'll make any difference... but if it would help then I can post them!
Also, you can probably tell from this that I haven't been doing android (or indeed java) for very long, but I'm trying my best so please be gentle! Thanks :)
What is happening is that your code is locking on the network communication and doesn't let your app update itself with the handler value.
You should create an AsyncTask to that work for you.
On the OnPreExecute method, change your UI to show the user that you are refreshing your content. Reading your code it appears that you are updating an image, do that here.
On the doInBackground method do your actual network communication, an optional step is to use onProgressUpdate(Progress...) to update your UI to notify the user that the operation is progressing.
On the onPostExecute method you them update your UI to reflect the new content.
For more info check the documentation in AsyncTask, you can also search StackOverflow, there's a lot of good questions about it here.
As a side note, I don't recommend that you use handlers at all, AsyncTasks are easier to use and the code looks better.
There's a button in my program that, when clicked, accesses a huge database and takes a second or two to do that, and then disappeaars. During that waiting time, I would like the button's text to change to "LOADING..." or something. I tried
myButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
myButton.setText("LOADING...");
//then do other stuff
}
but of course lines of code aren't executed sequentially like that, so the text doesn't show up (or, shows up so quickly before disappearing that it isn't noticeable). Is there a simple way to do this? The only thing that comes to mind is using a Timer but (1) I'm not really sure how and (2) that seems overly complicated for just one simple line of code like that.
You need to use AsyncTask for your database access. In the runInBackground() you need to set your button to show "loading". You could refer to this - http://developer.android.com/reference/android/os/AsyncTask.html
http://www.vogella.de/articles/AndroidPerformance/article.html#concurrency_asynchtask is also a really good tutorial to help you with what you are trying to do.
The problem is that everything is done on the UI thread, and the long database access blocks the UI thread and prevents the "Loading..." text to be displayed. You should perform the database operation outside of the UI thread. Read http://developer.android.com/resources/articles/painless-threading.html.
You could use a Handler to notify you when the Db query gets completed and change the text appropriately. For using Handlers, I referred this tutorial
Actually the text is changing, it just hasn't been rendered yet, try to invalidate() the button too. You can also just test it out by removing the long process after the button click. Also if you have a long process make sure its not on the main thread and possibly use a ProgressDialog
Set it up to load when the Db starts loading and Change to Finished When the load has stopped.
I'm facing a head-scratching moment similar to what this person (from Jan 2008) experienced when I realized that there is no cancel button in Android's progress dialog or spinners. It is now July 2009 and I've just installed the cupcake version of Android. Has this thing changed? If not, are you adding a cancel button into the dialogs and how do you do it?
not sure about the whole cancel button...i've heard reports of the onCancel() method not firing properly. my solution just consists of making a normal button on the dialog with a call to return whenever the button is pressed.
private void createCancelProgressDialog(String title, String message, String buttonText)
{
cancelDialog = new ProgressDialog(this);
cancelDialog.setTitle(title);
cancelDialog.setMessage(message);
cancelDialog.setButton(buttonText, new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int which)
{
// Use either finish() or return() to either close the activity or just the dialog
return;
}
});
cancelDialog.show();
}
then just use a simple call method from elsewhere in your activity
createCancelProgressDialog("Loading", "Please wait while activity is loading", "Cancel");
rather simple solution, but it does the trick ;)
also just to note that cancelDialog is an activity wipe variable, if you dont need to call it from elsewhere, then you should be able to get away with just limiting the scope of the variable to that method.
I'm no Android user or developer, but I think the answer given in the linked-to thread is pretty decent: there's a hardware "back" key on all Android devices. Users are supposed to know to press Back to back out of whatever activity they're currently in.
Thus, the UI designers feel it's unnecessary to include a GUI back/cancel button. This could be viewed as the UI application of the DRY principle; if there's already one way of doing something, that's enough.
The hardware key is the answer here. I'd be careful about generalising the DRY principle to UIs. There are plenty of cases where you need to hammer, hammer, hammer the same point to the user repeatedly via headings, body text, colours and images.
Users dont "read" UIs the way you read a novel. They scan read.
I can't speak for other apps, but in mine anything that might cause the UI thread to wait is executed in a seperate thread. The most I'll do is show a small progress spinner in the titlebar to let the user know something is going on in the background.
As an Android user, and developer, I can say, in my opinion, and based around my understanding of the platform, that there is a good reason for not having a cancel button by default on the cancel-free progress dialogs.
As a developer, these dialogs can not be cancelled by default, that is, you have to explicitely set them as cancelable.
This makes sense, because their purpose is to alert the user, via the UI thread, that some work is going on elsewhere that is important to the updating of the UI thread, before the user should continue their use of the application.
For example, when fetching a list of data to occupy an empty screen, there is nothing to interact with, and the user needs to be made aware that something is going on, and to expect there to be nothing available to interact with until this process is complete.
However, there may be cases, such as data retrieval from the internet, where the process is "sketchy" and due to connectivity issues, you may not be able to complete the request, and get stuck here.
This as a develop is where you enable the dialog to be cancel-able.
Now as a user, one that clearly understands the UI paradigm of Android, I know that if I want to go back to what I was doing before, or "cancel" the current operation, I should hit the back key.
As a user, it's no different to knowing that in Android, the menu key can often reveal hidden options, some times on a seemingly blank screen with no way to interact.
This is the behaviour a user expects, and the way the platform is designed. You could very well add a cancel button, but from a users perspective that understands their phone, this makes no difference, the back key is clearly the intended choice for this purpose.
Activities and UIs have a flow, you flow through activities and UI "screens" which are "stacked" and the back button essentially "pops" the last thing off the stack to return you to where you were previously. If you see the dialog as another of these activities, you want to pop it from the top of the stack to return to what is underneath, or an activity previous to that.
If a developer has a dialog that can not be cancelled by back, it is either, by design, for which there can, in cases, be very good reason for, or, it is poor development and an oversight on the devloper's part.