<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:blogger="http://schemas.google.com/blogger/2008" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;DEECQ3g4eip7ImA9WhBVFEo.&quot;"><id>tag:blogger.com,1999:blog-1531829516427013333</id><updated>2013-04-20T18:51:02.632+02:00</updated><category term="Minimal marketable app" /><category term="support library" /><category term="Intent" /><category term="Fragment" /><category term="FragmentStatePagerAdapter" /><category term="PagerAdapter" /><category term="Integer" /><category term="camera" /><category term="External storage" /><category term="BlinkLayout" /><category term="SeekBar" /><category term="OnPageChangeListener" /><category term="mockup" /><category term="String" /><category term="sketch" /><category term="UI" /><category term="bezel swipe" /><category term="CameraFragment" /><category term="scrolling" /><category term="margin" /><category term="Boolean" /><category term="API" /><category term="ViewGroup" /><category term="fake dragging" /><category term="roadmap" /><category term="Uri" /><category term="rotation" /><category term="picture" /><category term="Layout" /><category term="Resources" /><category term="ViewPager" /><category term="orientation" /><category term="OrientationEventListener" /><category term="Instant Mustache" /><category term="FragmentPagerAdapter" /><category term="Offscreen pages" /><category term="Clean Code" /><category term="MediaScanner" /><category term="OnClickListener" /><category term="TextUtils" /><category term="SurfaceView" /><category term="Animation" /><title>Android Zeitgeist</title><subtitle type="html" /><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://www.androidzeitgeist.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://www.androidzeitgeist.com/" /><author><name>Sebastian Kaspari</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-20YfT7gfh08/AAAAAAAAAAI/AAAAAAAALWI/LZ-ps7enWlI/s512-c/photo.jpg" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>16</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/AndroidZeitgeist" /><feedburner:info uri="androidzeitgeist" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;CE8GRXk7eCp7ImA9WhNbEUQ.&quot;"><id>tag:blogger.com,1999:blog-1531829516427013333.post-8353658165969956441</id><published>2013-01-14T20:47:00.000+01:00</published><updated>2013-01-14T20:47:04.700+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-01-14T20:47:04.700+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="orientation" /><category scheme="http://www.blogger.com/atom/ns#" term="rotation" /><category scheme="http://www.blogger.com/atom/ns#" term="camera" /><category scheme="http://www.blogger.com/atom/ns#" term="Instant Mustache" /><category scheme="http://www.blogger.com/atom/ns#" term="OrientationEventListener" /><title>Fixing the rotation - Instant Mustache #8</title><content type="html">&lt;div&gt;
&lt;span style="font-size: x-small;"&gt;This article is part of a series of articles about the development process of Instant Mustache, a fun camera app that adds mustaches to all faces using face detection.&amp;nbsp;&lt;a href="http://www.androidzeitgeist.com/p/instant-mustache.html"&gt;Click here&lt;/a&gt;&amp;nbsp;to get a chronological list of all published&amp;nbsp;&lt;a href="http://www.androidzeitgeist.com/p/instant-mustache.html"&gt;articles about Instant Mustache&lt;/a&gt;.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style="font-size: large;"&gt;Wrong orientation&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
If you run the current version of Instant Mustache and take some pictures you'll notice something odd: The orientation of the taken pictures is sometimes wrong. This may depend on the device you are using. When using a Galaxy Nexus the picture will be rotated 90° to the left when taking a picture in portrait mode but will be rotated correctly when taking a picture in landscape mode.&lt;br /&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-RDkIH8Iw8VY/UPRZTnyZA2I/AAAAAAAAH0Q/BU7sRAlQQOw/s1600/rotation_error.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="239" src="http://1.bp.blogspot.com/-RDkIH8Iw8VY/UPRZTnyZA2I/AAAAAAAAH0Q/BU7sRAlQQOw/s320/rotation_error.png" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Wrong orientation of photo that has been taken in portrait mode&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
How does this happen? You may remember that we've used &lt;a href="https://developer.android.com/reference/android/hardware/Camera.html#setDisplayOrientation(int)"&gt;Camera.setDisplayOrientation()&lt;/a&gt; in one of the &lt;a href="http://www.androidzeitgeist.com/2012/10/displaying-camera-preview-instant.html"&gt;previous articles&lt;/a&gt; to explicitly set the display rotation. First, this setting only affects the preview picture. The picture passed to the &lt;a href="https://developer.android.com/reference/android/hardware/Camera.ShutterCallback.html"&gt;Camera.ShutterCallback&lt;/a&gt; isn't affected by this setting. And second, we still have to account into how the device is rotated in the moment of taking the picture.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style="font-size: large;"&gt;Detecting and remembering the orientation&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
What we need to do in our code is to register an &lt;a href="https://developer.android.com/reference/android/view/OrientationEventListener.html"&gt;OrientationEventListener&lt;/a&gt; to get notified whenever the orientation changes. We'll remember this orientation and use this to rotate the taken image once the callback returns.&lt;br /&gt;
&lt;br /&gt;
Whenever the orientation changes &lt;a href="https://developer.android.com/reference/android/view/OrientationEventListener.html#onOrientationChanged(int)"&gt;onOrientationChanged(int)&lt;/a&gt; of the listener will be called. The orientation will be passed to the method in degrees, ranging from 0 to 359. We need to normalize this value as we are only interested in 90° steps for rotating the picture.&lt;br /&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-JQ2Rm-uZ0gQ/UPRahx8kf2I/AAAAAAAAH0c/v7NIwzqReBM/s1600/cameraorientationlistener_normalize.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-JQ2Rm-uZ0gQ/UPRahx8kf2I/AAAAAAAAH0c/v7NIwzqReBM/s1600/cameraorientationlistener_normalize.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;a href="https://github.com/pocmo/Instant-Mustache/blob/article-08/src/com/androidzeitgeist/mustache/listener/CameraOrientationListener.java#L31"&gt;CameraOrientationListener.normalize()&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
Another method called &lt;a href="https://github.com/pocmo/Instant-Mustache/blob/article-08/src/com/androidzeitgeist/mustache/listener/CameraOrientationListener.java#L51"&gt;rememberOrientation()&lt;/a&gt; will be used to save the orientation of the device in the moment of the user pressing the shutter button.&lt;br /&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-rqdv0tzl52Y/UPRbbrb1vBI/AAAAAAAAH00/2Ldj2OrPXBM/s1600/camerafragment_takepicture.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-rqdv0tzl52Y/UPRbbrb1vBI/AAAAAAAAH00/2Ldj2OrPXBM/s1600/camerafragment_takepicture.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;a href="https://github.com/pocmo/Instant-Mustache/blob/article-08/src/com/androidzeitgeist/mustache/fragment/CameraFragment.java#L231"&gt;CameraFragment.takePicture()&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;Rotating the picture&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Now we just need to rotate the Bitmap. We do this by creating a new Bitmap object and applying a rotated &lt;a href="http://developer.android.com/reference/android/graphics/Matrix.html"&gt;Matrix&lt;/a&gt; to the pixels. The rotation angle is calculated by summing the remembered orientation, the display orientation and the natural rotation of the device.&lt;br /&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-Kp9GQ7CSHik/UPRcKSjRiBI/AAAAAAAAH1I/cTRdA_NYgjI/s1600/camerafragment_onpicturetaken.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-Kp9GQ7CSHik/UPRcKSjRiBI/AAAAAAAAH1I/cTRdA_NYgjI/s1600/camerafragment_onpicturetaken.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;a href="https://github.com/pocmo/Instant-Mustache/blob/article-08/src/com/androidzeitgeist/mustache/fragment/CameraFragment.java#L241"&gt;CameraFragment.onPictureTaken()&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;Result&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-3lBP-pDo5cQ/UPRd8jZp-LI/AAAAAAAAH14/kJaLh3-Mdak/s1600/result_rotation.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="242" src="http://3.bp.blogspot.com/-3lBP-pDo5cQ/UPRd8jZp-LI/AAAAAAAAH14/kJaLh3-Mdak/s320/result_rotation.png" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Photos rotated correctly in portrait and landscape mode&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;img src="http://feeds.feedburner.com/~r/AndroidZeitgeist/~4/17oriJk6I8w" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.androidzeitgeist.com/feeds/8353658165969956441/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.androidzeitgeist.com/2013/01/fixing-rotation-camera-picture.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1531829516427013333/posts/default/8353658165969956441?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1531829516427013333/posts/default/8353658165969956441?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/AndroidZeitgeist/~3/17oriJk6I8w/fixing-rotation-camera-picture.html" title="Fixing the rotation - Instant Mustache #8" /><author><name>Sebastian Kaspari</name><uri>https://plus.google.com/112283223674539938062</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-20YfT7gfh08/AAAAAAAAAAI/AAAAAAAALWI/LZ-ps7enWlI/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-RDkIH8Iw8VY/UPRZTnyZA2I/AAAAAAAAH0Q/BU7sRAlQQOw/s72-c/rotation_error.png" height="72" width="72" /><thr:total>1</thr:total><gd:extendedProperty name="commentSource" value="1" /><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD" /><feedburner:origLink>http://www.androidzeitgeist.com/2013/01/fixing-rotation-camera-picture.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CE8HSHo8fip7ImA9WhNVEUU.&quot;"><id>tag:blogger.com,1999:blog-1531829516427013333.post-1598031232613876637</id><published>2012-12-22T14:21:00.000+01:00</published><updated>2012-12-22T14:27:19.476+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-12-22T14:27:19.476+01:00</app:edited><title>Android 2012</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-dKfHvBySVQk/UNWsnfVSK6I/AAAAAAAAHR8/FYWEUfw0yeU/s1600/android2012.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-dKfHvBySVQk/UNWsnfVSK6I/AAAAAAAAHR8/FYWEUfw0yeU/s1600/android2012.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
After &lt;a href="http://www.youtube.com/watch?v=xY_MUB8adEQ"&gt;Google Zeitgeist&lt;/a&gt; and&amp;nbsp;&lt;a href="http://www.youtube.com/watch?v=iCkYw3cRwLo"&gt;YouTube&lt;/a&gt;&amp;nbsp;looked back on 2012 it’s time to do the same for Android.&lt;span id="goog_2128203782"&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;January&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;a href="http://4.bp.blogspot.com/-4cV7er0VgPI/UNWw0GXYL5I/AAAAAAAAHSQ/nDFaspNqWns/s1600/androiddesign.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="157" src="http://4.bp.blogspot.com/-4cV7er0VgPI/UNWw0GXYL5I/AAAAAAAAHSQ/nDFaspNqWns/s200/androiddesign.png" width="200" /&gt;&lt;/a&gt;The year 2011 has just ended and the &lt;b&gt;Galaxy Nexus&lt;/b&gt; is the current flagship phone. 12 days later on January 12th the &lt;b&gt;&lt;a href="http://developer.android.com/design/index.html"&gt;Android Design&lt;/a&gt;&lt;/b&gt; website launched. Followed by the &lt;b&gt;&lt;a href="https://plus.google.com/u/0/+AndroidDevelopers/posts"&gt;Android developers Google+ page&lt;/a&gt;&lt;/b&gt; on January 30th.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;February&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
The first numbers of the year are published. &lt;b&gt;850,000&lt;/b&gt; Android phones are activated every day. &lt;b&gt;300 million &lt;/b&gt;devices have been activated so far.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;March&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
On March 5th &lt;b&gt;&lt;a href="http://android-developers.blogspot.de/2012/03/android-apps-break-50mb-barrier.html"&gt;expansion files&lt;/a&gt;&lt;/b&gt; are introduced and &lt;b&gt;Android apps break the 50MB barrier&lt;/b&gt; expanding the size limit to &lt;b&gt;4GB&lt;/b&gt;. The Android market retires and is reborn as &lt;b&gt;Google play&lt;/b&gt; on March 6th. The same month on March 21st the &lt;b&gt;SDK tools and ADT revision 17&lt;/b&gt; are released, adding an emulator that supports running x86 system images on Windows and Mac OS X. An update to the Android Developer Console on March 29th allows &lt;b&gt;multiple users&lt;/b&gt; to manage published Android apps.&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-qPqhAtg_PVg/UNWxPkos_2I/AAAAAAAAHSY/ivgQD4D4Nmo/s1600/appclinic.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="150" src="http://1.bp.blogspot.com/-qPqhAtg_PVg/UNWxPkos_2I/AAAAAAAAHSY/ivgQD4D4Nmo/s200/appclinic.jpg" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;April&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
The emulator gets even more faster on April 9th by adding &lt;b&gt;GPU support&lt;/b&gt;. On April 20th the first episode of &lt;b&gt;&lt;a href="http://www.youtube.com/playlist?list=PLB7B9B23D864A55C3"&gt;Friday App Review&lt;/a&gt;&lt;/b&gt; airs and is later called &lt;b&gt;&lt;a href="http://www.youtube.com/playlist?list=PLB7B9B23D864A55C3"&gt;The app clinic&lt;/a&gt;&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style="font-size: large;"&gt;May&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
On May 4th Wolfram Rittmeyer publishes the first posting on his blog &lt;b&gt;&lt;a href="http://www.grokkingandroid.com/"&gt;Grokking Android&lt;/a&gt;&lt;/b&gt;. Followed by the first article published on &lt;a href="http://www.androidzeitgeist.com/"&gt;&lt;b&gt;Android Zeitgeist&lt;/b&gt;&lt;/a&gt; on May 27th. 3 days before on May 24th &lt;b&gt;&lt;a href="http://android-developers.blogspot.de/2012/05/in-app-subscriptions-in-google-play.html"&gt;In-app Subscriptions&lt;/a&gt;&lt;/b&gt; are launched on Google Play.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;June&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;a href="http://1.bp.blogspot.com/-HvAwcdnUaq4/UNWxlZCN7XI/AAAAAAAAHSg/jM3slhIq--k/s1600/google-io-logo.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="40" src="http://1.bp.blogspot.com/-HvAwcdnUaq4/UNWxlZCN7XI/AAAAAAAAHSg/jM3slhIq--k/s200/google-io-logo.png" width="200" /&gt;&lt;/a&gt;&lt;br /&gt;
The &lt;b&gt;&lt;a href="https://developers.google.com/events/io/"&gt;Google I/O&lt;/a&gt;&lt;/b&gt; takes place for three days from June 27th to 29th. There are now &lt;b&gt;900,000&lt;/b&gt; Android devices activated every day and &lt;b&gt;400 million&lt;/b&gt; devices have been activated up to now. &lt;b&gt;Android 4.1 (Jelly Bean)&lt;/b&gt; is publicly shown for the first time on June 27th. The same day the &lt;b&gt;Android 4.1 SDK&lt;/b&gt; is released. In addition to that the first tablet by Google is unveiled: The &lt;b&gt;Nexus 7&lt;/b&gt;. On the second day of the Google I/O the &lt;b&gt;Android SDK tools&lt;/b&gt; are updated to &lt;b&gt;revision 20&lt;/b&gt;. At the end of the Google I/O there have been 3.5 million live streams seen from 170 countries.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;July&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-iu-C9xVT-_U/UNWyPKppPJI/AAAAAAAAHS4/JfRWJvOp7dg/s1600/ouya.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="200" src="http://3.bp.blogspot.com/-iu-C9xVT-_U/UNWyPKppPJI/AAAAAAAAHS4/JfRWJvOp7dg/s200/ouya.png" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;
On July 3rd the &lt;b&gt;&lt;a href="http://www.ouya.tv/"&gt;Ouya&lt;/a&gt;&lt;/b&gt;, an Android based console, is unveiled and a Kickstarter campaign is started on July 10th. On July 9th the &lt;b&gt;Android 4.1 source code&lt;/b&gt; is published as part of the Android Open Source Project (AOSP).&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;August&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
The funding phase for the &lt;b&gt;Ouya&lt;/b&gt; is completed. The campaign collected $8,596,475. That’s 904% more than the initial campaign goal.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;September&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
New numbers are released. There are now &lt;b&gt;1.3 million devices&lt;/b&gt; activated every a day. About &lt;b&gt;70,000&lt;/b&gt; of these devices are tablets. &lt;b&gt;480 million&lt;/b&gt; devices have been activated up to now. On September 9th the first episode of &lt;b&gt;&lt;a href="http://www.youtube.com/playlist?list=PLWz5rJ2EKKc9Wam5jE-9oY8l6RpeAx-XM"&gt;This week in Android development&lt;/a&gt;&lt;/b&gt; airs. A day later the first episode of &lt;b&gt;&lt;a href="http://www.youtube.com/playlist?list=PLWz5rJ2EKKc8j2B95zGMb8muZvrIy-wcF"&gt;Android Design in Action&lt;/a&gt;&lt;/b&gt; is uploaded to YouTube.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;October&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://3.bp.blogspot.com/-iMCBRXK31yE/UNWx_vXgIjI/AAAAAAAAHSw/9PXrh3tQBs4/s1600/nexus4.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="167" src="http://3.bp.blogspot.com/-iMCBRXK31yE/UNWx_vXgIjI/AAAAAAAAHSw/9PXrh3tQBs4/s200/nexus4.png" width="200" /&gt;&lt;/a&gt;Till mid October &lt;b&gt;3 million Nexus 7&lt;/b&gt; units have been sold. Starting from October 15th the &lt;b&gt;new Google Play Developer Console&lt;/b&gt; is available to everyone. Google planned a &lt;b&gt;launch event&lt;/b&gt; on October 29th in New York but it has been cancelled due to Hurricane Sandy. Nevertheless the &lt;b&gt;Nexus 4&lt;/b&gt; and &lt;b&gt;Nexus 10&lt;/b&gt; are introduced online this day. These are the first devices to run &lt;b&gt;Android 4.2&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;November&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
The first episode of &lt;a href="http://www.youtube.com/playlist?list=PLWz5rJ2EKKc9loen4OjS03gdjI0JhF4cW"&gt;(╯°□°）╯︵ ┻━┻&lt;/a&gt; airs on November 8th. On November 13th the &lt;b&gt;Nexus 4&lt;/b&gt; and &lt;b&gt;Nexus 10&lt;/b&gt; went on sale and are sold out in minutes. Later that day the &lt;b&gt;Android 4.2 SDK platform&lt;/b&gt; is released. Another day later the &lt;b&gt;Android SDK tools revision 21&lt;/b&gt; are released.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;December&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Google releases a new &lt;b&gt;&lt;a href="http://android-developers.blogspot.de/2012/12/new-google-maps-android-api-now-part-of.html"&gt;Google Maps API&lt;/a&gt;&lt;/b&gt; for Android on December 3rd. On December 10th a new version of the&lt;b&gt; &lt;a href="http://android-developers.blogspot.de/2012/12/in-app-billing-version-3.html"&gt;In-App billing API&lt;/a&gt;&lt;/b&gt; is released.&lt;br /&gt;
&lt;br /&gt;
The Android team releases their &lt;b&gt;Happy Holidays&lt;/b&gt; video:&lt;br /&gt;
&lt;br /&gt;
&lt;iframe allowfullscreen="allowfullscreen" frameborder="0" height="315" src="http://www.youtube.com/embed/967nio2LF7s" width="560"&gt;&lt;/iframe&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;2013?&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;What has been your Android highlight in 2012 and what are your wishes for 2013?&lt;/b&gt;&lt;img src="http://feeds.feedburner.com/~r/AndroidZeitgeist/~4/6_wXwDjJRdc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.androidzeitgeist.com/feeds/1598031232613876637/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.androidzeitgeist.com/2012/12/android-2012.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1531829516427013333/posts/default/1598031232613876637?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1531829516427013333/posts/default/1598031232613876637?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/AndroidZeitgeist/~3/6_wXwDjJRdc/android-2012.html" title="Android 2012" /><author><name>Sebastian Kaspari</name><uri>https://plus.google.com/112283223674539938062</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-20YfT7gfh08/AAAAAAAAAAI/AAAAAAAALWI/LZ-ps7enWlI/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-dKfHvBySVQk/UNWsnfVSK6I/AAAAAAAAHR8/FYWEUfw0yeU/s72-c/android2012.png" height="72" width="72" /><thr:total>1</thr:total><gd:extendedProperty name="commentSource" value="1" /><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD" /><feedburner:origLink>http://www.androidzeitgeist.com/2012/12/android-2012.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Dk4FQHc9cSp7ImA9WhNWEkg.&quot;"><id>tag:blogger.com,1999:blog-1531829516427013333.post-8734004828090755204</id><published>2012-12-11T20:41:00.000+01:00</published><updated>2012-12-11T20:41:51.969+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-12-11T20:41:51.969+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="TextUtils" /><category scheme="http://www.blogger.com/atom/ns#" term="API" /><category scheme="http://www.blogger.com/atom/ns#" term="Clean Code" /><category scheme="http://www.blogger.com/atom/ns#" term="String" /><title>Mind the gap: String.isEmpty()</title><content type="html">&lt;span style="font-size: x-small;"&gt;Articles labeled "Mind the gap" are short articles mostly about simple problems that arise from using different API levels of Android. They are more short trivia postings than big teachings about Android development.&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
I try to write code as readable as possible. That's the reason why I don't want to compare a String to an other empty String object or check its length when I want to know if a String is empty.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-FWLirpvHLAM/UMbfKHp3tUI/AAAAAAAAHCI/NPnjM4Qx5Pk/s1600/isemptyvariants.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-FWLirpvHLAM/UMbfKHp3tUI/AAAAAAAAHCI/NPnjM4Qx5Pk/s1600/isemptyvariants.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;/div&gt;
In the book "&lt;a href="http://books.google.de/books?id=dwSfGQAACAAJ&amp;amp;dq=isbn:0132350882y"&gt;Clean code&lt;/a&gt;" by &lt;a href="http://en.wikipedia.org/wiki/Robert_Cecil_Martin"&gt;Robert C. Martin&lt;/a&gt; you can read&amp;nbsp;&lt;a href="http://en.wikipedia.org/wiki/Grady_Booch"&gt;Grady Booch&lt;/a&gt; saying: "Clean code reads like well-written prose". So I try to use &lt;a href="http://developer.android.com/reference/java/lang/String.html#isEmpty()"&gt;String.isEmpty()&lt;/a&gt; for that reason. Internally it may do a length check as well (I stopped my investigation at the &lt;i&gt;native&lt;/i&gt; keyword)&amp;nbsp;but when reading the following snippet it is absolutely obvious what I intend to do.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-fPosAzNzRYc/UMbecA_7d3I/AAAAAAAAHB4/K6lPAMAkrIs/s1600/isEmptyMethod.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-fPosAzNzRYc/UMbecA_7d3I/AAAAAAAAHB4/K6lPAMAkrIs/s1600/isEmptyMethod.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Even though &lt;a href="http://developer.android.com/reference/java/lang/String.html#isEmpty()"&gt;isEmpty()&lt;/a&gt; has been introduced in Java 1.6 it hasn't been available in Android until API level 9 (Android 2.3) so I accidentally caused some crashes on earlier versions of Android. Nowadays &lt;a href="http://tools.android.com/tips/lint"&gt;lint&lt;/a&gt;&amp;nbsp;thankfully&amp;nbsp;saves me from doing this error.&lt;br /&gt;
&lt;br /&gt;
So what to do now? I don't know if someone at Google felt the same but there is a class in the Android framework that solves that problem: &lt;a href="http://developer.android.com/reference/android/text/TextUtils.html"&gt;TextUtils&lt;/a&gt;. This class also has a lot of other helpful methods like &lt;a href="http://developer.android.com/reference/android/text/TextUtils.html#join(java.lang.CharSequence, java.lang.Object[])"&gt;join()&lt;/a&gt; to join an array of elements to a String using a&amp;nbsp;delimiter&amp;nbsp;or &lt;a href="http://developer.android.com/reference/android/text/TextUtils.html#getReverse(java.lang.CharSequence, int, int)"&gt;getReverse() &lt;/a&gt;to reverse a String (Take that interview question!).&lt;br /&gt;
&lt;br /&gt;
In addition to that the TextUtils class has a method &lt;a href="http://developer.android.com/reference/android/text/TextUtils.html#isEmpty(java.lang.CharSequence)"&gt;isEmpty()&lt;/a&gt; that is available since API level 1.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-nzyWV2TAHaM/UMbelfdSHCI/AAAAAAAAHCA/Z2lLIH_YddU/s1600/TextUtils.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-nzyWV2TAHaM/UMbelfdSHCI/AAAAAAAAHCA/Z2lLIH_YddU/s1600/TextUtils.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Phew! By the way: &lt;a href="http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.1.1_r1/android/text/TextUtils.java#TextUtils.isEmpty%28java.lang.CharSequence%29"&gt;Internally&lt;/a&gt; isEmpty() checks if the length of the String is 0 (and does a null check).&lt;img src="http://feeds.feedburner.com/~r/AndroidZeitgeist/~4/jbePXNFlMnA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.androidzeitgeist.com/feeds/8734004828090755204/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.androidzeitgeist.com/2012/12/string-is-empty.html#comment-form" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1531829516427013333/posts/default/8734004828090755204?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1531829516427013333/posts/default/8734004828090755204?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/AndroidZeitgeist/~3/jbePXNFlMnA/string-is-empty.html" title="Mind the gap: String.isEmpty()" /><author><name>Sebastian Kaspari</name><uri>https://plus.google.com/112283223674539938062</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-20YfT7gfh08/AAAAAAAAAAI/AAAAAAAALWI/LZ-ps7enWlI/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-FWLirpvHLAM/UMbfKHp3tUI/AAAAAAAAHCI/NPnjM4Qx5Pk/s72-c/isemptyvariants.png" height="72" width="72" /><thr:total>5</thr:total><gd:extendedProperty name="commentSource" value="1" /><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD" /><feedburner:origLink>http://www.androidzeitgeist.com/2012/12/string-is-empty.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkMFQX8zeSp7ImA9WhNREUk.&quot;"><id>tag:blogger.com,1999:blog-1531829516427013333.post-4510260145421419236</id><published>2012-11-05T20:40:00.000+01:00</published><updated>2012-11-05T20:40:10.181+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-11-05T20:40:10.181+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="SeekBar" /><category scheme="http://www.blogger.com/atom/ns#" term="scrolling" /><category scheme="http://www.blogger.com/atom/ns#" term="fake dragging" /><category scheme="http://www.blogger.com/atom/ns#" term="bezel swipe" /><category scheme="http://www.blogger.com/atom/ns#" term="ViewPager" /><category scheme="http://www.blogger.com/atom/ns#" term="support library" /><title>Examining the ViewPager #3</title><content type="html">&lt;span style="font-size: x-small;"&gt;This article is part of a series of articles about the ViewPager component.&amp;nbsp;&lt;/span&gt;&lt;a href="http://www.androidzeitgeist.com/p/viewpager.html" style="font-size: small;"&gt;Click here&lt;/a&gt;&lt;span style="font-size: x-small;"&gt;&amp;nbsp;to see a list of&amp;nbsp;&lt;/span&gt;&lt;a href="http://www.androidzeitgeist.com/p/viewpager.html" style="font-size: small;"&gt;all articles of this series&lt;/a&gt;&lt;span style="font-size: x-small;"&gt;.&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style="font-size: large;"&gt;Horizontal scrolling pages&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Have you ever tried putting horizontal scrolling components inside a &lt;a href="http://developer.android.com/reference/android/support/v4/view/ViewPager.html"&gt;ViewPager&lt;/a&gt;? Well, since revision 9 of the &lt;a href="http://developer.android.com/tools/extras/support-library.html"&gt;support library&lt;/a&gt; this is supported by the ViewPager. As long as the inner component can scroll horizontally this component will be scrolled. Whenever the component can't be further scrolled the ViewPager will handle the touch events and you start to switch to the next page. This works out-of-the-box for scrolling view components of Android like the &lt;a href="http://developer.android.com/reference/android/webkit/WebView.html"&gt;WebView&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Internally the ViewPager uses &lt;a href="http://developer.android.com/reference/android/support/v4/view/ViewCompat.html#canScrollHorizontally(android.view.View, int)"&gt;ViewCompat.canScrollHorizontally(View v, int direction)&lt;/a&gt;&amp;nbsp;to determine if a child view can be scrolled horizontally and should receive the according touch events. Unfortunately this method is only implemented for Android 4.0 (API level 14) and above. For all earlier versions this method will always return false and therefore never scroll the components inside the ViewPager.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style="font-size: large;"&gt;Bezel swipe&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Allowing horizontal scrolling components introduces a new problem: What if you want to switch pages but not scroll every component to its horizontal end? When you start the swipe at the phone's bezel (or actually from the edge of the ViewPager) you'll switch pages instead of scrolling the page's content. This gesture is called &lt;i&gt;bezel swipe&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
For reading more about the bezel swipe gesture from a UI point of view read "&lt;a href="http://www.androiduipatterns.com/2012/02/bezel-swipe-solution-to-pan-and-swipe.html"&gt;Bezel swipe, a Solution to Pan and Swipe Confusion?&lt;/a&gt;" on &lt;a href="http://www.androiduipatterns.com/"&gt;Android UI Patterns&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
The good news is again: The ViewPager supports bezel swipe out of the box. But as you can't horizontally scroll inside pages on devices running an Android version lower than 4.0 (API level 14) bezel swipe isn't of any use on these as well.&lt;br /&gt;
&lt;br /&gt;
The area to start a bezel swipe has a width of either 16dp or a 10th of the total width of the ViewPager depending on which one is smaller.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-dNYV1OuZvdQ/UJgLXTptXHI/AAAAAAAAGS4/Zt0OXlBwbaM/s1600/viewpager_bezel_swipe.png" imageanchor="1"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-dNYV1OuZvdQ/UJgLXTptXHI/AAAAAAAAGS4/Zt0OXlBwbaM/s1600/viewpager_bezel_swipe.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;Fake dragging&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
The ViewPager supports fake dragging. Fake dragging can be used to simulate a dragging event/animation, e.g. for detecting drag events on a different component and delegating these to the ViewPager.&lt;br /&gt;
&lt;br /&gt;
You have to signal the ViewPager when to start or end a fake drag by calling &lt;a href="http://developer.android.com/reference/android/support/v4/view/ViewPager.html#beginFakeDrag()"&gt;beginFakeDrag()&lt;/a&gt; and &lt;a href="http://developer.android.com/reference/android/support/v4/view/ViewPager.html#endFakeDrag()"&gt;endFakeDrag()&lt;/a&gt; on it. After starting a fake drag you can use &lt;a href="http://developer.android.com/reference/android/support/v4/view/ViewPager.html#fakeDragBy(float)"&gt;fakeDragBy(float)&lt;/a&gt; to drag the ViewPager by the given amount of pixels along the x axis (negative values to the left and positive values to the right).&lt;br /&gt;
&lt;br /&gt;
The following example uses a &lt;a href="http://developer.android.com/reference/android/widget/SeekBar.html"&gt;SeekBar&lt;/a&gt;&amp;nbsp;whose current progress state is used to fake drag a ViewPager by the given percentage.&lt;br /&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-SFr1EyEfN4Q/UJgNTawCuSI/AAAAAAAAGTA/Pq_75XpuIes/s1600/SeekBarPagerListener.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-SFr1EyEfN4Q/UJgNTawCuSI/AAAAAAAAGTA/Pq_75XpuIes/s1600/SeekBarPagerListener.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;a href="https://github.com/pocmo/Android-Zeitgeist-Samples/blob/master/ViewPager/03/SeekBarPagerListener.java"&gt;SeekBarPagerListener.java&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
This video shows the fake drag in action:&lt;br /&gt;
&lt;br /&gt;
&lt;iframe allowfullscreen="allowfullscreen" frameborder="0" height="360" src="http://www.youtube.com/embed/us8w2g9YXC4?rel=0" width="480"&gt;&lt;/iframe&gt;&lt;img src="http://feeds.feedburner.com/~r/AndroidZeitgeist/~4/GsNXoeK7N6Y" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.androidzeitgeist.com/feeds/4510260145421419236/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.androidzeitgeist.com/2012/11/examining-viewpager-3.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1531829516427013333/posts/default/4510260145421419236?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1531829516427013333/posts/default/4510260145421419236?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/AndroidZeitgeist/~3/GsNXoeK7N6Y/examining-viewpager-3.html" title="Examining the ViewPager #3" /><author><name>Sebastian Kaspari</name><uri>https://plus.google.com/112283223674539938062</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-20YfT7gfh08/AAAAAAAAAAI/AAAAAAAALWI/LZ-ps7enWlI/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-dNYV1OuZvdQ/UJgLXTptXHI/AAAAAAAAGS4/Zt0OXlBwbaM/s72-c/viewpager_bezel_swipe.png" height="72" width="72" /><thr:total>1</thr:total><gd:extendedProperty name="commentSource" value="1" /><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD" /><feedburner:origLink>http://www.androidzeitgeist.com/2012/11/examining-viewpager-3.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEIBSHg8cSp7ImA9WhNSFk4.&quot;"><id>tag:blogger.com,1999:blog-1531829516427013333.post-5361828375857120954</id><published>2012-10-30T23:35:00.000+01:00</published><updated>2012-10-30T23:35:59.679+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-10-30T23:35:59.679+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Instant Mustache" /><category scheme="http://www.blogger.com/atom/ns#" term="Uri" /><category scheme="http://www.blogger.com/atom/ns#" term="Intent" /><title>Displaying the taken picture – Instant Mustache #7</title><content type="html">&lt;div&gt;
&lt;span style="font-size: x-small;"&gt;This article is part of a series of articles about the development process of Instant Mustache, a fun camera app that adds mustaches to all faces using face detection. &lt;a href="http://www.androidzeitgeist.com/p/instant-mustache.html"&gt;Click here&lt;/a&gt; to get a chronological list of all published &lt;a href="http://www.androidzeitgeist.com/p/instant-mustache.html"&gt;articles about Instant Mustache&lt;/a&gt;.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;Writing the PhotoActivity&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
In the &lt;a href="http://www.androidzeitgeist.com/2012/10/taking-picture-instant-mustache-6.html"&gt;last article&lt;/a&gt; we wrote the code to take a camera picture and save it on the external storage. After saving the file the activity will be finished and a Toast will show up. This is not really user-friendly so now we'll write our next activity which will display the taken picture and later offer the option to share this picture.&lt;br /&gt;
&lt;br /&gt;
We'll start by creating an empty activity called &lt;a href="https://github.com/pocmo/Instant-Mustache/blob/article-07/src/com/androidzeitgeist/mustache/activity/PhotoActivity.java"&gt;PhotoActivity&lt;/a&gt; and add it to the &lt;a href="https://github.com/pocmo/Instant-Mustache/blob/article-07/AndroidManifest.xml#L30"&gt;manifest&lt;/a&gt; of our application. For now the layout will only contain an &lt;a href="http://developer.android.com/reference/android/widget/ImageView.html"&gt;ImageView&lt;/a&gt; to display the picture:&lt;br /&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-KnA5sDjgZds/UJBOSqCkiZI/AAAAAAAAF2k/q3_2TKxMJ8I/s1600/layout_activity_photo.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-KnA5sDjgZds/UJBOSqCkiZI/AAAAAAAAF2k/q3_2TKxMJ8I/s1600/layout_activity_photo.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;a href="https://github.com/pocmo/Instant-Mustache/blob/article-07/res/layout/activity_photo.xml"&gt;activity_photo.xml&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
Instead of showing a toast in our &lt;a href="https://github.com/pocmo/Instant-Mustache/blob/article-07/src/com/androidzeitgeist/mustache/activity/CameraActivity.java"&gt;CameraActivity&lt;/a&gt; we create an Intent to start the PhotoActivity and use &lt;a href="http://developer.android.com/reference/android/content/Intent.html#setData(android.net.Uri)"&gt;setData(Uri)&lt;/a&gt; on the Intent object to pass a &lt;a href="http://developer.android.com/reference/android/net/Uri.html"&gt;Uri&lt;/a&gt; pointing to the picture file:&lt;br /&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-VSkxvSyGYTU/UJBOjJYq-aI/AAAAAAAAF2s/q1DBQt-Ib9A/s1600/intent_start_photo_activity.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-VSkxvSyGYTU/UJBOjJYq-aI/AAAAAAAAF2s/q1DBQt-Ib9A/s1600/intent_start_photo_activity.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;a href="https://github.com/pocmo/Instant-Mustache/blob/article-07/src/com/androidzeitgeist/mustache/activity/CameraActivity.java#L116"&gt;onPictureTaken() - CameraActivity.java&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
In &lt;a href="https://github.com/pocmo/Instant-Mustache/blob/article-07/src/com/androidzeitgeist/mustache/activity/PhotoActivity.java#L19"&gt;onCreate(Bundle)&lt;/a&gt; of the PhotoActivity we'll retrieve the Uri from the Intent and pass it to the ImageView. The ImageView will take care of loading the picture from the external storage and displaying it.&lt;br /&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-tE-1b0nu5Ic/UJBO0nSip_I/AAAAAAAAF20/Thmkq7JwsmM/s1600/photo_activity_on_create.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-tE-1b0nu5Ic/UJBO0nSip_I/AAAAAAAAF20/Thmkq7JwsmM/s1600/photo_activity_on_create.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;a href="https://github.com/pocmo/Instant-Mustache/blob/article-07/src/com/androidzeitgeist/mustache/activity/PhotoActivity.java#L19"&gt;onCreate() - PhotoActivity.java&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
And that's already all the code we need for the first version of the &lt;a href="https://github.com/pocmo/Instant-Mustache/blob/article-07/src/com/androidzeitgeist/mustache/activity/PhotoActivity.java"&gt;PhotoActivity&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-sX-QuJWGZtQ/UJBVljLcABI/AAAAAAAAF3I/XEL1UJHnjiI/s1600/camera_and_photo_screenshot.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-sX-QuJWGZtQ/UJBVljLcABI/AAAAAAAAF3I/XEL1UJHnjiI/s1600/camera_and_photo_screenshot.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;CameraActivity (left) and PhotoActivity (right)&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;&lt;img src="http://feeds.feedburner.com/~r/AndroidZeitgeist/~4/bA7tWUcBxoc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.androidzeitgeist.com/feeds/5361828375857120954/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.androidzeitgeist.com/2012/10/displaying-taken-picture-instant.html#comment-form" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1531829516427013333/posts/default/5361828375857120954?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1531829516427013333/posts/default/5361828375857120954?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/AndroidZeitgeist/~3/bA7tWUcBxoc/displaying-taken-picture-instant.html" title="Displaying the taken picture – Instant Mustache #7" /><author><name>Sebastian Kaspari</name><uri>https://plus.google.com/112283223674539938062</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-20YfT7gfh08/AAAAAAAAAAI/AAAAAAAALWI/LZ-ps7enWlI/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-KnA5sDjgZds/UJBOSqCkiZI/AAAAAAAAF2k/q3_2TKxMJ8I/s72-c/layout_activity_photo.png" height="72" width="72" /><thr:total>3</thr:total><gd:extendedProperty name="commentSource" value="1" /><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD" /><feedburner:origLink>http://www.androidzeitgeist.com/2012/10/displaying-taken-picture-instant.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0MARHs4fCp7ImA9WhNSFk4.&quot;"><id>tag:blogger.com,1999:blog-1531829516427013333.post-73829038323965617</id><published>2012-10-26T20:59:00.000+02:00</published><updated>2012-10-30T23:17:25.534+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-10-30T23:17:25.534+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="CameraFragment" /><category scheme="http://www.blogger.com/atom/ns#" term="camera" /><category scheme="http://www.blogger.com/atom/ns#" term="MediaScanner" /><category scheme="http://www.blogger.com/atom/ns#" term="Instant Mustache" /><category scheme="http://www.blogger.com/atom/ns#" term="External storage" /><category scheme="http://www.blogger.com/atom/ns#" term="OnClickListener" /><category scheme="http://www.blogger.com/atom/ns#" term="picture" /><title>Taking a picture – Instant Mustache #6</title><content type="html">&lt;span style="font-size: x-small;"&gt;This article is part of a series of articles about the development process of Instant Mustache, a fun camera app that adds mustaches to all faces using face detection.&amp;nbsp;&lt;/span&gt;&lt;a href="http://www.androidzeitgeist.com/p/instant-mustache.html" style="font-size: small;"&gt;Click here&lt;/a&gt;&lt;span style="font-size: x-small;"&gt;&amp;nbsp;to get a chronological list of all published&amp;nbsp;&lt;/span&gt;&lt;a href="http://www.androidzeitgeist.com/p/instant-mustache.html" style="font-size: small;"&gt;articles about Instant Mustache&lt;/a&gt;&lt;span style="font-size: x-small;"&gt;.&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
After writing the necessary code to display a camera preview in &lt;a href="http://www.androidzeitgeist.com/2012/10/displaying-camera-preview-instant.html"&gt;the last article&lt;/a&gt; it's now time to actually take a picture and save it on the external storage of the device.&lt;br /&gt;
&lt;br /&gt;
We start by extending the layout of the &lt;a href="https://github.com/pocmo/Instant-Mustache/blob/article-06/src/com/androidzeitgeist/mustache/activity/CameraActivity.java"&gt;CameraActivity&lt;/a&gt; to include a button for taking a picture. We assign a method to it to be called when the user clicks on the button via the attribute &lt;a href="http://developer.android.com/reference/android/view/View.html#attr_android:onClick"&gt;android:onClick&lt;/a&gt;. Another option would be to assign an &lt;a href="http://developer.android.com/reference/android/view/View.OnClickListener.html"&gt;OnClickListener&lt;/a&gt; to the view in code. Defining the method in the XML results in less code but has the disadvantage of not being checked by the compiler. Since one of the last releases of the Android SDK the &lt;a href="http://tools.android.com/tips/lint"&gt;lint&lt;/a&gt; tool is able to check the onClick attributes for correctness. So we will use the XML attribute here.&lt;br /&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-hmHriQ9ppUo/UIqjpzAIkZI/AAAAAAAAFpQ/PJZvXOEn5XE/s1600/activity_camera.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-hmHriQ9ppUo/UIqjpzAIkZI/AAAAAAAAFpQ/PJZvXOEn5XE/s1600/activity_camera.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;a href="https://github.com/pocmo/Instant-Mustache/blob/article-06/res/layout/activity_camera.xml"&gt;activity_camera.xml&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
As we encapsulated the code handling the &lt;a href="http://developer.android.com/reference/android/hardware/Camera.html"&gt;Camera&lt;/a&gt; object inside the &lt;a href="https://github.com/pocmo/Instant-Mustache/blob/article-06/src/com/androidzeitgeist/mustache/fragment/CameraFragment.java"&gt;CameraFragment&lt;/a&gt; class the activity just calls takePicture() on the fragment when the user presses the button.&lt;br /&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-FE7ro562XUI/UIqkAHnPvzI/AAAAAAAAFpY/-IZ0ncr7CbU/s1600/CameraActivity_takePicture.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-FE7ro562XUI/UIqkAHnPvzI/AAAAAAAAFpY/-IZ0ncr7CbU/s1600/CameraActivity_takePicture.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;a href="https://github.com/pocmo/Instant-Mustache/blob/article-06/src/com/androidzeitgeist/mustache/activity/CameraActivity.java#L64"&gt;takePicutre() - CameraActivity.java&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
The fragment calls &lt;a href="http://developer.android.com/reference/android/hardware/Camera.html#takePicture(android.hardware.Camera.ShutterCallback, android.hardware.Camera.PictureCallback, android.hardware.Camera.PictureCallback, android.hardware.Camera.PictureCallback)"&gt;takePicture()&lt;/a&gt; on the Camera object. It's possible to pass up to four callbacks to this method: A shutter callback, a raw callback, a postview callback and a jpeg callback. According to the documentation their usage is:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;The shutter callback occurs after the image is captured. This can be used to trigger a sound to let the user know that image has been captured.&lt;/li&gt;
&lt;li&gt;The raw callback occurs when the raw image data is available.&lt;/li&gt;
&lt;li&gt;The postview callback occurs when a scaled, fully processed postview image is available.&lt;/li&gt;
&lt;li&gt;The jpeg callback occurs when the compressed image is available.&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
We are only interested in the JPEG image. The fragment itself is also the callback so we'll implement the Camera.PictureCallback interface.&lt;br /&gt;
&lt;br /&gt;
Once the picture is taken &lt;a href="http://developer.android.com/reference/android/hardware/Camera.PictureCallback.html#onPictureTaken(byte[], android.hardware.Camera)"&gt;onPictureTaken()&lt;/a&gt; will be called with a byte array. We decode the given byte array and create a &lt;a href="http://developer.android.com/reference/android/graphics/Bitmap.html"&gt;Bitmap&lt;/a&gt; object and pass it via the &lt;a href="https://github.com/pocmo/Instant-Mustache/blob/article-06/src/com/androidzeitgeist/mustache/listener/CameraFragmentListener.java"&gt;CameraFragmentListener&lt;/a&gt; interface to our CameraActivity. Later we will use this bitmap to draw the mustaches on it.&lt;br /&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-HmhBl2pWTlo/UIqkdSoODnI/AAAAAAAAFpg/cJ69yQZOIeg/s1600/CameraFragment_onPictureTaken.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-HmhBl2pWTlo/UIqkdSoODnI/AAAAAAAAFpg/cJ69yQZOIeg/s1600/CameraFragment_onPictureTaken.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;a href="https://github.com/pocmo/Instant-Mustache/blob/article-06/src/com/androidzeitgeist/mustache/fragment/CameraFragment.java#L224"&gt;onPictureTaken() - CameraFragment.java&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style="font-size: large;"&gt;Saving the picture to the external storage&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Once the activity receives the bitmap object it needs to do a bunch of things:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Determine the directory to save the picture to and create it if necessary&lt;/li&gt;
&lt;li&gt;Create a unique file for the picture inside the directory and save the image data to it&lt;/li&gt;
&lt;li&gt;Notify the MediaScanner that we created a new file&lt;/li&gt;
&lt;li&gt;Show a toast that the picture has been saved successfully (For now until we've written the activity to display the taken picture).&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;Determining the directory&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
We want to save the picture into a directory on the external storage that is visible for all other applications. By calling &lt;a href="http://developer.android.com/reference/android/os/Environment.html#getExternalStoragePublicDirectory(java.lang.String)"&gt;Environment.getExternalStoragePublicDirectory()&lt;/a&gt; and passing &lt;a href="http://developer.android.com/reference/android/os/Environment.html#DIRECTORY_PICTURES"&gt;Environment.DIRECTORY_PICTURES&lt;/a&gt; we get the public directory for pictures (Available since API Level 8). Inside this directory we'll create a directory with the name of our application (if it doesn't exist already).&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;/div&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-etMHinejAMU/UIqlvdRKOlI/AAAAAAAAFpo/QlH_Lu4dUOY/s1600/determining_directory.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-etMHinejAMU/UIqlvdRKOlI/AAAAAAAAFpo/QlH_Lu4dUOY/s1600/determining_directory.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;a href="https://github.com/pocmo/Instant-Mustache/blob/article-06/src/com/androidzeitgeist/mustache/activity/CameraActivity.java#L77"&gt;onPictureTaken() - CameraActivity.java&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
&amp;nbsp;&lt;span style="font-size: large;"&gt;Saving the file&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
We'll create a file with a unique file name containing a timestamp, e.g.: MUSTACHE_20121031_235959.jpg. The &lt;a href="http://developer.android.com/reference/android/graphics/Bitmap.html#compress(android.graphics.Bitmap.CompressFormat, int, java.io.OutputStream)"&gt;compress()&lt;/a&gt; method of the bitmap object is used to save the picture into the file.&lt;br /&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-yNhLaUTQOs8/UIqlxhiP9tI/AAAAAAAAFp0/HlPPxj7_L9w/s1600/saving_picture.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-yNhLaUTQOs8/UIqlxhiP9tI/AAAAAAAAFp0/HlPPxj7_L9w/s1600/saving_picture.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;a href="https://github.com/pocmo/Instant-Mustache/blob/article-06/src/com/androidzeitgeist/mustache/activity/CameraActivity.java#L92"&gt;onPictureTaken() - CameraActivity.java&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;Notifying the MediaScanner&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Scanning the SD card for changes is costly. Therefore most Android versions only scan the whole card if the card is re-inserted or was mounted by another device. This seems to be different in different vendor versions of Android but nevertheless you can't assume a file to be seen by other applications (for example the gallery) until it has been scanned by the &lt;a href="http://developer.android.com/reference/android/media/MediaScannerConnection.html"&gt;MediaScanner&lt;/a&gt;. For that reason we'll notify the MediaScanner about the file we've created.&lt;br /&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-BKiT4GJmj8s/UIqlw9LsiFI/AAAAAAAAFpw/K1_jEkvhX98/s1600/notify_mediascanner.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-BKiT4GJmj8s/UIqlw9LsiFI/AAAAAAAAFpw/K1_jEkvhX98/s1600/notify_mediascanner.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;a href="https://github.com/pocmo/Instant-Mustache/blob/article-06/src/com/androidzeitgeist/mustache/activity/CameraActivity.java#L107"&gt;onPictureTaken() - CameraActivity.java&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
By now we've already created a simple camera application. We can take pictures and they show up in the gallery of the device. Pretty cool so far, huh?&lt;img src="http://feeds.feedburner.com/~r/AndroidZeitgeist/~4/c-K683UuF5g" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.androidzeitgeist.com/feeds/73829038323965617/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.androidzeitgeist.com/2012/10/taking-picture-instant-mustache-6.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1531829516427013333/posts/default/73829038323965617?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1531829516427013333/posts/default/73829038323965617?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/AndroidZeitgeist/~3/c-K683UuF5g/taking-picture-instant-mustache-6.html" title="Taking a picture – Instant Mustache #6" /><author><name>Sebastian Kaspari</name><uri>https://plus.google.com/112283223674539938062</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-20YfT7gfh08/AAAAAAAAAAI/AAAAAAAALWI/LZ-ps7enWlI/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-hmHriQ9ppUo/UIqjpzAIkZI/AAAAAAAAFpQ/PJZvXOEn5XE/s72-c/activity_camera.png" height="72" width="72" /><thr:total>1</thr:total><gd:extendedProperty name="commentSource" value="1" /><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD" /><feedburner:origLink>http://www.androidzeitgeist.com/2012/10/taking-picture-instant-mustache-6.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkUCR3gzeCp7ImA9WhNREUk.&quot;"><id>tag:blogger.com,1999:blog-1531829516427013333.post-8727545494996059717</id><published>2012-10-25T21:24:00.000+02:00</published><updated>2012-11-05T19:31:06.680+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-11-05T19:31:06.680+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="OnPageChangeListener" /><category scheme="http://www.blogger.com/atom/ns#" term="margin" /><category scheme="http://www.blogger.com/atom/ns#" term="ViewPager" /><category scheme="http://www.blogger.com/atom/ns#" term="Offscreen pages" /><title>Examining the ViewPager #2</title><content type="html">&lt;span style="font-size: x-small;"&gt;This article is part of a series of articles about the ViewPager component.&amp;nbsp;&lt;/span&gt;&lt;a href="http://www.androidzeitgeist.com/p/viewpager.html" style="font-size: small;"&gt;Click here&lt;/a&gt;&lt;span style="font-size: x-small;"&gt;&amp;nbsp;to see a list of&amp;nbsp;&lt;/span&gt;&lt;a href="http://www.androidzeitgeist.com/p/viewpager.html" style="font-size: small;"&gt;all articles of this series&lt;/a&gt;&lt;span style="font-size: x-small;"&gt;.&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style="font-size: large;"&gt;Offscreen pages&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
The &lt;a href="http://developer.android.com/reference/android/support/v4/view/ViewPager.html"&gt;ViewPager&lt;/a&gt; doesn't create all its pages at once. When using a lot of pages this would be horribly slow and even unnecessary if the user would never swipe through all these pages. By default the ViewPager only creates the current page as well as the offscreen pages to the left and right of the current page.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-HzlJvCZIyQc/UIkzJpr1neI/AAAAAAAAFls/jfMZCwnu30I/s1600/offscreen_pages.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-HzlJvCZIyQc/UIkzJpr1neI/AAAAAAAAFls/jfMZCwnu30I/s1600/offscreen_pages.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
If you only use a small amount of pages you may get a better performance by creating them all at once. You can use &lt;a href="http://developer.android.com/reference/android/support/v4/view/ViewPager.html#setOffscreenPageLimit(int)"&gt;setOffscreenPageLimit(int limit)&lt;/a&gt; to set the number of pages that will be created and retained. Note that the limit applies to both sides of the current page. So if you set the offscreen page limit to 2 the ViewPager will retain 5 pages: The current page plus 2 pages to the left and right.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style="font-size: large;"&gt;Responding to changing states&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
You can get notified whenever the displayed page changes or is incrementally scrolled. To listen to these state changes you can implement the &lt;a href="http://developer.android.com/reference/android/support/v4/view/ViewPager.OnPageChangeListener.html"&gt;OnPageChangeListener&lt;/a&gt; interface or extend the &lt;a href="http://developer.android.com/reference/android/support/v4/view/ViewPager.SimpleOnPageChangeListener.html"&gt;SimpleOnPageChangeListener&lt;/a&gt; class if you do not intent to override every method of the interfacce.&lt;br /&gt;
&lt;br /&gt;
The following example listener updates the title of the activity according to the title of the currently selected page:&lt;br /&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-xgUfOiVWc_g/UIkzQ_OCF8I/AAAAAAAAFl0/Fp_eXNYlt4g/s1600/UpdateTitleListener.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-xgUfOiVWc_g/UIkzQ_OCF8I/AAAAAAAAFl0/Fp_eXNYlt4g/s1600/UpdateTitleListener.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;a href="https://github.com/pocmo/Android-Zeitgeist-Samples/blob/master/ViewPager/02/UpdateTitleListener.java"&gt;UpdateTitleListener.java&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style="font-size: large;"&gt;Margin between pages&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
When scrolling through pages they all look like glued together. You can use &lt;a href="http://developer.android.com/reference/android/support/v4/view/ViewPager.html#setPageMargin(int)"&gt;setPageMargin(int pixels)&lt;/a&gt; to define a margin between pages. The gap is filled with the background color of the ViewPager.&lt;br /&gt;
&lt;br /&gt;
The following screenshots are showing the same ViewPager during switching pages. The left screenshot shows the ViewPager with no page margin set. In the right screenshot the margin has been set to 20 pixels. Notice that the method expects the margin to be defined in pixels. To use the same physical margin on all kind of screens independent from their pixel density define the margin in density independent pixels (dp) and &lt;a href="http://stackoverflow.com/a/6327095/234908"&gt;convert them to the actual number of pixels&lt;/a&gt; for the current screen.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-fS9q-7IO-Uc/UIkzWvgeSoI/AAAAAAAAFl8/GESmB7vau7c/s1600/page_margin.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-fS9q-7IO-Uc/UIkzWvgeSoI/AAAAAAAAFl8/GESmB7vau7c/s1600/page_margin.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
It's also possible to define a drawable that will be used to fill the margin between two pages using &lt;a href="http://developer.android.com/reference/android/support/v4/view/ViewPager.html#setPageMarginDrawable(int)"&gt;setPageMarginDrawable(int resId)&lt;/a&gt; or &lt;a href="http://developer.android.com/reference/android/support/v4/view/ViewPager.html#setPageMarginDrawable(android.graphics.drawable.Drawable)"&gt;setPageMarginDrawable(Drawable d)&lt;/a&gt;. The best approach is to use a &lt;a href="http://developer.android.com/guide/topics/graphics/2d-graphics.html#nine-patch"&gt;Nine-patch&lt;/a&gt; that be scaled dynamically by the system to fill the space between the pages.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style="font-size: large;"&gt;Switching pages programmatically&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
You can also switch between pages programmatically. Using &lt;a href="http://developer.android.com/reference/android/support/v4/view/ViewPager.html#setCurrentItem(int, boolean)"&gt;setCurrentItem(int position, boolean smoothScroll)&lt;/a&gt; you can switch to the given position. If the second parameter is &lt;span style="color: #660000;"&gt;true&lt;/span&gt; a smooth animated transition is being performed. Using &lt;span style="color: #660000;"&gt;false&lt;/span&gt; the ViewPager will switch to the given page without any animation. If you always want to switch pages with an animation you can also leave the second parameter and use &lt;a href="http://developer.android.com/reference/android/support/v4/view/ViewPager.html#setCurrentItem(int)"&gt;setCurrentItem(int position)&lt;/a&gt;.&lt;img src="http://feeds.feedburner.com/~r/AndroidZeitgeist/~4/EUMG4ssJLOA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.androidzeitgeist.com/feeds/8727545494996059717/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.androidzeitgeist.com/2012/10/examining-viewpager-2.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1531829516427013333/posts/default/8727545494996059717?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1531829516427013333/posts/default/8727545494996059717?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/AndroidZeitgeist/~3/EUMG4ssJLOA/examining-viewpager-2.html" title="Examining the ViewPager #2" /><author><name>Sebastian Kaspari</name><uri>https://plus.google.com/112283223674539938062</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-20YfT7gfh08/AAAAAAAAAAI/AAAAAAAALWI/LZ-ps7enWlI/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-HzlJvCZIyQc/UIkzJpr1neI/AAAAAAAAFls/jfMZCwnu30I/s72-c/offscreen_pages.png" height="72" width="72" /><thr:total>1</thr:total><gd:extendedProperty name="commentSource" value="1" /><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD" /><feedburner:origLink>http://www.androidzeitgeist.com/2012/10/examining-viewpager-2.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0IGQn0-cCp7ImA9WhNSFk4.&quot;"><id>tag:blogger.com,1999:blog-1531829516427013333.post-1618586447717593615</id><published>2012-10-22T18:30:00.000+02:00</published><updated>2012-10-30T23:18:43.358+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-10-30T23:18:43.358+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="FragmentPagerAdapter" /><category scheme="http://www.blogger.com/atom/ns#" term="ViewPager" /><category scheme="http://www.blogger.com/atom/ns#" term="PagerAdapter" /><category scheme="http://www.blogger.com/atom/ns#" term="FragmentStatePagerAdapter" /><title>Examining the ViewPager #1</title><content type="html">&lt;span style="font-size: x-small;"&gt;This article is part of a series of articles about the ViewPager component. &lt;a href="http://www.androidzeitgeist.com/p/viewpager.html"&gt;Click here&lt;/a&gt; to see a list of &lt;a href="http://www.androidzeitgeist.com/p/viewpager.html"&gt;all articles of this series&lt;/a&gt;.&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
The &lt;a href="http://developer.android.com/tools/extras/support-library.html"&gt;Android support library&lt;/a&gt; offers a great UI component for horizontal scrolling pages: &lt;a href="http://developer.android.com/reference/android/support/v4/view/ViewPager.html"&gt;The ViewPager&lt;/a&gt;. Over the last iterations of the support library more and more functionality has been added to the ViewPager silently. For that reason I decided to study the various features of the ViewPager more closely. This will be a series of articles covering several of these features.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;Disclaimer upfront&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
According to the &lt;a href="http://developer.android.com/reference/android/support/v4/view/ViewPager.html"&gt;documentation of the ViewPager&lt;/a&gt; the implementation and API of the class may change in future releases. Therefore also this blog posting may not be up-to-date if you are reading this a long time after the published date. Check the &lt;a href="http://developer.android.com/reference/android/support/v4/view/ViewPager.html"&gt;documentation&lt;/a&gt; if some of the examples may not work anymore as I described them here.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;The basics&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
The ViewPager is a &lt;a href="http://developer.android.com/reference/android/view/ViewGroup.html"&gt;ViewGroup&lt;/a&gt; that displays by default one page at a time. The user can switch between these pages by swiping horizontally. A &lt;a href="http://developer.android.com/reference/android/support/v4/view/PagerAdapter.html"&gt;PagerAdapter&lt;/a&gt; dynamically provides these pages which can be just views or fragments. However the ViewPager is not an AdapterView like the ListView or the GridView. Therefore you need to implement a specific adapter class in order to use the ViewPager class.&lt;br /&gt;
&lt;br /&gt;
The following video shows a ViewPager with different colored pages:&lt;br /&gt;
&lt;br /&gt;
&lt;iframe allowfullscreen="allowfullscreen" frameborder="0" height="360" src="http://www.youtube.com/embed/tcnGyRc9t0M?rel=0" width="480"&gt;&lt;/iframe&gt;

&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;Adapter using fragments&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
The easiest way to write an adapter for a ViewPager is to use fragments and let your adapter implementation extend the &lt;a href="http://developer.android.com/reference/android/support/v4/app/FragmentPagerAdapter.html"&gt;FragmentPagerAdapter&lt;/a&gt; class. You only need to implement &lt;a href="http://developer.android.com/reference/android/support/v4/app/FragmentPagerAdapter.html#getItem(int)"&gt;getItem(int position)&lt;/a&gt; to return a fragment for the page at the given position and &lt;a href="http://developer.android.com/reference/android/support/v4/view/PagerAdapter.html#getCount()"&gt;getCount()&lt;/a&gt; to return the number of pages to display.&lt;br /&gt;
&lt;br /&gt;
The following implementation shows the FragmentPagerAdapter used for the video above:&lt;br /&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-CkknYiuF5vQ/UIQMY-pOFOI/AAAAAAAAFjY/es0HrjuPA0U/s1600/SampleFragmentPagerAdapter.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-CkknYiuF5vQ/UIQMY-pOFOI/AAAAAAAAFjY/es0HrjuPA0U/s1600/SampleFragmentPagerAdapter.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;a href="https://github.com/pocmo/Android-Zeitgeist-Samples/blob/master/ViewPager/01/SampleFragmentPagerAdapter.java"&gt;SampleFragmentPagerAdapter.java&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;Saving fragment states&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
When using a &lt;a href="http://developer.android.com/reference/android/support/v13/app/FragmentPagerAdapter.html"&gt;FragmentPagerAdapter&lt;/a&gt; and swiping through the pages the ViewPager may eventually have created fragments for all the pages. Depending on the number of pages this may need a large amount of memory just for holding all the offscreen pages. To solve this problem the support library offers the &lt;a href="http://developer.android.com/reference/android/support/v4/app/FragmentStatePagerAdapter.html"&gt;FragmentStatePagerAdapter&lt;/a&gt; class. This adapter will destroy fragments not visible to the user when needed. Whenever this happens the adapter saves the fragment's current state using &lt;a href="http://developer.android.com/reference/android/app/Fragment.html#onSaveInstanceState(android.os.Bundle)"&gt;onSaveInstanceState(Bundle outState) &lt;/a&gt;of the fragment class to restore it when the fragment for this page gets recreated.&lt;br /&gt;
&lt;br /&gt;
Implementing an adapter extending the FragmentStatePagerAdapter is exactly the same as when using the FragmentPagerAdapter class. Just your fragment needs to take care of saving its state when getting destroyed. Take a look at the &lt;a href="http://developer.android.com/reference/android/app/Fragment.html#onSaveInstanceState(android.os.Bundle)"&gt;documentation&lt;/a&gt; for an example on how to retain the state of a fragment.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;Adapter using views&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
You can also use the ViewPager with only View objects as pages if using fragments isn't an option for you. It's a bit more tricky to implement the adapter as you'll have to directly extend the &lt;a href="http://developer.android.com/reference/android/support/v4/view/PagerAdapter.html"&gt;PagerAdapter&lt;/a&gt; class.&lt;br /&gt;
&lt;br /&gt;
The following example creates an adapter that shows a number of different colored pages like the FragmentPagerAdapter implementation above.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;/div&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-mxaO0n1cYhQ/UIQNo43ZszI/AAAAAAAAFjw/FQ5bbhdhrMU/s1600/SamplePagerAdapter.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-mxaO0n1cYhQ/UIQNo43ZszI/AAAAAAAAFjw/FQ5bbhdhrMU/s1600/SamplePagerAdapter.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;a href="https://github.com/pocmo/Android-Zeitgeist-Samples/blob/master/ViewPager/01/SamplePagerAdapter.java"&gt;SamplePagerAdaper.java&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
As you can see you need to write some boilerplate code to add and remove the views to the pager. I published a simple&amp;nbsp;&lt;a href="https://gist.github.com/3927202"&gt;ViewPagerAdapter&lt;/a&gt; class on GitHub that does all this for you so that you don't need to write much more code than when using fragments:&lt;br /&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-RG1Pybe0Qko/UIQNEZ0emlI/AAAAAAAAFjo/wiW86E8k3lY/s1600/SamplePagerAdapter2.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-RG1Pybe0Qko/UIQNEZ0emlI/AAAAAAAAFjo/wiW86E8k3lY/s1600/SamplePagerAdapter2.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;a href="https://github.com/pocmo/Android-Zeitgeist-Samples/blob/master/ViewPager/01/SamplePagerAdapter2.java"&gt;SamplePagerAdapter2.java&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;&lt;img src="http://feeds.feedburner.com/~r/AndroidZeitgeist/~4/Xd7oNSltXJE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.androidzeitgeist.com/feeds/1618586447717593615/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.androidzeitgeist.com/2012/10/examining-viewpager-14.html#comment-form" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1531829516427013333/posts/default/1618586447717593615?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1531829516427013333/posts/default/1618586447717593615?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/AndroidZeitgeist/~3/Xd7oNSltXJE/examining-viewpager-14.html" title="Examining the ViewPager #1" /><author><name>Sebastian Kaspari</name><uri>https://plus.google.com/112283223674539938062</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-20YfT7gfh08/AAAAAAAAAAI/AAAAAAAALWI/LZ-ps7enWlI/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://img.youtube.com/vi/tcnGyRc9t0M/default.jpg" height="72" width="72" /><thr:total>4</thr:total><gd:extendedProperty name="commentSource" value="1" /><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD" /><feedburner:origLink>http://www.androidzeitgeist.com/2012/10/examining-viewpager-14.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0IBRHg_fyp7ImA9WhNSFk4.&quot;"><id>tag:blogger.com,1999:blog-1531829516427013333.post-2935160722418880762</id><published>2012-10-18T19:28:00.003+02:00</published><updated>2012-10-30T23:19:15.647+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-10-30T23:19:15.647+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="CameraFragment" /><category scheme="http://www.blogger.com/atom/ns#" term="camera" /><category scheme="http://www.blogger.com/atom/ns#" term="SurfaceView" /><category scheme="http://www.blogger.com/atom/ns#" term="Instant Mustache" /><title>Displaying the camera preview - Instant Mustache #5</title><content type="html">&lt;span style="font-size: x-small;"&gt;This article is part of a series of articles about the development process of Instant Mustache, a fun camera app that adds mustaches to all faces using face detection.&amp;nbsp;&lt;/span&gt;&lt;a href="http://www.androidzeitgeist.com/p/instant-mustache.html" style="font-size: small;"&gt;Click here&lt;/a&gt;&lt;span style="font-size: x-small;"&gt;&amp;nbsp;to get a chronological list of all published&amp;nbsp;&lt;/span&gt;&lt;a href="http://www.androidzeitgeist.com/p/instant-mustache.html" style="font-size: small;"&gt;articles about Instant Mustache&lt;/a&gt;&lt;span style="font-size: x-small;"&gt;.&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
From &lt;a href="http://www.androidzeitgeist.com/2012/10/using-fragment-for-camera-preview.html"&gt;the last article&lt;/a&gt; we already have three components: A &lt;a href="https://github.com/pocmo/Instant-Mustache/blob/article-04/src/com/androidzeitgeist/mustache/activity/CameraActivity.java"&gt;CameraActivity&lt;/a&gt; with not much code, an empty &lt;a href="https://github.com/pocmo/Instant-Mustache/blob/article-04/src/com/androidzeitgeist/mustache/fragment/CameraFragment.java"&gt;CameraFragment&lt;/a&gt; and a &lt;a href="https://github.com/pocmo/Instant-Mustache/blob/article-04/src/com/androidzeitgeist/mustache/listener/CameraFragmentListener.java"&gt;CameraFragmentListener&lt;/a&gt; interface for the communication between fragment and activity. Now we need to write the actual CameraFragment code to display the camera preview.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;The CameraPreview component&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
For displaying the preview we need an instance of &lt;a href="http://developer.android.com/reference/android/view/SurfaceView.html"&gt;SurfaceView&lt;/a&gt; to draw the actual camera picture on. We'll extend the SurfaceView to create our own view component called &lt;a href="https://github.com/pocmo/Instant-Mustache/blob/article-05/src/com/androidzeitgeist/mustache/view/CameraPreview.java"&gt;CameraPreview&lt;/a&gt;.&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;a href="http://www.androidzeitgeist.com/2012/08/lets-start-coding-not-instant-mustache-3.html"&gt;In the first articles&lt;/a&gt; we decided to use a square ratio for the preview. After some testing around it seems the emulator is the only "device" that supports a square sized camera preview and picture size out of the box. To work around this issue we would need to use a widely supported ratio (4:3) and crop the preview picture as well as the taken photo ourselves. To keep the code and the first version of the app small (and to follow the &lt;a href="http://www.androidzeitgeist.com/2012/07/minimal-marketable-app-instant-mustache.html"&gt;Minimal Marketable App&lt;/a&gt; principle) I decided to change this requirement. We will use the commonly supported ratio of 4:3.&lt;br /&gt;
&lt;br /&gt;
We implement onMeasure() to set the dimension of the view to a 4:3 ratio:&lt;br /&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-NJ3UtjTFli4/UIA4oX9FTuI/AAAAAAAAFhg/AMivOOGn94Y/s1600/onmeasure.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-NJ3UtjTFli4/UIA4oX9FTuI/AAAAAAAAFhg/AMivOOGn94Y/s1600/onmeasure.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;a href="https://github.com/pocmo/Instant-Mustache/blob/article-05/src/com/androidzeitgeist/mustache/view/CameraPreview.java#L32"&gt;onMeasure() - CameraPreview.java&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style="font-size: large;"&gt;Setting up the camera&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Even though we know our desired ratio we can't just set a size via &lt;a href="http://developer.android.com/reference/android/hardware/Camera.html#setParameters(android.hardware.Camera.Parameters)"&gt;camera.setParameters(Camera.Parameters)&lt;/a&gt;. Instead we have to query the &lt;a href="http://developer.android.com/reference/android/hardware/Camera.Parameters.html"&gt;Camera.Parameters&lt;/a&gt; object we get from getParameters() to retrieve a list of supported preview and picture sizes. Then we have to scan this list for a size that has our desired ratio. This is what determineBestSize() does:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-9EpZpQQQk_g/UH2o5PQn4kI/AAAAAAAAFgk/Ip5ecGrvDSU/s1600/determine_size.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-9EpZpQQQk_g/UH2o5PQn4kI/AAAAAAAAFgk/Ip5ecGrvDSU/s1600/determine_size.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;a href="https://github.com/pocmo/Instant-Mustache/blob/article-05/src/com/androidzeitgeist/mustache/fragment/CameraFragment.java#L190"&gt;determineBestSize() - CameraFragment.java&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
We are using a threshold for the preview and picture size to save some heap space for the bitmap transformations we'll do later. For now these limits are 640x480 for the preview size and 1280x960 for the &amp;nbsp;picture size.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
Finally the determined values are used to setup the camera object:&lt;br /&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-aeWvWYDnT2s/UH2uJVZkAFI/AAAAAAAAFg4/puouCbK7VOQ/s1600/setup_camera.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-aeWvWYDnT2s/UH2uJVZkAFI/AAAAAAAAFg4/puouCbK7VOQ/s1600/setup_camera.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;a href="https://github.com/pocmo/Instant-Mustache/blob/article-05/src/com/androidzeitgeist/mustache/fragment/CameraFragment.java#L166"&gt;setupCamera() - CameraFragment.java&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
The CameraPreview component will be used as view of our CameraFragment by returning it in &lt;a href="http://developer.android.com/reference/android/app/Fragment.html#onCreateView(android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle)"&gt;onCreateView()&lt;/a&gt;. In addition to that our CameraFragment needs to implement &lt;a href="http://developer.android.com/reference/android/view/SurfaceHolder.Callback.html"&gt;SurfaceHolder.Callback&lt;/a&gt; in order to get notified when the surface is created or destroyed.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;&lt;span style="font-size: large;"&gt;Accessing the camera&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
To access the camera of the device we need to call &lt;a href="http://developer.android.com/reference/android/hardware/Camera.html#open(int)"&gt;Camera.open(int cameraId)&lt;/a&gt; to obtain a &lt;a href="http://developer.android.com/reference/android/hardware/Camera.html"&gt;Camera&lt;/a&gt; object. The camera ids are numbered starting with 0. As we currently don't want to support multiple cameras we will just call Camera.open(0).&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Unfortunately using the camera can cause undefined exceptions to be thrown. Therefore we need to wrap some code accessing the camera object into try-catch blocks and catch the generic Exception object. This is usually &lt;a href="http://source.android.com/source/code-style.html#dont-catch-generic-exception"&gt;considered bad practice&lt;/a&gt; but in this case &lt;a href="http://developer.android.com/guide/topics/media/camera.html#access-camera"&gt;encouraged to do by the documentation&lt;/a&gt;.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;Sharing the camera resource&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
The camera can only be used by one application at a time so we need to release the camera every time the activity gets paused. Otherwise the user would not be able to use other camera applications while our activity is in the background. In some cases not releasing the camera can lead to the CameraService crashing. If this happens no camera application can be used until the user reboots his phone. We never want this to happen.&lt;br /&gt;
&lt;br /&gt;
To be safe we will open the camera by calling Camera.open() in the &lt;a href="https://github.com/pocmo/Instant-Mustache/blob/article-05/src/com/androidzeitgeist/mustache/fragment/CameraFragment.java#L70"&gt;onResume()&lt;/a&gt; method of the CameraFragment and releasing it again in &lt;a href="https://github.com/pocmo/Instant-Mustache/blob/article-05/src/com/androidzeitgeist/mustache/fragment/CameraFragment.java#L87"&gt;onPause()&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Once we have a Camera object and our surface is created we can assign the surface to the camera object and start the preview. We wrap the call to startPreview() in our own method called &lt;a href="https://github.com/pocmo/Instant-Mustache/blob/article-05/src/com/androidzeitgeist/mustache/fragment/CameraFragment.java#L97"&gt;startCameraPreview()&lt;/a&gt; inside our fragment. This way we can setup the camera object before actually starting the preview.&lt;br /&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-KFpfQOjQJY4/UIA567dmV6I/AAAAAAAAFho/fv7wu7wsUYg/s1600/startpreview.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-KFpfQOjQJY4/UIA567dmV6I/AAAAAAAAFho/fv7wu7wsUYg/s1600/startpreview.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;a href="https://github.com/pocmo/Instant-Mustache/blob/article-05/src/com/androidzeitgeist/mustache/fragment/CameraFragment.java#L97"&gt;startCameraPreview() - CameraFragment.java&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;Determining the display orientation&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
The screen can be rotated in four different angles (0°, 90°, 180°, 270°). In addition to that the camera can also be built into the device in four different angles by the manufacturer. Finally the camera can be on the front or on the back of the device. We will need to get all these angles and tell the camera object the display orientation so that the preview will be drawn on the surface using the right rotation.&lt;br /&gt;
&lt;br /&gt;
This sounds tricky but fortunately there's a &lt;a href="http://developer.android.com/reference/android/hardware/Camera.html#setDisplayOrientation(int)"&gt;code snippet for that in the Android documentation&lt;/a&gt;. We'll use &lt;a href="http://developer.android.com/reference/android/hardware/Camera.html#setDisplayOrientation(int)"&gt;this code snippet&lt;/a&gt; to implement &lt;a href="https://github.com/pocmo/Instant-Mustache/blob/article-05/src/com/androidzeitgeist/mustache/fragment/CameraFragment.java#L126"&gt;determineDisplayOrientation()&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style="font-size: large;"&gt;Screenshot&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
And that's how our app looks like so far:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-YuVQvTJ3OU0/UIA00sECLRI/AAAAAAAAFhM/R8mHYZhRnIE/s1600/mustache_screen.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-YuVQvTJ3OU0/UIA00sECLRI/AAAAAAAAFhM/R8mHYZhRnIE/s1600/mustache_screen.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
As always the&amp;nbsp;&lt;a href="https://github.com/pocmo/Instant-Mustache/tree/article-05"&gt;source code&amp;nbsp;of the current version&lt;/a&gt; of the app is available at Github.&lt;/div&gt;
&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/AndroidZeitgeist/~4/C01oUsX3kSI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.androidzeitgeist.com/feeds/2935160722418880762/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.androidzeitgeist.com/2012/10/displaying-camera-preview-instant.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1531829516427013333/posts/default/2935160722418880762?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1531829516427013333/posts/default/2935160722418880762?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/AndroidZeitgeist/~3/C01oUsX3kSI/displaying-camera-preview-instant.html" title="Displaying the camera preview - Instant Mustache #5" /><author><name>Sebastian Kaspari</name><uri>https://plus.google.com/112283223674539938062</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-20YfT7gfh08/AAAAAAAAAAI/AAAAAAAALWI/LZ-ps7enWlI/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-NJ3UtjTFli4/UIA4oX9FTuI/AAAAAAAAFhg/AMivOOGn94Y/s72-c/onmeasure.png" height="72" width="72" /><thr:total>1</thr:total><gd:extendedProperty name="commentSource" value="1" /><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD" /><feedburner:origLink>http://www.androidzeitgeist.com/2012/10/displaying-camera-preview-instant.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0IDRHg9eyp7ImA9WhNSFk4.&quot;"><id>tag:blogger.com,1999:blog-1531829516427013333.post-7757019473292818494</id><published>2012-10-15T19:28:00.002+02:00</published><updated>2012-10-30T23:19:35.663+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-10-30T23:19:35.663+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Instant Mustache" /><category scheme="http://www.blogger.com/atom/ns#" term="Fragment" /><title>Using a fragment for the camera preview - Instant Mustache #4</title><content type="html">&lt;span style="font-size: x-small;"&gt;This article is part of a series of articles about the development process of Instant Mustache, a fun camera app that adds mustaches to all faces using face detection.&amp;nbsp;&lt;/span&gt;&lt;a href="http://www.androidzeitgeist.com/p/instant-mustache.html" style="font-size: small;"&gt;Click here&lt;/a&gt;&lt;span style="font-size: x-small;"&gt;&amp;nbsp;to get a chronological list of all published&amp;nbsp;&lt;/span&gt;&lt;a href="http://www.androidzeitgeist.com/p/instant-mustache.html" style="font-size: small;"&gt;articles about Instant Mustache&lt;/a&gt;&lt;span style="font-size: x-small;"&gt;.&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
This article will be the first one about writing the CameraActivity for &lt;a href="http://www.androidzeitgeist.com/p/instant-mustache.html"&gt;Instant Mustache&lt;/a&gt;. From &lt;a href="http://www.androidzeitgeist.com/2012/08/lets-start-coding-not-instant-mustache-3.html"&gt;the last article&lt;/a&gt; we already know how the layout of the activity should look like. Now it's time to start the coding part.&lt;br /&gt;
&lt;br /&gt;
I won't cover all the lines of code in this and the following blog articles but you can always get the complete &lt;a href="https://github.com/pocmo/Instant-Mustache"&gt;source code of Instant Mustache at GitHub&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Using a fragment&lt;/b&gt;&lt;br /&gt;
We'll move the actual code (and layout) that handles the camera preview to a &lt;a href="http://developer.android.com/guide/components/fragments.html"&gt;fragment&lt;/a&gt;. Using fragments has several advantages:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Fragments can be reused in different activities and layouts. Therefore they are perfect building blocks for composing UIs for different screen sizes.&lt;/li&gt;
&lt;li&gt;They encapsulate the code for a specific component including the layout of the component. This makes the activity code and layout much more simpler and cleaner. By using a bunch of fragments the activity basically only has to handle events and delegate them to the appropriate fragments. This leads to the activity becoming some kind of light meta controller instead of an unreadable dumping ground for handling everything on the current screen.&lt;/li&gt;
&lt;li&gt;Fragments can be dynamically added, removed, replaced, added to the back stack, animated and other cool things that can be painful to do yourself.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;b&gt;&lt;br /&gt;Activity layout&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div style="margin-bottom: 0in;"&gt;
As said before we are moving the camera
preview code and layout to a fragment. Therefore our activity's
layout is really quite simple:&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="margin-bottom: 0in;"&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;span style="margin-left: auto; margin-right: auto;"&gt;&lt;a href="http://www.blogger.com/goog_154278281"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-9A5F03FauP0/UHxDx3aMDcI/AAAAAAAAFfE/x245XxDRKJk/s1600/camera_activity_layout_2.png" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;a href="https://github.com/pocmo/Instant-Mustache/blob/article-04/res/layout/activity_camera.xml"&gt;activity_camera.xml&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="margin-bottom: 0in;"&gt;
&lt;b&gt;Communication between activity and fragment&lt;/b&gt;&lt;/div&gt;
&lt;div style="margin-bottom: 0in;"&gt;
&lt;/div&gt;
&lt;div style="margin-bottom: 0in;"&gt;
There are situations where the fragment
needs to notify the activity about events. In our case the fragment
needs to tell the activity when it's unable to instantiate a camera
preview so that the activity can handle this error case. Of course we
could just access the activity inside the fragment using
&lt;a href="http://developer.android.com/reference/android/app/Fragment.html#getActivity()"&gt;getActivity()&lt;/a&gt; and cast it to a CameraActivity object to get access to
a method like onCameraError() but then our fragment would only be
usable with this particular activity:&lt;/div&gt;
&lt;div style="margin-bottom: 0in;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="margin-bottom: 0in;"&gt;
&lt;/div&gt;
&lt;div style="margin-bottom: 0in;"&gt;
&lt;span style="color: #444444; font-family: Courier New, Courier, monospace;"&gt;CameraActivity activity = (CameraActivity) getActivity();&lt;/span&gt;&lt;/div&gt;
&lt;div style="margin-bottom: 0in;"&gt;
&lt;span style="color: #444444; font-family: Courier New, Courier, monospace;"&gt;activity.onCameraError();&lt;/span&gt;&lt;/div&gt;
&lt;div style="margin-bottom: 0in;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="margin-bottom: 0in;"&gt;
&lt;/div&gt;
&lt;div style="margin-bottom: 0in;"&gt;
We work around this issue by defining
an interface that has to be implemented by the CameraActivity and every
other component that wants to use the CameraFragment:&lt;/div&gt;
&lt;div style="margin-bottom: 0in;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/--DMu6Y45ciU/UHxBNXetSII/AAAAAAAAFe0/YrGtXiPkUXE/s1600/fragment_listener.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;span style="color: black;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/--DMu6Y45ciU/UHxBNXetSII/AAAAAAAAFe0/YrGtXiPkUXE/s1600/fragment_listener.png" /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;a href="https://github.com/pocmo/Instant-Mustache/blob/article-04/src/com/androidzeitgeist/mustache/listener/CameraFragmentListener.java"&gt;&lt;span style="color: black; font-size: small;"&gt;CameraFragmentListener.java&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
Every time our fragment gets attached to an activity &lt;a href="http://developer.android.com/reference/android/app/Fragment.html#onAttach(android.app.Activity)"&gt;onAttach()&lt;/a&gt; will be called with the activity as parameter. We use this method to enforce that the activity implements our defined interface:&lt;br /&gt;
&lt;div style="margin-bottom: 0in;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;span style="margin-left: auto; margin-right: auto;"&gt;&lt;a href="http://www.blogger.com/goog_154278245"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-hGixG23tyHc/UHxBneeyqOI/AAAAAAAAFe8/VF7FmuzO8Jk/s1600/fragment_on_attach.png" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;a href="https://github.com/pocmo/Instant-Mustache/blob/article-04/src/com/androidzeitgeist/mustache/fragment/CameraFragment.java"&gt;CameraFragment.java&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div style="margin-bottom: 0in;"&gt;
&lt;/div&gt;
&lt;div style="margin-bottom: 0in;"&gt;
Finally take
a look at the &lt;a href="https://github.com/pocmo/Instant-Mustache/blob/article-04/src/com/androidzeitgeist/mustache/activity/CameraActivity.java"&gt;CameraActivity source code on GitHub&lt;/a&gt;. It just sets the
layout in onCreate() and shows a &lt;a href="http://developer.android.com/guide/topics/ui/notifiers/toasts.html"&gt;toast&lt;/a&gt; in case of the fragment
calling onCameraError(). As this method will be called in case of
non-recoverable errors we'll also finish the activity.&lt;/div&gt;
&lt;/div&gt;
&lt;br /&gt;&lt;img src="http://feeds.feedburner.com/~r/AndroidZeitgeist/~4/BCc8E5OcNig" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.androidzeitgeist.com/feeds/7757019473292818494/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.androidzeitgeist.com/2012/10/using-fragment-for-camera-preview.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1531829516427013333/posts/default/7757019473292818494?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1531829516427013333/posts/default/7757019473292818494?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/AndroidZeitgeist/~3/BCc8E5OcNig/using-fragment-for-camera-preview.html" title="Using a fragment for the camera preview - Instant Mustache #4" /><author><name>Sebastian Kaspari</name><uri>https://plus.google.com/112283223674539938062</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-20YfT7gfh08/AAAAAAAAAAI/AAAAAAAALWI/LZ-ps7enWlI/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-9A5F03FauP0/UHxDx3aMDcI/AAAAAAAAFfE/x245XxDRKJk/s72-c/camera_activity_layout_2.png" height="72" width="72" /><thr:total>2</thr:total><gd:extendedProperty name="commentSource" value="1" /><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD" /><feedburner:origLink>http://www.androidzeitgeist.com/2012/10/using-fragment-for-camera-preview.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0INQHkzcSp7ImA9WhNSFk4.&quot;"><id>tag:blogger.com,1999:blog-1531829516427013333.post-8978580997544983984</id><published>2012-08-20T19:02:00.001+02:00</published><updated>2012-10-30T23:19:51.789+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-10-30T23:19:51.789+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Boolean" /><category scheme="http://www.blogger.com/atom/ns#" term="Resources" /><category scheme="http://www.blogger.com/atom/ns#" term="Integer" /><title>Know your resources: Integers and Booleans</title><content type="html">An Android application isn't only code but comes with a bunch of &lt;a href="http://developer.android.com/guide/topics/resources/index.html"&gt;resources&lt;/a&gt;. Probably the most important resources (besides layouts and drawables) are the string resources. In conjunction with the &lt;a href="http://developer.android.com/guide/topics/resources/providing-resources.html#AlternativeResources"&gt;resource qualifiers&lt;/a&gt; they are not only perfect to externalize strings for localization but also for defining different internal configurations of your app.&lt;br /&gt;
&lt;br /&gt;
However sometimes string resources are overused. Especially when they are used to define boolean or integer values. Let's look at the following example. Code lines like the next ones can be found in several Android projects. For example you can find &lt;a href="https://github.com/pocmo/Yaaic/blob/master/application/src/org/yaaic/model/Settings.java#L74"&gt;some of these in Yaaic&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;/div&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-XLbaLF9yRos/UDJrT8HzfaI/AAAAAAAAFMk/6_ctbD-1rQ8/s1600/resources_example01.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-XLbaLF9yRos/UDJrT8HzfaI/AAAAAAAAFMk/6_ctbD-1rQ8/s1600/resources_example01.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Loading string resources and parsing as boolean or integer&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
Or even worse in a condition without casting, doing a string comparison:&lt;br /&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-IfOUvr3e9og/UDJrri2Gu3I/AAAAAAAAFMs/qB5wMlRTBzI/s1600/resources_example02.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-IfOUvr3e9og/UDJrri2Gu3I/AAAAAAAAFMs/qB5wMlRTBzI/s1600/resources_example02.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Loading boolean as string resource and doing string comparison&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
The code above is not wrong but instead of using string resources and parsing or comparing them it would be easier to use resources of the appropriate type. Fortunately Android allows to&amp;nbsp;define &lt;a href="http://developer.android.com/guide/topics/resources/more-resources.html#Bool"&gt;boolean&lt;/a&gt; and &lt;a href="http://developer.android.com/guide/topics/resources/more-resources.html#Integer"&gt;integer&lt;/a&gt; resources too (since API level 1). It's basically the same process as defining a string resource in XML just use the bool and integer tags:&lt;br /&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-BIkUDBXNXFU/UDJr4uQMhTI/AAAAAAAAFM0/39d0Vj3jIKo/s1600/xml_resources.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-BIkUDBXNXFU/UDJr4uQMhTI/AAAAAAAAFM0/39d0Vj3jIKo/s1600/xml_resources.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Defining boolean and integer resources in XML&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
After that you can access these resources in code. However there are no &lt;a href="http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.1.1_r1/android/content/Context.java#304"&gt;alias methods&lt;/a&gt; on the &lt;a href="http://developer.android.com/reference/android/content/Context.html"&gt;Context&lt;/a&gt; object like for string resources. Therefore you need to get a &lt;a href="http://developer.android.com/reference/android/content/res/Resources.html"&gt;Resources&lt;/a&gt; instance first and then ask it for the defined resources.&lt;br /&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-bLP5ceuA0xY/UDOhAxoQunI/AAAAAAAAFNM/ONwuHscnEDw/s1600/accessing_resources.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-bLP5ceuA0xY/UDOhAxoQunI/AAAAAAAAFNM/ONwuHscnEDw/s1600/accessing_resources.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Accessing integer and boolean resources from code&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;img src="http://feeds.feedburner.com/~r/AndroidZeitgeist/~4/SH5Bn82Meao" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.androidzeitgeist.com/feeds/8978580997544983984/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.androidzeitgeist.com/2012/08/know-your-resources-integers-and.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1531829516427013333/posts/default/8978580997544983984?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1531829516427013333/posts/default/8978580997544983984?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/AndroidZeitgeist/~3/SH5Bn82Meao/know-your-resources-integers-and.html" title="Know your resources: Integers and Booleans" /><author><name>Sebastian Kaspari</name><uri>https://plus.google.com/112283223674539938062</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-20YfT7gfh08/AAAAAAAAAAI/AAAAAAAALWI/LZ-ps7enWlI/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-XLbaLF9yRos/UDJrT8HzfaI/AAAAAAAAFMk/6_ctbD-1rQ8/s72-c/resources_example01.png" height="72" width="72" /><thr:total>1</thr:total><gd:extendedProperty name="commentSource" value="1" /><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD" /><feedburner:origLink>http://www.androidzeitgeist.com/2012/08/know-your-resources-integers-and.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0EBQHgyfSp7ImA9WhNSFk4.&quot;"><id>tag:blogger.com,1999:blog-1531829516427013333.post-7567694303001801787</id><published>2012-08-01T21:01:00.002+02:00</published><updated>2012-10-30T23:20:51.695+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-10-30T23:20:51.695+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Instant Mustache" /><category scheme="http://www.blogger.com/atom/ns#" term="sketch" /><category scheme="http://www.blogger.com/atom/ns#" term="mockup" /><category scheme="http://www.blogger.com/atom/ns#" term="UI" /><title>Let's start coding ... NOT! - Instant Mustache #3</title><content type="html">&lt;span style="font-size: x-small;"&gt;This article is part of a series of articles about the development process of Instant Mustache, a fun camera app that adds mustaches to all faces using face detection.&amp;nbsp;&lt;/span&gt;&lt;a href="http://www.androidzeitgeist.com/p/instant-mustache.html" style="font-size: small;"&gt;Click here&lt;/a&gt;&lt;span style="font-size: x-small;"&gt;&amp;nbsp;to get a chronological list of all published&amp;nbsp;&lt;/span&gt;&lt;a href="http://www.androidzeitgeist.com/p/instant-mustache.html" style="font-size: small;"&gt;articles about Instant Mustache&lt;/a&gt;&lt;span style="font-size: x-small;"&gt;.&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
In the &lt;a href="http://www.androidzeitgeist.com/p/instant-mustache.html"&gt;last two articles&lt;/a&gt; about Instant Mustache we've talked a lot and it's about time to start coding! Yet I’ve to disappoint you for now. There still will be no code in this article. Before we’ll start coding we’ve to define what we actually need or want. From the last article we already know there will be two screens. But what we don’t know yet is how they should look like. So how will we figure out how the (very simple) UI will look like? Of course we can fire up our code editor or visual editor but there’s a much faster way to get results: Good old paper.&lt;br /&gt;
&lt;br /&gt;
I won’t talk about paper prototypes or UI development and user testing here. But there’s a better resource for that. The &lt;a href="http://www.androiduipatterns.com/"&gt;Android UI Patterns blog&lt;/a&gt; has a lot of articles published covering a variety of Android UI topics. Here we are going to just sketch some screens, play around and hopefully come up with an idea of how the app will feel like when it’s finally developed. As said before I'll use paper for that. Other people may like to use software for creating mockups (&lt;a href="http://www.fluidui.com/"&gt;Fluid UI&lt;/a&gt; seems to be a nice online tool for that). It's up to you what works the best for you. For me paper is the easiest way to try different ideas without the limitations of a software tool. But the important thing is: We won't write a lot of code that we need to throw away again after we realize that our initial idea may not be as good as we thought.&lt;br /&gt;
&lt;br /&gt;
The following photo shows a bunch of discarded drawings I came up with during brainstorming the UI:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-vLyg3OA870M/UBlqUI8HXhI/AAAAAAAAEeA/E3oDqTCMi9o/s1600/screens.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="176" src="http://2.bp.blogspot.com/-vLyg3OA870M/UBlqUI8HXhI/AAAAAAAAEeA/E3oDqTCMi9o/s400/screens.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;/div&gt;
&lt;b&gt;The camera screen (CameraActivity)&lt;/b&gt;&lt;br /&gt;
The first screen the user will see after launching the app will be the camera screen. There are two main components we need: A camera preview and a button to take a photo. In addition to that we may want to reserve some space for future features like switching between cameras and mustaches.&lt;br /&gt;
&lt;br /&gt;
Let's take a look at the the final version of the camera screen as I've drawn it:&lt;br /&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-ACfaRYTWXiQ/UBlrUkZlmPI/AAAAAAAAEe4/c5nw7R2I3EM/s1600/final_camera_activity.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-ACfaRYTWXiQ/UBlrUkZlmPI/AAAAAAAAEe4/c5nw7R2I3EM/s1600/final_camera_activity.jpg" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;CameraActivity&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
The following decisions I've made during drawing and experimenting:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;I want the app to have an &lt;a href="http://developer.android.com/design/patterns/actionbar.html"&gt;ActionBar&lt;/a&gt;. To be consistent I also want the ActionBar in the camera screen. I don't know yet if it's useful to show the app title "Instant Mustache" in the ActionBar as I've drawn it. It's quite long and may take up too much space. Furthermore the overflow menu drawn here may not be visible as we have no menu entries defined yet.&lt;/li&gt;
&lt;li&gt;The camera picture will be a square. We'll have to define a picture ratio and a square may fit quite nice into the screen. The darker areas on the screen will grow or shrink depending on the screen size of the device and always center the camera preview.&lt;/li&gt;
&lt;li&gt;There will be a bar at the bottom of the screen which will house the button for taking a picture. Here we will have enough space for adding more functionality in later releases.&lt;/li&gt;
&lt;li&gt;Almost all activities showing a camera preview are fixed in their orientation. While moving the phone around to take a photo you don't want the phone to destroy the current activity, do the rotation and re-create the activity. Especially because the camera picture will be oriented correctly anyways because you are rotating the camera inside the phone as well. To satisfy the previous points we will fixate the orientation to portrait mode.&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;b&gt;The photo screen (PhotoActivity)&lt;/b&gt;&lt;br /&gt;
After taking a photo you will see another screen showing the photo you've taken and you'll have the option to share the photo with other apps on your phone.&lt;br /&gt;
&lt;br /&gt;
That's how my final version of the photo screen looks like:&lt;br /&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-ZkXDFTYoBTs/UBlv6nT4mRI/AAAAAAAAEfI/RGFW1HHcngE/s1600/final_share_activity.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-ZkXDFTYoBTs/UBlv6nT4mRI/AAAAAAAAEfI/RGFW1HHcngE/s1600/final_share_activity.jpg" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;PhotoActivtiy&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
The first version of this screen will be really simple:&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;At the top we'll have the ActionBar again. To share the photo we'll add a &lt;a href="http://developer.android.com/guide/topics/ui/actionbar.html#ActionProvider"&gt;ShareActionProvider&lt;/a&gt; that shows a list of available share targets as well as the most used app as an icon right beside it.&lt;/li&gt;
&lt;li&gt;Below the ActionBar we'll show the taken photo and that's everything for now.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;b&gt;What's next?&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;
Now we've defined how our two screens will look like. In the next article we are going to launch our IDE and start writing the CameraActivity. I am curious to know what you think about the UI as described here and if you have other ideas. Let me know in the comments or on Google+.&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/AndroidZeitgeist/~4/xRHDRu4wROY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.androidzeitgeist.com/feeds/7567694303001801787/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.androidzeitgeist.com/2012/08/lets-start-coding-not-instant-mustache-3.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1531829516427013333/posts/default/7567694303001801787?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1531829516427013333/posts/default/7567694303001801787?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/AndroidZeitgeist/~3/xRHDRu4wROY/lets-start-coding-not-instant-mustache-3.html" title="Let's start coding ... NOT! - Instant Mustache #3" /><author><name>Sebastian Kaspari</name><uri>https://plus.google.com/112283223674539938062</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-20YfT7gfh08/AAAAAAAAAAI/AAAAAAAALWI/LZ-ps7enWlI/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-vLyg3OA870M/UBlqUI8HXhI/AAAAAAAAEeA/E3oDqTCMi9o/s72-c/screens.png" height="72" width="72" /><thr:total>2</thr:total><gd:extendedProperty name="commentSource" value="1" /><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD" /><feedburner:origLink>http://www.androidzeitgeist.com/2012/08/lets-start-coding-not-instant-mustache-3.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0EDQ307eCp7ImA9WhNSFk4.&quot;"><id>tag:blogger.com,1999:blog-1531829516427013333.post-2631040260680088231</id><published>2012-07-03T20:08:00.003+02:00</published><updated>2012-10-30T23:21:12.300+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-10-30T23:21:12.300+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="roadmap" /><category scheme="http://www.blogger.com/atom/ns#" term="Instant Mustache" /><category scheme="http://www.blogger.com/atom/ns#" term="Minimal marketable app" /><title>Minimal marketable app - Instant Mustache #2</title><content type="html">&lt;span style="font-size: x-small;"&gt;This article is part of a series of articles about the development process of Instant Mustache, a fun camera app that adds mustaches to all faces using face detection.&amp;nbsp;&lt;/span&gt;&lt;a href="http://www.androidzeitgeist.com/p/instant-mustache.html" style="font-size: small;"&gt;Click here&lt;/a&gt;&lt;span style="font-size: x-small;"&gt;&amp;nbsp;to get a chronological list of all published&amp;nbsp;&lt;/span&gt;&lt;a href="http://www.androidzeitgeist.com/p/instant-mustache.html" style="font-size: small;"&gt;articles about Instant Mustache&lt;/a&gt;&lt;span style="font-size: x-small;"&gt;.&lt;/span&gt;&lt;br /&gt;
&lt;b&gt;&lt;span style="font-family: Arial; font-size: 15px; font-weight: normal; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/b&gt;
&lt;b id="internal-source-marker_0.039026354206725955"&gt;&lt;span style="font-family: Arial; font-size: 15px; font-weight: normal; vertical-align: baseline; white-space: pre-wrap;"&gt;In &lt;a href="http://www.androidzeitgeist.com/2012/06/instant-mustache-1-idea.html"&gt;the last article&lt;/a&gt; I described roughly the idea behind Instant Mustache. Now it's time to get more concrete. While doing so we try to follow the principle of the minimal marketable feature (MMF).&lt;/span&gt;&lt;/b&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style="font-family: Arial; font-size: 15px; vertical-align: baseline; white-space: pre-wrap;"&gt;Minimal marketable feature&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;span id="internal-source-marker_0.039026354206725955"&gt;&lt;span style="font-family: Arial; font-size: 15px; font-weight: normal; vertical-align: baseline; white-space: pre-wrap;"&gt;The idea behind the minimal marketable feature is to strip all aspects of a feature that are not necessarily needed to end up with a useful (or marketable) feature. After that you'll end up with smaller features that are easier and faster to develop. This is only a very rough explanation of MMF. You can find a way better &lt;a href="http://www.upstarthq.com/2010/04/introduction-to-minimum-marketable-features-mmf/"&gt;Introduction to Minimum marketable feature&lt;/a&gt; at the upstart blog.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b style="background-color: white; font-family: Arial; font-size: 15px; white-space: pre-wrap;"&gt;Minimal marketable app&lt;/b&gt;&lt;br /&gt;
&lt;span style="font-family: Arial; font-size: 15px; font-weight: normal; vertical-align: baseline; white-space: pre-wrap;"&gt;In this case we are slightly modifying this idea to end up with something like a &lt;/span&gt;&lt;span style="font-family: Arial; font-size: 15px; font-weight: bold; vertical-align: baseline; white-space: pre-wrap;"&gt;minimal marketable app&lt;/span&gt;&lt;span style="font-family: Arial; font-size: 15px; font-weight: normal; vertical-align: baseline; white-space: pre-wrap;"&gt;. This means we are going one level higher and strip all features that are not essentially required for a first releasable app. This does not mean that we won't develop these features at all but our first version will be without them enabling us to ship the app as early as possible.
&lt;/span&gt;&lt;br /&gt;
&lt;span style="background-color: white; font-family: Arial; font-size: 15px; white-space: pre-wrap;"&gt;Let's continue with an example. When you think about the app (&lt;a href="http://www.androidzeitgeist.com/2012/06/instant-mustache-1-idea.html"&gt;see first article&lt;/a&gt;) you will very fast come up with an idea like: The user should be able to select between a bunch of mustaches - more mustaches = more fun. But do we really need this feature when we launch the app? No, we don't. Our fun app will still be fun with one single mustache. Of course this is one of the first features we should have in the next release after the initial one.&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Arial; font-size: 15px; font-weight: normal; vertical-align: baseline; white-space: pre-wrap;"&gt;Another feature that's easy to come up with is switching between the cameras of a device. In most cases this means switching between back and front camera. Again for our basic app it's totally acceptable to strip this feature in the first release. The users of our app won't be able to take pictures of themselves easily and therefore they won't have much fun when there's no mustache-less friend to photograph around. Therefore we should rank this feature high as well to implement it right after the first release.&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Arial; font-size: 15px; font-weight: normal; vertical-align: baseline; white-space: pre-wrap;"&gt;In our case the minimal marketable feature set is an app that has two screens: A camera screen - with a camera preview and a button to take a picture - and a second screen that shows the picture you took and has an option to share this picture. The camera preview will show a live preview. Every detected face on the live preview will automatically have a mustache overlayed. If you take a picture the second screen will show the composed picture including the added mustaches. The user will be able to share the picture via the &lt;a href="http://android-developers.blogspot.co.uk/2012/02/share-with-intents.html"&gt;Android intent system&lt;/a&gt;.&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style="font-family: Arial; font-size: 15px; vertical-align: baseline; white-space: pre-wrap;"&gt;Roadmap and Milestones&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;b id="internal-source-marker_0.039026354206725955"&gt;&lt;span style="font-family: Arial; font-size: 15px; font-weight: normal; vertical-align: baseline; white-space: pre-wrap;"&gt;Nothing is more motivating than playing around with what you have created. In contrast nothing is more killing motivation than programming for ages without coming up with something that runs at all.&lt;/span&gt;&lt;span style="vertical-align: baseline;"&gt; &lt;/span&gt;&lt;span style="font-family: Arial; font-size: 15px; font-weight: normal; vertical-align: baseline; white-space: pre-wrap;"&gt;This leads us to the goal to always have a running prototype that step by step gets features added until it's ready to ship. So let's break the functionality into parts that can be implemented in order and always leave us with a working prototype that we can deploy on our phone and use at the next party.&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style="font-family: Arial;"&gt;&lt;span style="font-size: 15px; white-space: pre-wrap;"&gt;&lt;b&gt;Milestone #1&lt;/b&gt;: &lt;/span&gt;&lt;/span&gt;&lt;b id="internal-source-marker_0.039026354206725955"&gt;&lt;span style="font-family: Arial; font-size: 15px; font-weight: normal; vertical-align: baseline; white-space: pre-wrap;"&gt;A camera screen that shows the camera preview and has a button to take a photo. The photos will be saved on the SD card. After that we will end up with a basic camera app that we can use to take photos on the go. Goodbye native camera app!&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span style="font-family: Arial; font-size: 15px; vertical-align: baseline; white-space: pre-wrap;"&gt;Milestone #2&lt;/span&gt;&lt;span style="font-family: Arial; font-size: 15px; font-weight: normal; vertical-align: baseline; white-space: pre-wrap;"&gt;: &lt;/span&gt;&lt;/b&gt;&lt;b id="internal-source-marker_0.039026354206725955"&gt;&lt;span style="font-family: Arial; font-size: 15px; font-weight: normal; vertical-align: baseline; white-space: pre-wrap;"&gt;We add the second screen. After taking a photo we’ll switch to this second screen which shows the taken photo and has an option to share the photo.&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span style="font-family: Arial; font-size: 15px; vertical-align: baseline; white-space: pre-wrap;"&gt;Milestone #3&lt;/span&gt;&lt;span style="font-family: Arial; font-size: 15px; font-weight: normal; vertical-align: baseline; white-space: pre-wrap;"&gt;: &lt;/span&gt;&lt;/b&gt;&lt;b id="internal-source-marker_0.039026354206725955"&gt;&lt;span style="font-family: Arial; font-size: 15px; font-weight: normal; vertical-align: baseline; white-space: pre-wrap;"&gt;It’s time to add the face tracking. We’ll use the face tracking and display mustaches for every face on top of the camera preview.&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span style="font-family: Arial; font-size: 15px; vertical-align: baseline; white-space: pre-wrap;"&gt;Milestone #4&lt;/span&gt;&lt;span style="font-family: Arial; font-size: 15px; font-weight: normal; vertical-align: baseline; white-space: pre-wrap;"&gt;: &lt;/span&gt;&lt;/b&gt;&lt;b id="internal-source-marker_0.039026354206725955"&gt;&lt;span style="font-family: Arial; font-size: 15px; font-weight: normal; vertical-align: baseline; white-space: pre-wrap;"&gt;When taking a photo we’ll compose the final photo using the information of the face tracking. The composed photo will contain mustaches like the preview screen before. The composed photo will be saved on the SD card and shown in the second screen. We are ready to release!&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;img src="http://feeds.feedburner.com/~r/AndroidZeitgeist/~4/D7VVl5yQcUE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.androidzeitgeist.com/feeds/2631040260680088231/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.androidzeitgeist.com/2012/07/minimal-marketable-app-instant-mustache.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1531829516427013333/posts/default/2631040260680088231?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1531829516427013333/posts/default/2631040260680088231?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/AndroidZeitgeist/~3/D7VVl5yQcUE/minimal-marketable-app-instant-mustache.html" title="Minimal marketable app - Instant Mustache #2" /><author><name>Sebastian Kaspari</name><uri>https://plus.google.com/112283223674539938062</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-20YfT7gfh08/AAAAAAAAAAI/AAAAAAAALWI/LZ-ps7enWlI/s512-c/photo.jpg" /></author><thr:total>2</thr:total><gd:extendedProperty name="commentSource" value="1" /><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD" /><feedburner:origLink>http://www.androidzeitgeist.com/2012/07/minimal-marketable-app-instant-mustache.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0ENQX88eyp7ImA9WhNSFk4.&quot;"><id>tag:blogger.com,1999:blog-1531829516427013333.post-2571392770508842451</id><published>2012-06-08T12:14:00.002+02:00</published><updated>2012-10-30T23:21:30.173+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-10-30T23:21:30.173+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="BlinkLayout" /><category scheme="http://www.blogger.com/atom/ns#" term="Animation" /><category scheme="http://www.blogger.com/atom/ns#" term="ViewGroup" /><category scheme="http://www.blogger.com/atom/ns#" term="Layout" /><title>Creating a MarqueeLayout with the Android Animation System</title><content type="html">When I posted the article about &lt;a href="http://www.androidzeitgeist.com/2012/05/curious-blinklayout.html"&gt;the hidden BlinkLayout&lt;/a&gt; inside Android’s LayoutInflater &lt;a href="https://plus.google.com/105344175486242358933/posts"&gt;Thierry-Dimitri Roy&lt;/a&gt; wrote on Google+:&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://2.bp.blogspot.com/-kpn1WJrtNRw/T9CZQxI269I/AAAAAAAADnM/Pxbd7NWhWkM/s1600/gpluscomment.png" imageanchor="1" style="clear: left; display: inline !important; margin-bottom: 1em; margin-right: 1em; text-align: center;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-kpn1WJrtNRw/T9CZQxI269I/AAAAAAAADnM/Pxbd7NWhWkM/s1600/gpluscomment.png" /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
That’s a challenge I accept! Back in the days when I worked at Jimdo we developed “&lt;a href="http://www.youtube.com/watch?v=RDNhra-6dQo"&gt;a lifeboat for GeoCities&lt;/a&gt;” which allowed users to migrate their GeoCities website to Jimdo before GeoCities finally shut down in 2009. So I’ve some kind of heart for&amp;nbsp;GeoCities&amp;nbsp;users.&lt;br /&gt;
&lt;br /&gt;
The &lt;a href="http://developer.android.com/guide/topics/graphics/view-animation.html"&gt;view animation system&lt;/a&gt; of Android makes it quite easy to develop something like a MarqueeLayout. All we need to do is to extend an existing ViewGroup and attach a marquee-like animation to every instance.&lt;br /&gt;
&lt;br /&gt;
The &lt;a href="http://developer.android.com/reference/android/view/animation/TranslateAnimation.html"&gt;TranslateAnimation&lt;/a&gt; does already exactly what we need: It moves a view from a starting position to an ending position. The two positions can either be declared absolute (position on the screen) or relative to the view or its parent. After that we only need to define the duration of the animation and Android will do the rest for us.&lt;br /&gt;
&lt;br /&gt;
We'll define the start and end positions of the animation by using coordinates relative to the view. When using relative coordinates you can think of our view having a size of 1x1 and it's top left corner placed at (0,0).&lt;br /&gt;
&lt;br /&gt;
&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-002il9hIkbs/T9CiYixSw3I/AAAAAAAADnY/-04SitxZqVg/s1600/view.png" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-002il9hIkbs/T9CiYixSw3I/AAAAAAAADnY/-04SitxZqVg/s1600/view.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;View of size 1x1 at position (0,0)&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
If our view's width stretches to the whole width of the screen we can consider the screen's size also 1 (relative to the view's width).&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-a8TAfL-nbQs/T9ClZz9tuxI/AAAAAAAADnk/qwDhuGD7DRU/s1600/view_on_screen.png" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-a8TAfL-nbQs/T9ClZz9tuxI/AAAAAAAADnk/qwDhuGD7DRU/s1600/view_on_screen.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;View (green) filling full width of screen (grey)&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
Assuming a screen size of 1 and a starting position on the right side outside of the screen gives us a relative starting position of (1,0). This will place our view exactly outside the screen (or it's parent).&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-wuSTX1TEt88/T9Cl3Z4JaxI/AAAAAAAADns/orVD4QJqXMg/s1600/start_at_1_0.png" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="231" src="http://2.bp.blogspot.com/-wuSTX1TEt88/T9Cl3Z4JaxI/AAAAAAAADns/orVD4QJqXMg/s320/start_at_1_0.png" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;View animation starting at (1,0)&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
The view should move from the starting position to the left until it's outside of the screen at (-1, 0).&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-NOoImxh16nw/T9CmIXQJRqI/AAAAAAAADn0/OF_7nGDw9Pw/s1600/end_-1_0_1.png" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="231" src="http://4.bp.blogspot.com/-NOoImxh16nw/T9CmIXQJRqI/AAAAAAAADn0/OF_7nGDw9Pw/s320/end_-1_0_1.png" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;View animation stopping at (-1,0)&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
The animation system will generate all transient positions needed for the animation. Given all the information above we can write a simple MarqueeLayout in a few lines:&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;span style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;a href="http://www.blogger.com/goog_1690609543"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-OaTBb9uyHZ4/T9Cox5IvbMI/AAAAAAAADoA/bD9eXxmXu-Y/s1600/marquee_layout_code.png" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;a href="http://source.androidzeitgeist.com/raw/marquee_layout_code.txt"&gt;MarqueeLayout.java&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
That's what our MarqueeLayout looks like when adding a TextView to it:&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
&lt;iframe allowfullscreen="" frameborder="0" height="360" src="http://www.youtube.com/embed/r1LT2EpIB0s" width="480"&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
The following code was used to set up an activity using our MarqueeLayout:&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;span style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;a href="http://www.blogger.com/goog_1690609550"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-VzGJqlPup70/T9CpDx20HUI/AAAAAAAADoI/iw61M_02ZuQ/s1600/marquee_activity.png" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;a href="http://source.androidzeitgeist.com/raw/marquee_layout_activity.txt"&gt;MarqueeLayoutActivity.java&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div style="text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/AndroidZeitgeist/~4/5ogW6KCmbFc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.androidzeitgeist.com/feeds/2571392770508842451/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.androidzeitgeist.com/2012/06/creating-marqueelayout-with-android.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1531829516427013333/posts/default/2571392770508842451?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1531829516427013333/posts/default/2571392770508842451?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/AndroidZeitgeist/~3/5ogW6KCmbFc/creating-marqueelayout-with-android.html" title="Creating a MarqueeLayout with the Android Animation System" /><author><name>Sebastian Kaspari</name><uri>https://plus.google.com/112283223674539938062</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-20YfT7gfh08/AAAAAAAAAAI/AAAAAAAALWI/LZ-ps7enWlI/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-kpn1WJrtNRw/T9CZQxI269I/AAAAAAAADnM/Pxbd7NWhWkM/s72-c/gpluscomment.png" height="72" width="72" /><thr:total>1</thr:total><gd:extendedProperty name="commentSource" value="1" /><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD" /><feedburner:origLink>http://www.androidzeitgeist.com/2012/06/creating-marqueelayout-with-android.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0AER3c-fyp7ImA9WhNSFk4.&quot;"><id>tag:blogger.com,1999:blog-1531829516427013333.post-8985540882459629006</id><published>2012-06-05T20:33:00.000+02:00</published><updated>2012-10-30T23:21:46.957+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-10-30T23:21:46.957+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Instant Mustache" /><title>Instant Mustache #1 - The idea</title><content type="html">&lt;span style="font-family: Arial; font-size: 15px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;span style="font-family: 'Times New Roman'; font-size: x-small; white-space: normal;"&gt;This article is part of a series of articles about the development process of Instant Mustache, a fun camera app that adds mustaches to all faces using face detection.&amp;nbsp;&lt;/span&gt;&lt;a href="http://www.androidzeitgeist.com/p/instant-mustache.html" style="font-family: 'Times New Roman'; font-size: small; white-space: normal;"&gt;Click here&lt;/a&gt;&lt;span style="font-family: 'Times New Roman'; font-size: x-small; white-space: normal;"&gt;&amp;nbsp;to get a chronological list of all published&amp;nbsp;&lt;/span&gt;&lt;a href="http://www.androidzeitgeist.com/p/instant-mustache.html" style="font-family: 'Times New Roman'; font-size: small; white-space: normal;"&gt;articles about Instant Mustache&lt;/a&gt;&lt;span style="font-family: 'Times New Roman'; font-size: x-small; white-space: normal;"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Arial; font-size: 15px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;
&lt;span style="font-family: Arial; font-size: 15px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;b&gt;The idea&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span id="internal-source-marker_0.8338896373752505"&gt;&lt;span style="font-family: Arial; vertical-align: baseline;"&gt;&lt;span style="font-size: 15px; white-space: pre-wrap;"&gt;Instant Mustache is the name of an app that I'm going to develop. The idea is to show the development process of an app starting from a rough idea to a full featured app in the Android market. I'll demonstrate the process of developing the app as well as the thoughts and decisions involved. The source code will be publicly available on &lt;/span&gt;&lt;a href="http://github.com/pocmo/Instant-Mustache" style="font-size: 15px; font-weight: normal; white-space: pre-wrap;"&gt;GitHub&lt;/a&gt;&lt;span style="font-size: 15px; white-space: pre-wrap;"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span id="internal-source-marker_0.8338896373752505"&gt;&lt;span style="font-family: Arial; font-size: 15px; font-weight: normal; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Arial; font-size: 15px; font-weight: normal; vertical-align: baseline; white-space: pre-wrap;"&gt;Later versions of this series of articles are expected to be about topics like &lt;i&gt;refactoring&lt;/i&gt;, adding &lt;i&gt;features&lt;/i&gt;, &lt;i&gt;testing&lt;/i&gt; and maybe &lt;i&gt;monetization&lt;/i&gt;. I'll try to make everything as transparent as possible including user statistics of the Android market.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style="font-family: Arial; font-size: 15px; vertical-align: baseline; white-space: pre-wrap;"&gt;The app&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;b id="internal-source-marker_0.8338896373752505"&gt;&lt;span style="font-family: Arial; font-size: 15px; font-weight: normal; vertical-align: baseline; white-space: pre-wrap;"&gt;Instant Mustache is a fun app that utilizes the face tracking feature of Android 4.x to add mustaches to all detected faces currently visible to the camera. Users will be able to take funny pictures and share them with their friends on social networks or other apps on their mobile phone. The user shouldn't need to place the mustaches herself. Instead the placing should be done automatically for every detected face.&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;div&gt;
&lt;span id="internal-source-marker_0.8338896373752505"&gt;&lt;span style="font-family: Arial; font-size: 15px; font-weight: normal; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Arial; font-size: 15px; font-weight: normal; vertical-align: baseline; white-space: pre-wrap;"&gt;This is a rough idea every developer can come up with. In the following postings we will refine the idea, plan the app with some basic wireframes and develop an elementary version that can be extended to match our planned full-featured app later.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: Arial; font-size: 15px; font-weight: normal; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: Arial;"&gt;&lt;span style="font-size: 15px; white-space: pre-wrap;"&gt;&lt;b&gt;Do not forget the napkin&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;b id="internal-source-marker_0.8338896373752505"&gt;&lt;span style="font-family: Arial; font-size: 15px; font-weight: normal; vertical-align: baseline; white-space: pre-wrap;"&gt;Of course as a good entrepreneur we had this world-changing idea on the go and had only time to sketch it on a napkin to not forget it later.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Arial; font-size: 15px; font-weight: normal; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Arial; font-size: 15px; font-weight: normal; vertical-align: baseline; white-space: pre-wrap;"&gt;So here is the napkin we came up with:&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
&lt;a href="http://1.bp.blogspot.com/-fF1hf6-tlzA/T8ZmAQiTOzI/AAAAAAAADb4/ADS5E1ODlLU/s1600/instant_mustache_tissue.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="200" src="http://1.bp.blogspot.com/-fF1hf6-tlzA/T8ZmAQiTOzI/AAAAAAAADb4/ADS5E1ODlLU/s200/instant_mustache_tissue.jpg" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;b&gt;&lt;span style="font-family: Arial; font-size: 15px; font-weight: normal; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/AndroidZeitgeist/~4/QNOIAC4E51A" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.androidzeitgeist.com/feeds/8985540882459629006/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.androidzeitgeist.com/2012/06/instant-mustache-1-idea.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1531829516427013333/posts/default/8985540882459629006?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1531829516427013333/posts/default/8985540882459629006?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/AndroidZeitgeist/~3/QNOIAC4E51A/instant-mustache-1-idea.html" title="Instant Mustache #1 - The idea" /><author><name>Sebastian Kaspari</name><uri>https://plus.google.com/112283223674539938062</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-20YfT7gfh08/AAAAAAAAAAI/AAAAAAAALWI/LZ-ps7enWlI/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-fF1hf6-tlzA/T8ZmAQiTOzI/AAAAAAAADb4/ADS5E1ODlLU/s72-c/instant_mustache_tissue.jpg" height="72" width="72" /><thr:total>2</thr:total><gd:extendedProperty name="commentSource" value="1" /><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD" /><feedburner:origLink>http://www.androidzeitgeist.com/2012/06/instant-mustache-1-idea.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0AGQ30_fip7ImA9WhNSFk4.&quot;"><id>tag:blogger.com,1999:blog-1531829516427013333.post-9065086572488467738</id><published>2012-05-27T19:01:00.002+02:00</published><updated>2012-10-30T23:22:02.346+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-10-30T23:22:02.346+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="BlinkLayout" /><category scheme="http://www.blogger.com/atom/ns#" term="ViewGroup" /><category scheme="http://www.blogger.com/atom/ns#" term="Layout" /><title>The curious BlinkLayout</title><content type="html">&lt;span id="internal-source-marker_0.19517051335424185"&gt;&lt;span style="font-family: Arial; font-size: 15px; font-weight: normal; vertical-align: baseline; white-space: pre-wrap;"&gt;While reading the source code of Android's &lt;a href="http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.0.3_r1/android/view/LayoutInflater.java#LayoutInflater"&gt;LayoutInflater class&lt;/a&gt; I found a hidden gem that seems to be quite unnoticed yet. Ladies and gentlemen I present you the mighty &lt;a href="http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.0.3_r1/android/view/LayoutInflater.java#LayoutInflater.BlinkLayout"&gt;BlinkLayout&lt;/a&gt;. Views that are placed inside this ViewGroup blink at a rate of 500ms.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Arial; font-size: 15px; font-weight: normal; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Arial; font-size: 15px; font-weight: normal; vertical-align: baseline; white-space: pre-wrap;"&gt;The BlinkLayout is an inner class of the LayoutInflater and can therefore only be used in a XML layout that will be parsed by a LayoutInflater instance. Due to the implementation it's only possible to use it as root node using the &amp;lt;blink&amp;gt; tag inside a XML layout.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Arial; font-size: 15px; font-weight: normal; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Arial; font-size: 15px; font-weight: normal; vertical-align: baseline; white-space: pre-wrap;"&gt;It seems like the BlinkLayout is available since Android 4.0 and isn't used in the Android source code I observed. Maybe it was added for debugging reasons and was forgotten later.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Arial;"&gt;&lt;span style="font-size: 15px; white-space: pre-wrap;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;object class="BLOGGER-youtube-video" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" data-thumbnail-src="http://i.ytimg.com/vi/o_EX1mH5ZvM/0.jpg" height="266" width="320"&gt;&lt;param name="movie" value="http://www.youtube.com/v/o_EX1mH5ZvM?version=3&amp;f=user_uploads&amp;c=google-webdrive-0&amp;app=youtube_gdata" /&gt;




&lt;param name="bgcolor" value="#FFFFFF" /&gt;




&lt;embed width="320" height="266"  src="http://www.youtube.com/v/o_EX1mH5ZvM?version=3&amp;f=user_uploads&amp;c=google-webdrive-0&amp;app=youtube_gdata" type="application/x-shockwave-flash"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;
&lt;span style="font-family: Arial;"&gt;&lt;span style="font-size: 15px; white-space: pre-wrap;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Arial; font-size: 15px; font-weight: normal; vertical-align: baseline; white-space: pre-wrap;"&gt;T&lt;/span&gt;&lt;span style="font-family: Arial; font-size: 15px; vertical-align: baseline; white-space: pre-wrap;"&gt;he video above shows the BlinkLayout in action using the following layout XML:&lt;/span&gt;&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-2PBd4Bdwjr8/T8I-BukTXnI/AAAAAAAADZs/_z-Ajl7hOlo/s1600/blinklayout_xml.png" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img alt="" border="0" src="http://1.bp.blogspot.com/-2PBd4Bdwjr8/T8I-BukTXnI/AAAAAAAADZs/_z-Ajl7hOlo/s1600/blinklayout_xml.png" title="" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;a href="http://source.androidzeitgeist.com/raw/blinklayout_view_xml.txt"&gt;main_layout.xml&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;span style="font-family: Arial; font-size: 15px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Arial; font-size: 15px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;span style="font-family: Arial; font-size: 15px; vertical-align: baseline; white-space: pre-wrap;"&gt;T&lt;/span&gt;&lt;span style="font-family: Arial; font-size: 15px; vertical-align: baseline; white-space: pre-wrap;"&gt;he following snippet was used to inflate the layout and pass it to the activity:&lt;/span&gt;&lt;br /&gt;
&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;span style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;a href="http://www.blogger.com/goog_899898043"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-zgP0dePQwzw/T8JIp8nqZ0I/AAAAAAAADaY/ZP7LER-JmM0/s1600/blinklayout_code.png" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;a href="http://source.androidzeitgeist.com/raw/blinklayout_activity_code.txt"&gt;BlinkLayoutActivity.java&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div style="text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;span style="font-family: Arial;"&gt;&lt;span style="font-size: 15px; white-space: pre-wrap;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span style="font-family: Arial; font-size: 15px; font-weight: normal; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style="font-family: Arial;"&gt;&lt;span style="font-size: 15px; white-space: pre-wrap;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;br /&gt;
&lt;span style="font-family: Arial;"&gt;&lt;span style="font-size: 15px; white-space: pre-wrap;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span style="font-family: Arial; font-size: 15px; font-weight: normal; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;img src="http://feeds.feedburner.com/~r/AndroidZeitgeist/~4/1MleyCfQAow" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.androidzeitgeist.com/feeds/9065086572488467738/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.androidzeitgeist.com/2012/05/curious-blinklayout.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1531829516427013333/posts/default/9065086572488467738?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1531829516427013333/posts/default/9065086572488467738?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/AndroidZeitgeist/~3/1MleyCfQAow/curious-blinklayout.html" title="The curious BlinkLayout" /><author><name>Sebastian Kaspari</name><uri>https://plus.google.com/112283223674539938062</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-20YfT7gfh08/AAAAAAAAAAI/AAAAAAAALWI/LZ-ps7enWlI/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-2PBd4Bdwjr8/T8I-BukTXnI/AAAAAAAADZs/_z-Ajl7hOlo/s72-c/blinklayout_xml.png" height="72" width="72" /><thr:total>2</thr:total><gd:extendedProperty name="commentSource" value="1" /><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD" /><feedburner:origLink>http://www.androidzeitgeist.com/2012/05/curious-blinklayout.html</feedburner:origLink></entry></feed>
