Ok, so, the first bug I'm going to tackle is canceling the timer when the "home" button is pressed - otherwise, it comes back in with the old timer still running. That's fixed; I put a cancel timer in on the on pause; but it raises another issue.
The 'nother issue is that, when the program is paused, it doesn't save the sequence of numbers of the current quiz. So, coming back in the quiz is regenerated. However, the number of questions asked isn't reset. So, I just have to reset the number of questions correct to zero on the pause. It's not the optimal solution, but it's pretty simple in that it doesn't involve persisting the randomized list to disk.
Ok, next? How about we take care of what happens when the end of the vocabulary list is discovered?
Ok, in "NextLevel", we have this:
appState.incrementQuizStartAndFinish(this);
So, this is the activity that displays a "congratulations - you have advanced to the next level" message. But, it should alos take care of coming to the end of the line. Probably, it should change the message to "congratulations - you have completed this level! Returning to beginning."
If i really feel ambitious, I could throw maybe some kind of animation in there, but I guess I just want to push the program out at this point.
Ok. That was straightforward enough.
Next? Ok, we'll tackle the automatic mode problem. the automatic mode should play all words in its level. But it's currently just doing the five or whatever is on its own level. What it has to do, is if automatic mode is set, it's got to save the start an end quiz number. Then, it has to reset the quiz start and end number to 1 and the total numbers in the quiz. Then, when it returns to quiz mode, it should restore the original start and end quiz numbers.
Actually, it turns out that I had it all set up, except for setting the start and end numbers to 1 and the total number of words on the level. Let's test it...
Actually, there was an issue with entered numbers overriding the automatically set numbers; but the best solution there was just to call finish, thus not allowing the "save" button to be pressed. Ok. That was right on time.
Ok, next? Oh, yeah. The trackball issue. For some reason, when I select with the trackball, it not the same as when I select with the touch. It thinks it's the wrong answer. Also, the highlight color, a kind of brown that I've put in, doesn't look good when mixed with the "correct" green color. It becomes a kind of brownish green. The problem is that there is some kind touch vs. non-touch mode in Android, which I read about once; I don't recall the specifics, but they are two different states and that introduces complexity. I wonder how big of a sacrifice it would be to take away the trackball? Another thing I don't like about it, it when I use it, it makes it easy to somehow accidentally exit the program. Since my recovery in quiz mode in the question display is somewhat less than optimal, I would prefer to minimize that also. But the main thing is at I don't think the feature is huge enough to justify the trackball - just because the phone has it doesn't mean I need to support it.
Well, now that I've talked myself into disabling the trackball, the question is, how do do it? Let's check.
Well, the only link I can really find is this:
http://stackoverflow.com/questions/3423948/disable-trackball-click-in-android
I've run into some difficulties with implementing a custom progress dialog.
// ok, so he wants to disable it on a custom progress dialog.
// I think I want to do it for a list class.
Even though an overlay intercepts touch events the
// what's an overlay?
user can still operate the trackball and click elements that are supposed to be disabled.
// right.
Is there any way around this?
Edit: here's a solution
//=====================================================================================
protected void showProgressIndicator()
{
progressIndicator_.show();
}
// ok - so his custom class possibly wraps a standard progress indicator...
//=====================================================================================
@Override
public boolean onTrackballEvent(MotionEvent event)
{
return progressIndicator_.getVisibility() == View.VISIBLE;
}
// Ok - so, if his custom class gets a trackball event, it returns true if
// the project indicator is visible, otherwise returns false. Why?
//==================================
===================================================
protected void hideProgressIndicator()
{
progressIndicator_.hide();
}
// this one just hides it.
An then in show method
//=====================================================================================
public void show()
{
setVisibility(VISIBLE);
// make it visible.
if (animationHandler_ != null)
return;
// not doing anything other than making it visible if there is already
// an animation handler
animationHandler_ = new Handler();
// then it post an animate task to it
animationHandler_.post(animateTask_);
// and request focus for this widget
requestFocus();
}
I don't really get it. He offers a further word of explanation. The offered solution first is shown, then his explanation.
Check the onTrackballEvent() method. Then try to directly returning true in the method without doing anything in it. This should kill the event right away.
// This sounds good but apparently has a flaw...
Your solution isn't precisely correct because the user can't navigate with the trackball that way but he can click it.
// So, although the trackball is disabled - the user can still click with it!
So if a button is focused he can still click it.
// So, what nothing can get the focus except a touch? Well, that's
// not true on the answer screen, but maybe that's ok.
The solution was just to request focus from the progress dialog and implement onTrackballEvent().
// So, he made sure to get the focus on what he wanted it to be on.
I think I'm just going to go with the initial try. It may be adequate for my purposes,
because when the user touches anything, it goes somewhere. Let's try.
Let's try it:
@Override public boolean onTrackballEvent(MotionEvent e) {
return true;
}
Yes, that's perfectly fine. Nice. Ok, I still have 12 minutes (I'm trying to work in 50 minute chunks). I want to linkify something. Let's see how fast I can get it done.
The problem with linkify is that it adds the pattern to whatever you give as the url. I want to be like an html address link, where you have the text highlighted, but the actual url is used when you click on it.
It looks like maybe I can do something with tranformUrl:
public abstract String transformUrl (Matcher match, String url)
Examines the matched text and either passes it through or uses the data in the Matcher state to produce a replacement.
// so it looks at the text, our uses the the Matcher to produce a replacement.
Parameters
match The regex matcher state that found this URL text
url The text that was matched
Returns
The transformed form of the URL
// This is a bit confusing. The input url, which I completely want to replace,
// looks like it will be changed by whatever is in matcher. Let's
// see if there is a an example.
Hmm. Nothing really.
Let's look at the matcher docs. Ok. This looks like it might help:
String replaceAll(String replacement)
Replaces all occurrences of this matcher's pattern in the input with a given string.
So, I just want to replace my name (which is in the pattern) with the url.
Oh, here's a link which give a general idea of how to use it:
http://stackoverflow.com/questions/6416055/linkify-android-transform-question
title.setText(titleText);
Linkify.TransformFilter transformer = new Linkify.TransformFilter() {
@Override
public String transformUrl(Matcher match, String url) {
return match.group(1);
}
};
Linkify.addLinks(title, userName, "content://user=", null, transformer);
But, where is the Matcher?
So, here's an example of Pattern:
// String convenience methods:
boolean sawFailures = s.matches("Failures: \\d+");
String farewell = s.replaceAll("Hello, (\\S+)", "Goodbye, $1");
String[] fields = s.split(":");
// Direct use of Pattern:
Pattern p = Pattern.compile("Hello, (\\S+)");
Matcher m = p.matcher(inputString);
while (m.find()) { // Find each match in turn; String can't do this.
String name = m.group(1); // Access a submatch group; String can't do this.
}
So, we create a pattern, and then match it. Then, we call find on it to match, and then call a method on it to return the string we want.
Ok, so, since it's an internal class to Pattern, matcher must be based on the pattern that was originally created. Even though it's not shown, in the SO sample, the name field has got to be a pattern. The API for linkify which includes the tranform is like this:
final static void
addLinks(TextView text, Pattern p, String scheme, Linkify.MatchFilter matchFilter, Linkify.TransformFilter transformFilter)
Applies a regex to the text of a TextView turning the matches into links.
So, let's try something like this:
Linkify.TransformFilter transformer = new Linkify.TransformFilter() {
@Override
public String transformUrl(Matcher match, String url) {
return match.group(1);
}
};
Linkify.addLinks(title, userName, "content://user=", null, transformer);
I was going to try something like this:
// pattern we want to match and turn into a clickable link
Pattern pattern = Pattern.compile("My Name");
Linkify.TransformFilter transformer = new Linkify.TransformFilter() {
@Override
public String transformUrl(Matcher match, String url) {
return match.replaceAll("lastnode");
}
};
// prefix our pattern with http://
Linkify.addLinks(paintingTitleText, pattern, "http://myurl/firstnode/", null, transformer);
But, it's taking "My name", deleting that, keeping the rest, then adding "lastnode" on the end.
So, we're back to just using the whole text as the link. That's ok - it's probably better, because the "my name" was splitting lines. This way, I can be sure it's on a separate line.
TextView paintingAuthorTextView = (TextView) findViewById(R.id.next_level_painting_author);
paintingAuthorTextView.setText("by KanjiSoft");
// pattern we want to match and turn into a clickable link
Pattern pattern = Pattern.compile("");
Linkify.addLinks(paintingAuthorTextView, pattern, "http://kanjisoft.com");
Ok, that's a wrap.
No comments:
Post a Comment