I found this handy post to the Android developer’s group, which explained how to get the equivalent behaviour to Apple’s flexible spacer views on toolbars.
The implementation in a layout XML file looks like this:
<LinearLayout android:id="@+id/ToolBar" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="wrap_content"> <View android:layout_width="0px" android:layout_weight="1" android:visibility="invisible"/> <Button android:layout_height="wrap_content" android:layout_width="wrap_content" android:background="@drawable/homebuttonselector" android:id="@+id/HomeButton"/> <View android:layout_width="0px" android:layout_weight="1" android:visibility="invisible"/> <Button android:layout_height="wrap_content" android:layout_width="wrap_content" android:background="@drawable/nextbuttonselector" android:id="@+id/NextButton"/> <View android:layout_width="0px" android:layout_weight="1" android:visibility="invisible"/> </LinearLayout>
Note the use of the layout_weight property for the hidden views. This tells the layout code to take whatever space is leftover from the non-weighted views (the two buttons) and divide it evenly amongst all the other views set to a weight of 1. You could play with this to do other goofy layouts as well. This is much handier than using padding, or even relative layouts to achieve the same effect because it allows you to leave the calculations up to the layout code rather than you figuring out at runtime what the padding should be. Especially if you’re adding/removing views depending on context.
UPDATE:
After playing with this a little more I actually went with this solution, which makes it even easier to programmatically show/hide the buttons.
<LinearLayout android:id="@+id/ToolBar" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="wrap_content"> <RelativeLayout android:id="@+id/Button1Layout" android:layout_height="wrap_content" android:layout_width="wrap_content" android:layout_weight="1"> <Button android:layout_height="wrap_content" android:layout_width="wrap_content" android:background="@drawable/button1selector" android:id="@+id/Button1" android:layout_centerHorizontal="true"/> </RelativeLayout> <RelativeLayout android:id="@+id/Button2Layout" android:layout_height="wrap_content" android:layout_width="wrap_content" android:layout_weight="1"> <Button android:layout_height="wrap_content" android:layout_width="wrap_content" android:background="@drawable/button2selector" android:id="@+id/Button2" android:layout_centerHorizontal="true"/> </RelativeLayout> </LinearLayout>
With this version to show/hide buttons all you have to do is set the visibility for the layout group the button resides in to Visibility.GONE or Visibility.VISIBLE. You don’t have to worry about having the proper arrangement of empty views to the left and right of the button.
This PC World article does a good job discussing the new Apple ToS that dictate using third party tools to generate iPhone apps is a no-no.
I agree, it’s definitely a move against Flash. However, as a business person when you’re planning a project and doing your business plan and get to that risk section are you really going to gloss over the huge possibility that Apple could at any moment say that the major technology you’re relying on is not allowed anymore?
I have a license for Unity3D and Unity basic for iPhone. I’m very bummed out, because there’s no way I’m going to use them now. It’s not worth the risk. The difficulty in rolling your own 3D solution is now outweighed by the risk of relying on a technology that could be completely blocked from use.
If you wanted to make a bunch of money right now, all you need to do is write a 3D graphics engine for the iPhone and follow it up with a book on how to use it and tutorials for it and what not. You’d sell many a copy that’s for sure. Every graphics programmer I know has their own little “pet” engine project they putter away on. Just put the polish on it you lazy bums and get it out there! Native Objective-C of course!
Man sucks to be those guys. Their only option now I suppose is to be better or different. Hopefully differently better.
The new OS means quite a few things for me. I’ve got to decide whether it makes economic sense to revisit Photo Resize for one, they added some mechanisms to improve access to the photo library, and it seems like you can now preserve meta information (i.e. geotags). I may consider making these improvements and releasing it with advertisements. For Prescriber’s Letter there’s also some major new issues with the new OS. The big one being the fact that apps don’t shut down anymore (like on the Android), and so if you had one time operations you used to do on initial load / quit you’ve now got to figure out how to place those in your new flow of “going to sleep” and “waking back up”. Luckily we’ll have this figured out for the Android and have time to decide how we want to address things like re-authenticating the user, checking for new content, etc…
I’ve been working away with major blinders, supremely focused on building the Activity class model properly for the Android port of Prescriber’s Letter. I’m working on the menu system currently, how the list view of menu items gets filled out from the XML menu structure, how activities are spawned to present the various selected menu items, issues like that. I’m trying my best to get it right the first time, which takes a lot of googling, book reading and planning to make sure I’m doing things properly the “Android way”.
Some things have been easier to do on Android than they were on the iPhone version, for example the special custom label classes I had to write for the iPhone to display text with mixed normal and italic typefaces. On Android this is MUCH simpler to do. You can select spans of text in a text view and apply styles, colors, etc. to the span. On the iPhone I had to build the custom label class that basically appended labels to each other, each one set to display its particular style. Being able to rely on the built-in components is nice, it will make all the other follow on things much simpler (supporting different screen dimensions, supporting landscape and portrait orientations, etc.).
iPhone OS 3.2 is a thorn in my side that I’m glad I don’t have to worry about just at the moment. They snuck in a requirement for Snow Leopard on this version, which I think is plain ridiculous. There can’t possibly be any good reason for it to require Snow Leopard. This is flat out just a plain money grab by Apple to force all of us developers to upgrade. It bothers me to no end, I have no need to upgrade to Snow Leopard. It doesn’t offer me any features that I place any value in. All it does is waste my time and money.
Well milestone 1 is complete and everything’s going well. There was quite a bit of OT needed for the milestone just due to every task coming in more towards the high estimate than the average estimate I use to set milestone deadlines. Lots of unexpected trickiness to an unfamiliar platform to blame of course. The biggest problem was getting the download of the content bundle to work quickly. On my dev phone 2 (which is an unlocked HTC Magic) the download of a 6.5MB file takes 10 minutes or more. On the client’s Nexus One it takes about 10 seconds. It takes only a few seconds more on an Android developer that lives in New York’s Nexus One that helped me debug the issue on the Android beginners Google list.
I’m not sure what makes it so slow on my device, but I’ll definitely need to find out, otherwise I’ll be wasting too much time in development waiting for bundles to install.
Debugging on the Android emulator is brutally slow, so I’m doing all of my debugging directly on my Android Dev Phone 2. When you’re doing a lot of back and forth between writing code / testing it gets annoying picking it up and putting it down. I have solved the problem, and I can officially sell my solution to approximately 5 more people. Behold:
Yeah, that’s right. It’s the end of an eraser taped to my desk which allows me to prop my device up against the desk. I say that I can sell 5 more of these to interested parties because that’s about how much eraser I have left to chop bits off of.
I’ve been working on downloading and installing the content bundle for the Android version of Prescriber’s Letter. I’ve got the whole process working perfectly, however I’ve found that the system is extremely slow on the emulator. It takes an extremely long time to unzip the bundle, to parse the XML for the string table included in the bundle, and generally any file operations I’m doing. I’ll definitely need to Google this issue and find out where I’m going wrong performance-wise.
One thing I did was switched to BufferedInputStream and BufferedOutputStream, as I read that these would have better performance, which makes sense to me. I’ve adjusted the buffers to generally be able to hold the average file size entirely in the buffer, in the hopes that this reduces the final flush to the file to a single hit to the file system. I’m not sure whether it works like that internally, but I can hope!
Part of me suspects there’s just something funky going on with the emulator. I do notice that Eclipse starts to get slower and slower the more I switch tasks (DDMS / Java / Debug) perspectives throughout the day. I don’t know, hopefully Google will save me when I have the time to investigate.
I purchased these three e-books online. I came across them while asking questions on the Android beginners Google group. Their author, Mark Murphy is very active on this group answering newb’s questions on a regular basis with detailed and helpful answers. You can even get a full chapter sample to check it out and see whether the writing style jives with your style of learning.
I do recommend a book of some sort for starting out with Android. Without a book you’re sort of left to your own devices. You have to sniff around the Internet at every stage: “How do I use the Android database classes?”, “How do layouts work?”, you can spend a lot of time googling and following time wasting paths through pages that don’t give the answers you’re looking for. I was doing a lot of this and these books have cut down on that time drastically.
The Android project is coming along well. I’m spending a lot of time just thinking about how to best solve problems the Android way, a lesson I learned on the iPhone, to make sure I don’t back myself into bad corners that are hard to get out of.
Well vacation’s over, and while I was away my last client has decided to go ahead with porting Prescriber’s Letter to the Android. So I’ve got a lot of work to do on that in the coming months. Should be interesting, and hopefully I’ll have some good stuff to post here in regards to the challenges you can run into porting iPhone apps to the Android.
The weather in Mexico wasn’t always as good as this picture, but here’s what the beach was like where I was staying:
I’ve spent the last week adding changes to the Prescriber’s Letter app. One of the changes was to add support for browsing all the content in landscape mode. Supporting landscape and portrait orientations quickly exposes any shortcuts you’ve taken in the design and implementation of your views. Not to say that I took lots of shortcuts, actually most of my stuff just worked, but there were a few points where I could have saved myself sometime if I’d planned for landscape support from the beginning. One of those was how I initially chose to do the login screen. I knew when I was doing it that I should create the login screen as its own view controller and then present it modally. It was more efficient at the time though to just add the login screen as another view to the root view controller and slide it in and out myself (since the whole screen is generated by code). Once it came to adding landscape support we didn’t want to have the login screen rotate to landscape. Now I was in trouble. There’s no way to “force” a UIViewController to rotate to one direction or another. You can screw around with writing your own code to perform matrix transformations on your view, but in my opinion that’s just a hack waiting to bite you in the ass. Really you need to redesign your system so that the view is reloaded, and currently in the latest SDK reloading (or loading) the view guarantees that the return value of shouldAutorotateToInterfaceOrientation: is respected. So I converted everything for the login screen over to its own view controller that returns NO to any orientation but portrait, and then present it modally. No matter what orientation the root view controller is in this brings up the login screen in portrait mode.
I’m off to Mexico now for a well deserved vacation with my wife (who deserves it more than me), away until February 26th! Lucky me.

