Sunday, August 31, 2014

Converting VB6 to Android: Die Roller - Finishing it off

I'll try to keep this short.  I added a custom keyboard, a listview to display results, and began converting the dice roller code into (poorly designed) objects.
The first thing I did was add move my routines into objects.  I started out with DiceEvalResult, and thing spiraled out of control from there.  I needed to be able to get all of the roll results, even if the routine had to recurse, so that I could display all dice that were rolled.

Once that was done, I added a ScrollView below my results text so that I could display the results.  The code was very simple, and I just instantiated a header textview, for the die function (such as "4d6") and then a results textview for each of the die rolls (4 in this case).

           for (int i = 0; i < result.DiceResults.size(); i++) {
               TextView newHeader = new TextView(this);
               newHeader.setTypeface(null, Typeface.BOLD);
               for (int j = 0; j < result.DiceResults.get(i).Dice.size(); j++) {
                   TextView newItem = new TextView(this);
 This worked fine, but didn't really have anything set off from the rest of the app.  Without even having a visible scroll bar, you couldn't tell it scrolled at all.  And note that I am adding my views inside of "lstResultsChild".  That's something to watch out for.  At first, when I clicked the ScrollView and named it "lstResults" in the UI properties panel, I found out I was naming a contained child control instead of the actual ListView.  I found it because my cast from findByViewId to (ScrollView) failed, since the child is a LayoutView.

I then wanted a keyboard.  I have "Hacker's Keyboard" installed on my android, but most people don't.  And switching back and forth between alpha and numeric views to type "2d6" is a pain in the butt.  So I found a custom keyboard example here, which I found via stack exchange.  As I read through it, I converted it into an object instead of routines in the main activity, and then found out that the author converts it to an object at the end as well, so my object model may not be the same as his.

I modified the keys by adding an extra row on top for the dice, including "%" for a calculation based on double d10s and a simple "d" for the user to create any other die calculation.  I kept his numbers, and changed the letters to mathematical operators.  I got rid of all of the images (because I just copied and pasted the code instead of downloading it), and changed the "all left" and "all right" buttons (home and end) to parenthesis.  Finally, I got rid of the Prev and Next buttons, which were meant to move focus to the next and previous editable, and added a "Roll" button to execute the evaluation code.

Once I got that done, I revisited the scroll view and I decided to refactor to a ListView.  I originally was going to try that anyway, thinking it may be closer to the vb6 listview.  I didn't because after seeing "ScrollView", I thought it may be implying that a ListView wouldn't scroll.

The ListView was more complicated, in that you first have to create a child view to display a single item.  This view will be used for each item that gets put in the list.  Then you have to create an "adapter" to populate a single instance of the child view with a single data member.  In my case, I went with 2 TextViews, and changed the die results to a comma-delimited list instead of putting them one result per row.  After finding the convoluted nature of this, I didn't want to nest another listview control to show the data.

Then, eclipse decided to screw me over.  When I tested the app, the custom keyboard would display, but wouldn't let me type anything.  It had worked before refactoring from ScrollView, so it had to be something to do with my ListView code.  I'm still not sure exactly what happened, but the error I ended up finding after digging through the log was telling me that it couldn't convert a ListView to a Keyboard.  I had added the ListView through the UI, not modifying the XML directly, and the ListView ended up being put below the keyboard.    I tried moving it back down, and nothing happened.  I figured the compiler had somehow associated an ID with a certain position, and had screwed something up, but I didn't know how to get to it.  To finally solve it, at 3 in the morning, I deleted the keyboard entry from the XML altogether, then compiled and let my Keyboard code fail because of the missing Id.  Then I pasted the Keyboard back in, and everything worked.  So it wasn't an issue with the code, but an issue with eclipse.  I suspect that it wasn't even an issue with the order of the elements in the XML (and know that nothing else was different).  I suspect that it boiled down to a caching issue.

Now, everything works.  I need to get rid of the "Hide" button altogether.  I don't need it since I am capturing the back button press anyway.  I would really like to find out how to change the on-screen back icon (if present) to be the same as when the built-in keyboard is up, but I haven't found that yet.  I also need to add an option to make it automatically roll the die as soon as you hit one of  die keys, for people that don't want to enter a longer expression.  Or maybe just roll a die as soon as it is detected even if you are writing an expression.  Then I would need some sort of delay timer so that the first press would clear whatever is currently in the textview, but only if it has been a certain amount of time since the last entry/evaluation.  But I'm probably not going to do any of this anytime soon.  I'm going to install the free version of Unity (which I've only recently discovered) and figure out how to create this same app in that.  Then I'll see if I can add some 3d rolling dice.  Hopefully, that will be a simple introduction to the system.

Below are links to the completed code and the apk for the app.  If you need to know how or why I did anything, just post in the comments.

No comments:

Post a Comment