For a long time Android has had the reputation of being ugly. Since Android 4.0 Ice Cream Sandwich, that's changing.
I just happened to take a look at the android docs (looking at Data Backup) and noticed they've revamped the whole developer documentation site. It now more-or-less matches their Android Design guidelines page, which accompanied Ice Cream Sandwich.
This is pretty important for Google if they want to compete with Microsoft's Metro UI. Although Microsoft has plenty of their own humps that they have to overcome, including some unsurprising Windows 8 bashing from various authors, consensus is that Metro is visually pleasing, arguably even more so than both ICS and Apple's iOS.
The recent announcement of Microsoft's Surface Tablet also spells some trouble for Google. The tablet-plus-full-keyboard device is intended to fill the niche that Windows 8 will be creating with its new gesture-and-keyboard hybrid UI.
No wonder, then, that on the new Android developer site, Design is first and Develop second. Sure, it only makes sense since the tabs are, in order: Design, Develop, Distribute, which matches the typical way of making an app. But the fact that they now, unlike before, lay that out so explicitly, ushering newcomers to look at the entire Design section first, is quite telling of Google's current position in the mobile ecosystem and mindshare.
It's definitely a larger trend in tech these days, where Design and Simplicity are king, and as for actual features, less is often more. It's clear that the big players, beginning with Apple five years ago and now Google and Microsoft, are really drinking the Kool-Aid. And so are thousands of developers who keep up with the latest trends. This is a great thing; I'd love to see every app I use be eye candy. I'd love to design some beautiful and functional apps. Just interesting how everyone seems to be "getting it" at the same time.
Thursday, June 21, 2012
Saturday, November 5, 2011
Why I'm not using Android Market in-app billing
From a developer's standpoint, Android Market's in-app billing service is not that fun to use. It really doesn't give me any feeling of a well-designed API, like I've gotten from Twilio, and Stripe more recently. The whole in-app billing implementation pushes a lot more responsibility onto the app developer for what appears to be little gain.
The one benefit that I can see is that people will get to use Google Checkout without the extra login step. Android Market managed purchases are essentially useless in their current form, since the app developer has to store redundant info anyway in the case of doing content distribution.
Here are the reasons why it does make sense to have the app developer implement most of the in-app billing:
Things that would make the Android Market in-app billing API nicer:
The one benefit that I can see is that people will get to use Google Checkout without the extra login step. Android Market managed purchases are essentially useless in their current form, since the app developer has to store redundant info anyway in the case of doing content distribution.
Here are the reasons why it does make sense to have the app developer implement most of the in-app billing:
- Security. One recurring theme in the in-app billing documentation is that for security, the developer should do things like implement a remote server, and rewrite the sample code so it's tougher to reverse-engineer.
- Managed purchases. The way Android Market in-app billing works with managed purchases, is that it keeps track of a boolean yes/no whether you've bought a given product. However there is no mechanism to restrict content distribution from a remote server, so in that case it makes sense to have the app developer implement that piece.
- Identifying the user. It's difficult to know anything about the user of an Android device, or any identifying features of the device itself, which is why in-app billing requires a Google account, via Android Market. If you want to do anything more sophisticated than just finding out if the user has paid, such as anything surrounding content distribution, then it's up to you as the app developer to come up with some identity management scheme. I.e., have a separate login, since Android Market isn't about to tell you the user's email.
Things that would make the Android Market in-app billing API nicer:
- A service to deliver content. (Maybe they don't have the infrastructure or business strategy for this service right now, in the context of Android Market at least.)
- An online (non-cached) mode, letting the app developer require Internet connectivity to use a feature.
- A way to create and distribute encryption keys. I'd love for Android Market to have a way to make callbacks to our web servers and help distribute encryption keys or other sensitive info, without unnaturally routing that info through the client app and then to our remote server.
- Giving us unique identifiers for users. This would save a lot of trouble and help with many apps that wouldn't normally require accounts, but only need some identifier to make sure the user has paid.
- Allowing more flexible payment models, like variable prices (good for donations) and managing numeric quantities of items (with an optional max limit) instead of just a boolean yes/no whether the user has purchased it before.
Saturday, October 15, 2011
First Impressions: Sencha Touch is faster than jQuery Mobile
Sencha Touch I have found to be a pretty sweet cross-browser HTML5 solution for building web apps. I was looking for a good library to go along with PhoneGap.
At first I looked at jQuery Mobile 1.0rc1, but after checking out the examples on my phone, decided it's broken on Android. Specifically I have a Motorola Droid 1 running stock Android 2.2.2, and the examples ran quite choppily, with CSS page transition effects pretty much completely busted--I guess because they are relying on hardware accelerated CSS on newer phone models.
But even navigating the jQuery Mobile documentation site, which is naturally written with jQuery Mobile, showed some bugginess where the loading dialog would show off-center, the back button would flash the wrong page before finalizing the transition (a side effect of the broken CSS transitions, I guess), and just overall slowness. They even made some basic performance mistakes like binding to the "click" event instead of the "touchstart" event, adding some slowness--see this informative post from March 2011.
The Sencha Touch demos proved to be quite a lot snappier and look quite pretty. The button clicks are very responsive. I was impressed with the speed of the drag and drop, although there was a tiny bit of bugginess where the color might change differently depending if I drag quickly or slowly. In any case I'm pretty convinced that Sencha Touch meets my needs for many use cases for current generation mobile devices. jQuery Mobile might serve me better in the future, when they speed up the library's performance or if I ever decide to cater to a small set of fast devices.
For some more opinions, check out this stackoverflow page: http://stackoverflow.com/questions/4066167/sencha-touch-or-jquery-mobile.
At first I looked at jQuery Mobile 1.0rc1, but after checking out the examples on my phone, decided it's broken on Android. Specifically I have a Motorola Droid 1 running stock Android 2.2.2, and the examples ran quite choppily, with CSS page transition effects pretty much completely busted--I guess because they are relying on hardware accelerated CSS on newer phone models.
But even navigating the jQuery Mobile documentation site, which is naturally written with jQuery Mobile, showed some bugginess where the loading dialog would show off-center, the back button would flash the wrong page before finalizing the transition (a side effect of the broken CSS transitions, I guess), and just overall slowness. They even made some basic performance mistakes like binding to the "click" event instead of the "touchstart" event, adding some slowness--see this informative post from March 2011.
The Sencha Touch demos proved to be quite a lot snappier and look quite pretty. The button clicks are very responsive. I was impressed with the speed of the drag and drop, although there was a tiny bit of bugginess where the color might change differently depending if I drag quickly or slowly. In any case I'm pretty convinced that Sencha Touch meets my needs for many use cases for current generation mobile devices. jQuery Mobile might serve me better in the future, when they speed up the library's performance or if I ever decide to cater to a small set of fast devices.
For some more opinions, check out this stackoverflow page: http://stackoverflow.com/questions/4066167/sencha-touch-or-jquery-mobile.
Labels:
android,
comparison,
jquery mobile,
phonegap,
sencha touch
Sunday, October 9, 2011
Android Market: Application Licensing vs In-app Billing
Licensing is the new way of doing Android Market copy protection. It requires the device to have the Android Market app, and the app must be associated to a Google account. The app that is licensed must be a paid app; free applications are considered licensed to all users. A down side is that many devices that are not licensed to use the official Google android apps won't be compatible with the licensing code. http://developer.android.com/guide/publishing/licensing.html
In-app purchases are also tied to Android Market. Here you are still locked down to the official Android Market app, but your application does not need to be a paid one, according to http://developer.android.com/guide/market/billing/billing_overview.html#billing-limitations. This is cool in that you can release an application for free, then charge for extra content.
In-app purchases are also tied to Android Market. Here you are still locked down to the official Android Market app, but your application does not need to be a paid one, according to http://developer.android.com/guide/market/billing/billing_overview.html#billing-limitations. This is cool in that you can release an application for free, then charge for extra content.
Tuesday, March 2, 2010
Google giving free phones to devs!
So Google is giving free phones to developers who had at least 3.5 star ratings and 5000 unique downloads as of February 2010. reddit is fun met the conditions and I'll be getting a free Droid or Nexus One (based on "random distribution")!
TechCrunch has a posting about it so I'm pretty sure it's not a scam!
http://techcrunch.com/2010/03/02/google-handing-out-free-nexus-ones-and-droids-to-top-android-devs/
Thank you redditors!!!!! And of course thank you Google!!!!!
TechCrunch has a posting about it so I'm pretty sure it's not a scam!
http://techcrunch.com/2010/03/02/google-handing-out-free-nexus-ones-and-droids-to-top-android-devs/
Thank you redditors!!!!! And of course thank you Google!!!!!
Labels:
developers,
droid,
excitement,
giveaway,
google,
happy,
nexus one,
reddit is fun
Sunday, November 8, 2009
Verizon Droid and bugs
Android has been getting excellent press lately. It's really exciting!
Seems like they're putting a huge marketing push behind the new Verizon Droid phone, which is running the new Android 2.0, comes with the car GPS holder, and looks sexy. Finally a pretty Android phone on par with iPhone's looks!
Yeah so the "reddit is fun" app seems to exhibit weird behavior on Droid. Users have reported some crashes coming back to it from a browser link. Also the default Light theme is apparently broken... I guess Droid or Android 2.0 changed the themes around from the 1.6 built-ins.
Hope I can find some time soon to look at 2.0 SDK, which I haven't even installed yet.
Seems like they're putting a huge marketing push behind the new Verizon Droid phone, which is running the new Android 2.0, comes with the car GPS holder, and looks sexy. Finally a pretty Android phone on par with iPhone's looks!
Yeah so the "reddit is fun" app seems to exhibit weird behavior on Droid. Users have reported some crashes coming back to it from a browser link. Also the default Light theme is apparently broken... I guess Droid or Android 2.0 changed the themes around from the 1.6 built-ins.
Hope I can find some time soon to look at 2.0 SDK, which I haven't even installed yet.
Tuesday, September 15, 2009
Crashes with CyanogenMod and apps2sd
A handful of users have been reporting force closes and bugginess when running reddit is fun and CyanogenMod and apps2sd. Unfortunately I don't use either, so I can't reproduce the bugs.
I wonder if any Android developers who do use these mods would mind helping debug this issue?
(follow the issue at http://github.com/talklittle/reddit-is-fun/issues/#issue/13)
EDIT: Ok, I looked at xda-developers forum and see there's this script, switchrom.sh to make it easier to switch between different ROMs. Well, I guess I'll try it out then.
Used this recovery image by JesusFreke to do Nandroid backup before anything else. Then replaced with Cyanogen's 1.4 after I installed CyanogenMod 4.1.9.2. (probably could have skipped using the first recovery image at all... oh well)
Took a break and donated 5 bucks to Cyanogen's beer fund :)
Then backed up sd card contents, and following directions here to setup partitions for apps2sd (which is automatic in Cyanogen rom after doing partitioning)
EDIT2: Yes, I have now indeed encountered force closes that I didn't encounter with stock rom. They mostly happen when rotating the screen. Happened again when rotating screen with login dialog onscreen. Also I get a weird bug where it doesn't load the threads list correctly the first time, and I have to refresh to get anything to show up.
EDIT3: FIXED!!! I had a bunch of errors caused by things like weird Android behavior, trying to run onPrepareDialog for every possible Dialog whenever you rotate the screen or return from another Activity, leading to NullPointerExceptions. Some other things too, like having to setup the DefaultHttpClient to be multithreaded (found examples on apache.org HttpClient 4.0 samples). So grab version 0.7.11, and CyanogenMod too :)
I wonder if any Android developers who do use these mods would mind helping debug this issue?
(follow the issue at http://github.com/talklittle/reddit-is-fun/issues/#issue/13)
EDIT: Ok, I looked at xda-developers forum and see there's this script, switchrom.sh to make it easier to switch between different ROMs. Well, I guess I'll try it out then.
Used this recovery image by JesusFreke to do Nandroid backup before anything else. Then replaced with Cyanogen's 1.4 after I installed CyanogenMod 4.1.9.2. (probably could have skipped using the first recovery image at all... oh well)
Took a break and donated 5 bucks to Cyanogen's beer fund :)
Then backed up sd card contents, and following directions here to setup partitions for apps2sd (which is automatic in Cyanogen rom after doing partitioning)
EDIT2: Yes, I have now indeed encountered force closes that I didn't encounter with stock rom. They mostly happen when rotating the screen. Happened again when rotating screen with login dialog onscreen. Also I get a weird bug where it doesn't load the threads list correctly the first time, and I have to refresh to get anything to show up.
EDIT3: FIXED!!! I had a bunch of errors caused by things like weird Android behavior, trying to run onPrepareDialog for every possible Dialog whenever you rotate the screen or return from another Activity, leading to NullPointerExceptions. Some other things too, like having to setup the DefaultHttpClient to be multithreaded (found examples on apache.org HttpClient 4.0 samples). So grab version 0.7.11, and CyanogenMod too :)
Labels:
android,
apps2sd,
bug,
cyanogen,
cyanogenmod,
reddit is fun
Saturday, September 5, 2009
Released reddit is fun under GPLv3
I just open sourced my first Android app, reddit is fun. I did it because I won't have time to maintain it anymore (or if I do have time, I think I'm ready to move onto other projects). Hopefully people will find it useful, or even better, contribute to it. Contributions could be in the form of better themes, improved layouts, and added features (like offline caching).
I chose GPL over the Apache license because I think GPL makes more sense here. I gave it a lot of thought, and I think that if I use GPL (which requires derived works to also release their source under GPL) then it'll be easier for people to contribute to a "community" sort of app. The alternative under Apache would be that people could take the code and do whatever they wanted, and then keep the changes to themselves as closed source. Which might be good if people want to make a really high quality reddit app and keep the source to themselves. But really, I can't see additions to the current code being so drastic that people would want to hide their changes.
Git repository: http://github.com/talklittle/reddit-is-fun/tree
I chose GPL over the Apache license because I think GPL makes more sense here. I gave it a lot of thought, and I think that if I use GPL (which requires derived works to also release their source under GPL) then it'll be easier for people to contribute to a "community" sort of app. The alternative under Apache would be that people could take the code and do whatever they wanted, and then keep the changes to themselves as closed source. Which might be good if people want to make a really high quality reddit app and keep the source to themselves. But really, I can't see additions to the current code being so drastic that people would want to hide their changes.
Git repository: http://github.com/talklittle/reddit-is-fun/tree
Monday, August 31, 2009
reddit is fun v0.7.0 - My last major release for awhile
reddit is fun v0.7.0!
New features:
This'll be my last major release for awhile since I'm going back to start my Masters program. I'll work on new features when I have time though. Thanks for everyone's support!
EDIT: Oops, I forgot to implement "load more comments". I'll do that soon.
EDIT: 0.7.1 fixes some bad formatting of titles and comment bodies. Thanks to Todd for bringing this to my attention.
EDIT: 0.7.2 fixes couple minor bugs. thanks to jk3us again for pointing out force close when replying to thread while not logged in.
EDIT: 0.7.3 fixes a force close when selecting "pick subreddit" without internet connection
EDIT: 0.7.4 finally implements "load more comments". not inline, unfortunately (how would I handle all the indentation?). also adds "go to parent" context menu option for more convenient navigation.
Also if you'd like to donate, please use the "reddit is fun donation" app in the Market. I also have a paypal account (talklittle, gmail). Thanks very much! :)
New features:
- check your reddit mail. change the mail notification style, or disable, in Menu->Settings.
- automatic background mail notification service, off by default. (Menu->Settings)
- change sort order of threads and comments. new, hot, top, etc.
- pick from your personalized subreddit list
- let you change default starting reddit (Menu->Settings)
This'll be my last major release for awhile since I'm going back to start my Masters program. I'll work on new features when I have time though. Thanks for everyone's support!
EDIT: Oops, I forgot to implement "load more comments". I'll do that soon.
EDIT: 0.7.1 fixes some bad formatting of titles and comment bodies. Thanks to Todd for bringing this to my attention.
EDIT: 0.7.2 fixes couple minor bugs. thanks to jk3us again for pointing out force close when replying to thread while not logged in.
EDIT: 0.7.3 fixes a force close when selecting "pick subreddit" without internet connection
EDIT: 0.7.4 finally implements "load more comments". not inline, unfortunately (how would I handle all the indentation?). also adds "go to parent" context menu option for more convenient navigation.
Also if you'd like to donate, please use the "reddit is fun donation" app in the Market. I also have a paypal account (talklittle, gmail). Thanks very much! :)
Friday, August 28, 2009
1000 downloads!
I just hit the 1000 download mark on Android Market for reddit is fun! Thanks, reddit.com!
Wednesday, August 26, 2009
Intent filter for "Share link"
I just released reddit is fun v0.6.4.
The main feature was a suggestion by jk3us which was to add the app to the list of destinations for sharing, for instance when you click "Share page" from the Browser menu.
To do it, I had to add an intent filter. It looks like this:
I also fixed a long-standing possible force close due to a race condition around dismissing the login dialog and reading from the dialog's members. I never experienced the force close until today, but I have a feeling some other phone models experience it more often than the G1. I was moving some stuff around in the code, which caused the force close to happen very, very frequently. Which makes me think that other phone models could easily have had a higher frequency of this happening, if it was really due to a race condition. Oh well, it should be gone now.
The main feature was a suggestion by jk3us which was to add the app to the list of destinations for sharing, for instance when you click "Share page" from the Browser menu.
To do it, I had to add an intent filter. It looks like this:
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
I also fixed a long-standing possible force close due to a race condition around dismissing the login dialog and reading from the dialog's members. I never experienced the force close until today, but I have a feeling some other phone models experience it more often than the G1. I was moving some stuff around in the code, which caused the force close to happen very, very frequently. Which makes me think that other phone models could easily have had a higher frequency of this happening, if it was really due to a race condition. Oh well, it should be gone now.
Labels:
android,
intent filter,
race condition,
reddit,
reddit is fun,
share page
Saturday, August 22, 2009
reddit is fun v0.6.0 - You can submit links
I just released reddit is fun 0.6.0 and it feels awesome. (the act of releasing a new version, that is.)
The big feature of 0.6.0 is posting new threads (links or self posts). Yessss.
Sssssssss.
Anyway, there's still a long way to go before my app reaches "pro" status. First up are things like the orange-red envelope, expanding and collapsing comment trees, and viewing user posting histories.
I also have a long list of big and small changes I'd still like to make. So there's plenty left to do. Too bad when school starts I'll have a lot less time to work on this.
Reddit post:
http://www.reddit.com/r/Android/comments/9d6dg/reddit_is_fun_060_is_out/
EDIT: 0.6.1 lets you follow links embedded in comments. It was annoying not to be able to get to those. I copied the behavior of the Android Messaging app.
EDIT: 0.6.2 lets you hide comments by long-pressing and using the context menu. I figure the context menu can be used for less frequently used (for me at least) actions, while regular clicks will show the frequently used actions -- voting, reply, and visiting links embedded in the comment.
Edit: 0.6.3 lets you go to the next/previous pages in threads list. hooray! It was weird implementing this because the reddit API requires you to provide the correct "count" value in the URL, or else it doesn't tell you how to get back to the previous page. Whatever. Details...
Also fixes the bug with rotating the screen putting you back at the reddit frontpage instead of whatever subreddit you were in.
The big feature of 0.6.0 is posting new threads (links or self posts). Yessss.
Sssssssss.
Anyway, there's still a long way to go before my app reaches "pro" status. First up are things like the orange-red envelope, expanding and collapsing comment trees, and viewing user posting histories.
I also have a long list of big and small changes I'd still like to make. So there's plenty left to do. Too bad when school starts I'll have a lot less time to work on this.
Reddit post:
http://www.reddit.com/r/Android/comments/9d6dg/reddit_is_fun_060_is_out/
EDIT: 0.6.1 lets you follow links embedded in comments. It was annoying not to be able to get to those. I copied the behavior of the Android Messaging app.
EDIT: 0.6.2 lets you hide comments by long-pressing and using the context menu. I figure the context menu can be used for less frequently used (for me at least) actions, while regular clicks will show the frequently used actions -- voting, reply, and visiting links embedded in the comment.
Edit: 0.6.3 lets you go to the next/previous pages in threads list. hooray! It was weird implementing this because the reddit API requires you to provide the correct "count" value in the URL, or else it doesn't tell you how to get back to the previous page. Whatever. Details...
Also fixes the bug with rotating the screen putting you back at the reddit frontpage instead of whatever subreddit you were in.
Tuesday, August 18, 2009
reddit is fun v0.5.3
I just released 0.5.3 of reddit is fun!
So, thanks to helpful feedback from people, I fixed quite a few stability issues. It sucks to admit it, but the first release had lots of synchronous tasks that should have been asynchronous. I hadn't realized that was really necessary until people told me about their crashes. So I went back to eclipse and pounded away at the app for hours, refactoring until I turned all the synchronous crap into AsyncTasks, which are EXTREMELY useful on Android. (Before I knew about AsyncTask, I was trying to use Threads and Handlers and callbacks, and keeping track of the state of the Activities. AsyncTask takes care of the nitty gritty stuff and makes it much easier and more robust.)
Anyway I'm also getting good suggestions for UI improvements. Awesome. I really like my pace on this project because it feels like I can just get into it and keep going full speed. Maybe it's the fact that it's all Java and that Eclipse fills in a lot of the uninteresting stuff for you so you can worry about the program instead of the code. There were a couple debug sessions that dragged on, though. But it's always nice to take a step back and think of a possible cause and solution for a bug, and even nicer when it works. It kicks butt. No, it kicks two butts. Make that three.
So, thanks to helpful feedback from people, I fixed quite a few stability issues. It sucks to admit it, but the first release had lots of synchronous tasks that should have been asynchronous. I hadn't realized that was really necessary until people told me about their crashes. So I went back to eclipse and pounded away at the app for hours, refactoring until I turned all the synchronous crap into AsyncTasks, which are EXTREMELY useful on Android. (Before I knew about AsyncTask, I was trying to use Threads and Handlers and callbacks, and keeping track of the state of the Activities. AsyncTask takes care of the nitty gritty stuff and makes it much easier and more robust.)
Anyway I'm also getting good suggestions for UI improvements. Awesome. I really like my pace on this project because it feels like I can just get into it and keep going full speed. Maybe it's the fact that it's all Java and that Eclipse fills in a lot of the uninteresting stuff for you so you can worry about the program instead of the code. There were a couple debug sessions that dragged on, though. But it's always nice to take a step back and think of a possible cause and solution for a bug, and even nicer when it works. It kicks butt. No, it kicks two butts. Make that three.
Sunday, August 16, 2009
reddit is fun - first release, version 0.5.0
reddit is fun
My first app is now on the Android marketplace! "reddit is fun" is an app for browsing reddit.com with IMO a less annoying interface than dealing with the Android browser.
For this version, 0.5.0, you can look at the hot stories on different subreddits, login and vote, and leave comment replies.
In future versions I still have a lot of things to add:
- Posting new threads
- Better UI (some dialogs are wonky)
- Looking at user info
- The "red envelope" for replies
- Sorting the subreddit and comments by things other than "hot"
- "load more comments"
- View more pages within a subreddit
- Handling embedded links in comments
- A few other features that might go into a paid version :)
Labels:
android,
market,
marketplace,
reddit,
reddit is fun
Tuesday, June 16, 2009
StateListDrawable and TransitionDrawable
StateListDrawable and TransitionDrawable are useful classes when it comes to making custom buttons and controls.
Making a custom button is simple. First of all you need to create some graphics for the different states of your button (see the Android dev guide on basic 2d Graphics).
I created a couple NinePatchDrawable image files using GIMP and the draw9patch.bat tool included in the Android SDK under <sdk-dir>/tools/. Here they are:
bluebutton.9.png
redbutton.9.png
Android already has its own default built-in buttons which are pretty similar to these. Of course, in a real app you can give the buttons different shapes and designs. Also, since these are NinePatch images, I could have made them smaller to save space since they'd stretch the same way anyway.
To use these in my project, I created a couple XML files under my project's res/drawable directory, pressbutton.xml and longpressbutton.xml.
res/drawable/pressbutton.xml:
With selectors (StateListDrawables), the object displays the first <item> underneath the <selector> tag whose attributes match the state of the object. Since the last <item> in my example doesn't have any attributes like state_pressed, it acts as a catch-all.
res/drawable/longpressbutton.xml:
The <transition> (TransitionDrawable) is more of an animation definition, so you don't need attributes on the <item>s. It plays through the <item>s sequentially based on the argument you pass into the startTransition(milliseconds) method.
Now, getting TransitionDrawables to work is a bit trickier than using StateListDrawables. Well, at least it took me longer to figure out.
I made a subclass of Button called TransitionButton, like this:
To use the Button and TransitionButton, as usual I put the necessary code into the onCreate(Bundle) method of my Activity. So I have something like this:
Finally, my res/layout/main.xml:
Now, that will hopefully compile and run (with minor changes like adding the imports and package statements). If so, then you should see that the Button using a StateListDrawable works fine, while the TransitionButton is buggy. It looks like this at the end of the transition:
No, we don't want it to look like that. What's going on? The answer is that since we're using NinePatch images, the padding area of the images is not changed when we use a TransitionDrawable for the background. We can fix this by either using a regular Drawable (xxx.png instead of xxx.9.png) or by drawing padding lines that extend all the way along the right and bottom edges, making button text ugly unless you manually size the Buttons.
With custom Buttons though, I think most of the time you'd be using static sized images rather than NinePatch images, but that's just my opinion. I was just too lazy this time to make more than two images.
Anyway that's about it for this small tutorial. Hope it makes sense! I wrote it mostly for myself to document this procedure, since it took awhile to figure out the details.
Making a custom button is simple. First of all you need to create some graphics for the different states of your button (see the Android dev guide on basic 2d Graphics).
I created a couple NinePatchDrawable image files using GIMP and the draw9patch.bat tool included in the Android SDK under <sdk-dir>/tools/. Here they are:
bluebutton.9.png
redbutton.9.pngAndroid already has its own default built-in buttons which are pretty similar to these. Of course, in a real app you can give the buttons different shapes and designs. Also, since these are NinePatch images, I could have made them smaller to save space since they'd stretch the same way anyway.
To use these in my project, I created a couple XML files under my project's res/drawable directory, pressbutton.xml and longpressbutton.xml.
res/drawable/pressbutton.xml:
<selector android="http://schemas.android.com/apk/res/android">
<item state_pressed="true" drawable="@drawable/redbutton">
<item drawable="@drawable/bluebutton">
</selector>
With selectors (StateListDrawables), the object displays the first <item> underneath the <selector> tag whose attributes match the state of the object. Since the last <item> in my example doesn't have any attributes like state_pressed, it acts as a catch-all.
res/drawable/longpressbutton.xml:
<transition android="http://schemas.android.com/apk/res/android">
<item drawable="@drawable/redbutton">
<item drawable="@drawable/bluebutton">
</transition>
The <transition> (TransitionDrawable) is more of an animation definition, so you don't need attributes on the <item>s. It plays through the <item>s sequentially based on the argument you pass into the startTransition(milliseconds) method.
Now, getting TransitionDrawables to work is a bit trickier than using StateListDrawables. Well, at least it took me longer to figure out.
I made a subclass of Button called TransitionButton, like this:
public class TransitionButton extends Button {
private TransitionDrawable mTransition = null;
private Context mContext;
public TransitionButton(Context context) {
super(context);
mContext = context;
}
public TransitionButton(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
}
public TransitionButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mContext = context;
}
public void setTransition(TransitionDrawable transition) {
mTransition = transition;
setBackgroundDrawable(transition);
}
public void setPressed(boolean pressed) {
super.setPressed(pressed);
if (pressed && mTransition != null) {
mTransition.startTransition(1000);
} else if (!pressed && mTransition != null) {
mTransition.resetTransition();
}
}
}
To use the Button and TransitionButton, as usual I put the necessary code into the onCreate(Bundle) method of my Activity. So I have something like this:
public class StateAndTransition extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final Context mContext = getApplicationContext();
Resources res = mContext.getResources();
TransitionDrawable transition = (TransitionDrawable) res.getDrawable(R.drawable.longpressbutton);
final Button stateButton = (Button) findViewById(R.id.statebutton);
stateButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
stateButton.setTextSize(10 + stateButton.getTextSize());
}
});
final TransitionButton longpressButton = (TransitionButton) findViewById(R.id.longpress);
longpressButton.setTransition(transition);
longpressButton.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent m) {
if (m.getAction() == MotionEvent.ACTION_DOWN) {
longpressButton.setPressed(true);
} else {
longpressButton.setPressed(false);
}
return true; // The Listener consumes the Touch action
}
});
}
}
Finally, my res/layout/main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res/talklittle.android.examples.stateandtransition"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<Button android:id="@+id/statebutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerInParent="true"
android:text="Touch me"
android:textSize="8sp"
android:background="@drawable/pressbutton"/>
<talklittle.android.examples.stateandtransition.TransitionButton
android:id="@+id/longpress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerInParent="true"
android:text="Hold me"
android:textSize="30sp"
android:background="@drawable/redbutton"/>
</LinearLayout>
Now, that will hopefully compile and run (with minor changes like adding the imports and package statements). If so, then you should see that the Button using a StateListDrawable works fine, while the TransitionButton is buggy. It looks like this at the end of the transition:
No, we don't want it to look like that. What's going on? The answer is that since we're using NinePatch images, the padding area of the images is not changed when we use a TransitionDrawable for the background. We can fix this by either using a regular Drawable (xxx.png instead of xxx.9.png) or by drawing padding lines that extend all the way along the right and bottom edges, making button text ugly unless you manually size the Buttons.With custom Buttons though, I think most of the time you'd be using static sized images rather than NinePatch images, but that's just my opinion. I was just too lazy this time to make more than two images.
Anyway that's about it for this small tutorial. Hope it makes sense! I wrote it mostly for myself to document this procedure, since it took awhile to figure out the details.
Labels:
android,
button,
graphics,
statelistdrawable,
transition,
transitiondrawable
Sunday, June 14, 2009
Wish my wireless router was better
I was able to get my Android Dev phone set up very easily without a data plan, just using a wireless connection and Linux, by following the directions on this very useful post from technomancy.org. Luckily I had an Ubuntu VM ready to go, so the entire setup process took no more than ten minutes.
Unfortunately, though, my wireless router is a bit old and sucky, and the wireless craps out from time to time. On top of that, the phone won't keep retrying the connection; I believe it tries to reconnect to your remembered wifi access points once each, then after that you have to manually go back and press the button to reconnect. (I'm running Android software 1.1. I don't think it's fixed yet in cupcake 1.5.) It's quite annoying. Maybe I'll have to put down the money for a data plan....
I think the folks in the issue tracker for #2718 are having the same issue on Cupcake though. Oh well, at least I'm not addicted to using the web from my phone yet. Mostly because "Crackdroid" sounds stupid.
On an unrelated note, I wonder how many android blogs on Blogger use this "Son of Moto" template? sigh... I'll try to come up with something better.
Unfortunately, though, my wireless router is a bit old and sucky, and the wireless craps out from time to time. On top of that, the phone won't keep retrying the connection; I believe it tries to reconnect to your remembered wifi access points once each, then after that you have to manually go back and press the button to reconnect. (I'm running Android software 1.1. I don't think it's fixed yet in cupcake 1.5.) It's quite annoying. Maybe I'll have to put down the money for a data plan....
I think the folks in the issue tracker for #2718 are having the same issue on Cupcake though. Oh well, at least I'm not addicted to using the web from my phone yet. Mostly because "Crackdroid" sounds stupid.
On an unrelated note, I wonder how many android blogs on Blogger use this "Son of Moto" template? sigh... I'll try to come up with something better.
Subscribe to:
Posts (Atom)
