With the Scratchpad finished, the next step was to get the regular notepad functionality working. Since I already had a working example, all I had to do was fit it into my existing codebase. This turned out to be fairly easy, and I had a half-working example after no more than an hour's work. Getting it working
well was another matter entirely.
For one, the text on the main screen was small, and only the text itself was responsive to touch input. If the title of a note was small, it was almost impossible to open (and if there was
no title, it was completely inaccessible). This fix taught me just how important it is to understand the built in Android layout rules. The "wrap_content" rule, for instance, can be a bad choice for setting the width of a view. So can "match_parent" if you aren't aware of what the parent view's width is set to. This is yet another area in which blindly following sample code can get you in trouble, when all of a sudden your GUI is lined up all wrong and you don't know why. I ended up re-evaluating the width and height of every View in every XML file in the app, since this forced me to justify each and every setting. By the end, I had everything looking the way I wanted it, and more importantly, I understood
why.
My initial porting attempt also broke a small (but handy) feature from the sample Notepad app; if there were no saved notes, a special "no notes" message was displayed instead. In my app, however, this message was displaying even when there were notes present. It turns out that this feature requires your app to be designed in a very specific fashion, which happened to be the case for the sample app, but not mine. Specifically, the
Activity in question needs to:
- Subclass Android's ListActivity class.
- The layout file associated with the Activity needs to contain one ListView and one TextView, and they must be id'ed using two of Android's standard View names - "list" and "no_notes".
Looking at my app, I knew that my layout file used different id names, and that my class only extended Activity. An easy fix to be sure, but there was another problem - could I still cram the Scratchpad
button onto the page? If I added it to the layout file, would it display? And even if it did, would the
ListActivity accomodate the code responsible for handling click input?
The answer to both of these questions is "yes" and "yes". By using a
ListActivity, you benefit from having a built-in ListView object to use, but you aren't married to it. Remember that you can technically associate any layout file to a ListActivity. It helps if some of the Views defined in the layout are structured in such a way to work well with the class, but even then you can still add more on top of it. Then, once you add extra buttons and gizmos, you simply write a click handler for each one. For me, this translated into an extra layout entry (for the Scratchpad button), and a single, small click handler. Nice and easy all around, and I learned a ton about how views and activities relate to each other.
After that, it was just a matter of making a few final touch ups, such as having the cursor appear at the end of the title when opening a note, and giving notes a default title when none is entered. All told, this phase of the work took almost as long as the last, but I got far, far more done.
I'd like to end this entry with a list of additional lessons learned. All told, this was a very rewarding experience, and I feel more motivated than ever after achieving this small success.
- For the first time, I used version control on a personal project. I'm using git, as I'm used to it from work, and it worked like a charm. When I tried to refactor the app to use a ListActivity, I created a new branch: it was nice to know that, should it not work, I could revert back to a working state.
- I'm planing on going back to this app at a later date, to make some improvements. Specifically, it could use better error handling, and it would be nice to have more flexible controls for adding/deleting/editing content. Perhaps even a home screen widget for displaying the Scratchpad.
- I ran into an issue using StringBuffer; namely, I was trying to reuse the same StringBuffer instance without cleaning it out, so it kept preserving its previous content. Ideally, what I should have been doing was creating a new object every time, but sometimes I still think like a C coder, and I considered that a waste of memory. Yeah yeah, there's garbage collection, I know, but wiping the buffer was trivial, and now I feel like I can go to sleep tonight.
- Next up, a tasks app. It'll be far more complicated, but even more useful too.