<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Styling Android</title>
	
	<link>http://blog.stylingandroid.com</link>
	<description>A guide to applying styles and themes to Android apps</description>
	<lastBuildDate>Sat, 18 May 2013 10:46:10 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/</creativeCommons:license>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/StylingAndroid" /><feedburner:info uri="stylingandroid" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Navigation Drawer – Part 1</title>
		<link>http://feedproxy.google.com/~r/StylingAndroid/~3/C20F9XvRG-Y/1793</link>
		<comments>http://blog.stylingandroid.com/archives/1793#comments</comments>
		<pubDate>Fri, 17 May 2013 10:00:37 +0000</pubDate>
		<dc:creator>Mark Allison</dc:creator>
				<category><![CDATA[Adapter]]></category>
		<category><![CDATA[ArrayAdapter]]></category>
		<category><![CDATA[DrawerLayout]]></category>
		<category><![CDATA[androiddev]]></category>

		<guid isPermaLink="false">http://blog.stylingandroid.com/?p=1793</guid>
		<description><![CDATA[As I am writing this it is Google I/O week 2013. Amongst the new releases this week is a new version of the v4 support library (release 13) which contains support for the Navigation Drawer pattern. This pattern steadily grown in popularity, but until this point there has been no official support and guidelines from [...]]]></description>
				<content:encoded><![CDATA[<p>As I am writing this it is Google I/O week 2013. Amongst the new releases this week is a new version of the v4 support library (release 13) which contains support for the Navigation Drawer pattern. This pattern steadily grown in popularity, but until this point there has been no official support and guidelines from Google. This has now changed, and there are <a href="http://developer.android.com/design/patterns/navigation-drawer.html" target="_blank">official design guidelines</a>. In the recent series on <a href="/archives/1679" title="Adapters – Part 1">Adapters</a> we created an app which used <em>Spinner</em> navigation in the <em>ActionBar</em> to switch between different examples. In this short series we&#8217;ll convert this to use the Navigation Drawer pattern instead.<br />
<span id="more-1793"></span></p>
<p>The first thing that we need to do is switch to release 13 of the support library. As this is a maven project, this is achieved via the POM, but if you are not using maven you&#8217;ll need to remove the existing library and re-import release 13.</p>
<p>The first thing that we need to do is alter our main layout and wrap it in a <em>DrawerLayout</em> (from the support library) and then add a new <em>ListView</em> to contain the navigation list:</p>
<pre class="brush: xml; highlight: [1,2,3,4,5,6,7,15,16,17,18,19,20,21,22,23]; title: ; notranslate">
&lt;android.support.v4.widget.DrawerLayout 
    xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
    xmlns:tools=&quot;http://schemas.android.com/tools&quot;
    android:id=&quot;@+id/drawer_layout&quot;
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;match_parent&quot;
    tools:context=&quot;.MainActivity&quot; &gt;

    &lt;FrameLayout
        android:id=&quot;@+id/main&quot;
        android:layout_width=&quot;match_parent&quot;
        android:layout_height=&quot;match_parent&quot; &gt;
    &lt;/FrameLayout&gt;

    &lt;ListView
        android:id=&quot;@+id/drawer&quot;
        android:layout_width=&quot;240dp&quot;
        android:layout_height=&quot;match_parent&quot;
        android:layout_gravity=&quot;start&quot;
        android:background=&quot;#FFF&quot;
        android:choiceMode=&quot;singleChoice&quot; /&gt;

&lt;/android.support.v4.widget.DrawerLayout&gt;
</pre>
<p>Next we need to change our MainActivity to attach the Adapter to the <em>ListView</em> instead of the existing <em>Spinner</em>:</p>
<pre class="brush: java; highlight: [0,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52]; title: ; notranslate">
@Override
protected void onCreate(Bundle savedInstanceState)
{
	super.onCreate(savedInstanceState);
	setContentView(R.layout.activity_main);
	final String[] names = 
		getResources().getStringArray(R.array.nav_names);
	final String[] classes = 
		getResources().getStringArray(R.array.nav_classes);
	ArrayAdapter&lt;String&gt; adapter = 
		new ArrayAdapter&lt;String&gt;(
			getActionBar().getThemedContext(), 
			android.R.layout.simple_list_item_1, names);

	final DrawerLayout drawer = 
		(DrawerLayout)findViewById(R.id.drawer_layout);
	final ListView navList = 
		(ListView) findViewById(R.id.drawer);
	navList.setAdapter(adapter);
	navList.setOnItemClickListener(new OnItemClickListener()
	{

		@Override
		public void onItemClick(AdapterView&lt;?&gt; parent, 
				View view, final int pos, long id)
		{
			drawer.setDrawerListener( 
				new DrawerLayout.SimpleDrawerListener()
			{
				@Override
				public void onDrawerClosed(View drawerView)
				{
					super.onDrawerClosed(drawerView);
					FragmentTransaction tx = 
						getSupportFragmentManager()
							.beginTransaction();
					tx.replace(R.id.main, 
						Fragment.instantiate(
							MainActivity.this, 
							classes[pos]));
					tx.commit();
				}
			});
			drawer.closeDrawer(navList);
		}
	});

	FragmentTransaction tx = 
		getSupportFragmentManager().beginTransaction();
	tx.replace(R.id.main,
		Fragment.instantiate(MainActivity.this, classes[0]));
	tx.commit();
}
</pre>
<p>First we need to use a different layout for each item as this is now a <em>ListView</em> and not a <em>Spinner</em>. Next we find our <em>DrawerLayout</em> and <em>ListView</em> controls from the layout and set the <em>Adapter</em> to the <em>ListView</em>. Then we handle click events on our <em>ListView</em> &#8211; whenever an item is clicked, we close the drawer, wait for it to complete using a <em>DrawerListener</em>, and switch the <em>Fragment</em> once the drawer has closed. The reason for waiting for the drawer to close is to prevent stuttering during the drawer closing animation if we try and switch the <em>Fragment</em> at the same time. Alternatively we could switch the <em>Fragment</em> first, and then close the drawer, but for simplicity in this example we&#8217;ll wait for the drawer to close.</p>
<p>Finally we need to set set the default <em>Fragment</em>. The reason for this is that when we were using the <em>Spinner</em>, a default selection in the <em>Spinner</em> would be made which would trigger our <em>OnNavigationListener</em> to create the appropriate <em>Fragment</em>. In this new navigation model there is no initial event so we have to load the default <em>Fragment</em> manually.</p>
<p>That&#8217;s enough to get a basic Navigation Drawer working. If we swipe from the left hand edge of the screen our Navigation Drawer appears, and we can select the different examples:</p>
<p><a href="http://blog.stylingandroid.com/wp-content/uploads/2013/05/simple.png"><img src="http://blog.stylingandroid.com/wp-content/uploads/2013/05/simple.png" alt="simple" width="360" height="567" class="alignnone size-full wp-image-1807" /></a></p>
<p>In the next article in this series we&#8217;ll look at how we can connect the Navigation Drawer up the the app icon in our <em>ActionBar</em> to show and hide it.</p>
<p>The source code for this article is available <a href="https://bitbucket.org/StylingAndroid/adapters/src/03263bae4437e5e26c5d433bbfacb3ffd429a1cd/?at=NavigationDrawerPart1" target="_blank">here</a>.</p>
<p style='text-align:left'>&copy; 2013, <a href='http://blog.stylingandroid.com'>Mark Allison</a>. All rights reserved. This article originally appeared on <a href="http://blog.stylingandroid.com">Styling Android</a>.<br/><br/>Portions of this page are modifications based on work created and shared by Google and used according to terms described in the Creative Commons 3.0 Attribution License</p>
<p><a class="a2a_button_delicious" href="http://www.addtoany.com/add_to/delicious?linkurl=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1793&amp;linkname=Navigation%20Drawer%20%E2%80%93%20Part%201" title="Delicious" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/delicious.png" width="16" height="16" alt="Delicious"/></a><a class="a2a_button_stumbleupon" href="http://www.addtoany.com/add_to/stumbleupon?linkurl=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1793&amp;linkname=Navigation%20Drawer%20%E2%80%93%20Part%201" title="StumbleUpon" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/stumbleupon.png" width="16" height="16" alt="StumbleUpon"/></a><a class="a2a_button_reddit" href="http://www.addtoany.com/add_to/reddit?linkurl=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1793&amp;linkname=Navigation%20Drawer%20%E2%80%93%20Part%201" title="Reddit" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/reddit.png" width="16" height="16" alt="Reddit"/></a><a class="a2a_button_digg" href="http://www.addtoany.com/add_to/digg?linkurl=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1793&amp;linkname=Navigation%20Drawer%20%E2%80%93%20Part%201" title="Digg" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/digg.png" width="16" height="16" alt="Digg"/></a><a href="javascript:if(document.all){window.external.AddFavorite('http://blog.stylingandroid.com/archives/1793','Navigation%20Drawer%20&#8211;%20Part%201')}else{var%20b=a2a_config.localize.BookmarkInstructions%20||%20'Press%20Ctrl+D%20to%20bookmark%20this%20page';alert(a2a_config.localize.BookmarkInstructions)}" title="Bookmark/Favorites" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/bookmark.png" width="16" height="16" alt="Bookmark/Favorites"/></a><a class="a2a_button_twitter_tweet addtoany_special_service" data-count="none" data-url="http://blog.stylingandroid.com/archives/1793" data-text="Navigation Drawer &#8211; Part 1"></a><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1793&amp;title=Navigation%20Drawer%20%E2%80%93%20Part%201" id="wpa2a_4"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share"/></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/StylingAndroid?a=C20F9XvRG-Y:J0C2dKTIvkQ:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/StylingAndroid?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/StylingAndroid/~4/C20F9XvRG-Y" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.stylingandroid.com/archives/1793/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/</creativeCommons:license>
	<feedburner:origLink>http://blog.stylingandroid.com/archives/1793</feedburner:origLink></item>
		<item>
		<title>Adapters – Part 6</title>
		<link>http://feedproxy.google.com/~r/StylingAndroid/~3/DDkzqklkb4o/1783</link>
		<comments>http://blog.stylingandroid.com/archives/1783#comments</comments>
		<pubDate>Fri, 10 May 2013 10:00:01 +0000</pubDate>
		<dc:creator>Mark Allison</dc:creator>
				<category><![CDATA[Adapter]]></category>
		<category><![CDATA[PagerAdapter]]></category>
		<category><![CDATA[ViewPager]]></category>
		<category><![CDATA[androiddev]]></category>

		<guid isPermaLink="false">http://blog.stylingandroid.com/?p=1783</guid>
		<description><![CDATA[Previously in this series we&#8217;ve looked at different kinds of Adapters, and in two separate separate series on Styling Android (ViewPager and ViewPager Redux) we&#8217;ve looked at ViewPagers. In this article we&#8217;re going to look at the common factor of both of these: PagerAdapters. A PagerAdapter is responsible for creating the content for each page [...]]]></description>
				<content:encoded><![CDATA[<p>Previously in this <a href="/archives/1679" title="Adapters – Part 1">series</a> we&#8217;ve looked at different kinds of <em>Adapter</em>s, and in two separate separate series on Styling Android (<a href="/archives/537" title="ViewPager – Part 1">ViewPager</a> and <a href="/archives/1357" title="ViewPager Redux – Part 1">ViewPager Redux</a>) we&#8217;ve looked at <em>ViewPager</em>s. In this article we&#8217;re going to look at the common factor of both of these: <em>PagerAdapters</em>.<br />
<span id="more-1783"></span></p>
<p>A <em>PagerAdapter</em> is responsible for creating the content for each page within a <em>ViewPager</em>. It takes two main forms: When creating or inflating a standard <em>View</em> hierarchy the standard <em>PagerAdapter</em> is used, but when each page is a <em>Fragment</em> we can use <em>FragmentPagerAdapter</em> instead. Let&#8217;s start with the former:</p>
<pre class="brush: java; title: ; notranslate">
private static String[] titles = new String[]
{ 
	&quot;Page 1&quot;, &quot;Page 2&quot;, &quot;Page 3&quot;, &quot;Page 4&quot;, &quot;Page 5&quot;
};

private class MyPagerAdapter extends PagerAdapter
{
	@Override
	public int getCount()
	{
		return titles.length;
	}

	@Override
	public boolean isViewFromObject(View view, 
		Object object)
	{
		return view.equals(object);
	}

	@Override
	public Object instantiateItem(ViewGroup container, 
		int position)
	{
		TextView text = new TextView(getActivity());
		text.setText(titles[position]);
		container.addView(text);
		return text;
		}

	@Override
	public void destroyItem(ViewGroup container, 
		int position, Object object)
	{
		if (object instanceof View)
		{
			container.removeView((View) object);
		}
	}
		
	@Override
	public CharSequence getPageTitle(int position)
	{
		return titles[position];
	}
}
</pre>
<p>This is pretty much as simple as we can get it. The view that is created is a simple <em>TextView</em> and we set the text to the value of the appropriate string from the titles array. In the <code>instantiateItem()</code> method we could, just as easily, use a <em>LayoutInflator</em> to inflate a layout from XML and then find the controls to bind to. We could also create or inflate different layouts depending on the position. But the basic principle in that <code>getCount()</code> returns the number of pages to display, <code>instantiateItem()</code> gets called to create the individual layouts, <code>destroyItem()</code> gets called to remove the layouts, and <code>getPageTitle()</code> returns the title to use in a <em>PagerTabStrip</em> or <em>PagerTitleStrip</em> (for more information on <em>PagerTabString</em> see <a href="/archives/1366" title="ViewPager Redux – Part 2">this article</a>).</p>
<p>To create Fragment instead of a <em>View</em> hierarchy, we first need to create a Fragment class: </p>
<pre class="brush: java; title: ; notranslate">
public static class MyFragment extends Fragment
{		
	private static final String TAG = &quot;MyFragment&quot;;
	public MyFragment()
	{
		super();
	}
		
	@Override
	public View onCreateView(LayoutInflater inflater, 
		ViewGroup container,
		Bundle savedInstanceState)
	{
		View view = inflater.inflate(R.layout.page, 
			container, false);
		View text = view.findViewById(android.R.id.text1);
		if(text != null &amp;&amp; text instanceof TextView)
		{
			((TextView)text).setText(
				titles[getArguments().getInt(&quot;position&quot;)]);
			}
		return view;
	}
				
	@Override
	public void onAttach(Activity activity)
	{
		super.onAttach(activity);
		Log.d(TAG, &quot;Attached &quot; + 
			getArguments().getInt(&quot;position&quot;));
	}
		
	@Override
	public void onDetach()
	{
		Log.d(TAG, &quot;Detached &quot; + 
			getArguments().getInt(&quot;position&quot;));
		super.onDetach();
	}
}
</pre>
<p>Our <em>Fragment</em> class, <code>MyFragment</code>, creates a layout identical to the one used in the previous example, only in this case it inflates it from XML instead of creating the View objects programatically. Either approach is fine, just chose whichever suits the task that you&#8217;re trying to perform best &#8211; I&#8217;ve simply included both forms here to show that it can be done. The overrides of the <code>onAttach()</code> and <code>onDetach()</code> methods simply add a little logging to show when the instances of this class become attached and detached from an <em>Activity</em> (the reasons for adding this will become obvious later on). </p>
<p>The <em>Adapter</em> itself is actually simpler than the previous <em>PagerAdapter</em> example because we don&#8217;t need to worry about the <code>destroyItem()</code> method this time:</p>
<pre class="brush: java; title: ; notranslate">
private class MyFragmentPagerAdapter 
	extends FragmentPagerAdapter
{
	public MyFragmentPagerAdapter(FragmentManager fm)
	{
		super(fm);
	}

	@Override
	public Fragment getItem(int position)
	{
		Bundle args = new Bundle();
		args.putInt(&quot;position&quot;, position);
		return Fragment.instantiate(getActivity(), 
			MyFragment.class.getName(), args);
	}

	@Override
	public int getCount()
	{
		return titles.length;
	}
		
	@Override
	public CharSequence getPageTitle(int position)
	{
		return titles[position];
	}
}
</pre>
<p>The important thing to remember here is that we can actually instantiate different kinds of <em>Fragment</em> for different positions. It is the role of the <em>Adapter</em> to create the correct instance for each position. This implementation is actually much cleaner than the first example because it clearly splits the responsibilities in to different objects. The <em>Fragment</em> instance represents the view for an individual page, and the <em>Adapter</em> is responsible for creating the separate instances.</p>
<p>There is one further thing that is important, although I stated that there were two types of <em>PagerAdapter</em>, there are actually three because there are two variants of <em>FragmentPagerAdapter</em>: <em>FragmentPagerAdapter</em> (as we have used here) and <em>FragmentStatePagerAdapter</em>. The difference between the two is that <em>FragmentPagerAdpater</em> will create views and hold them in memory for the lifecycle of the <em>Adapter</em>, whereas <em>FragmentStatePagerAdapter</em> can destroy individual <em>Fragment</em>s when they are not visible. This makes <em>FragmentPagerAdapter</em> suitable when you have a small number of static page <em>Fragment</em>s that aren&#8217;t particularly memory hungry; but <em>FragmentStatePagerAdapter</em> is better if you have a large number of pages, or some or all of the individual page <em>Fragment</em>s are particularly memory hungry.</p>
<p>You can actually switch between the two by simply changing the base class that <em>MyFragmentPagerAdapter</em> subclasses. If you try this and check the logs, you&#8217;ll see that when using <em>FragmentPagerAdapter</em>, each of the views gets attached to the <em>Activity</em> once when it is first viewed, but they all remain attached no matter how much you page between the different pages in the <em>ViewPager</em>. On the other hand if you switch to <em>FragmentStatePagerAdapter</em> you&#8217;ll see that each time you switch pages, views will become attached to the <em>Activity</em> while others become detached.</p>
<p>If we run this, we can see two ViewPagers which look and behave identically, but have rather different implementations:</p>
<p><a href="http://blog.stylingandroid.com/wp-content/uploads/2013/05/PagerAdapter.png"><img src="http://blog.stylingandroid.com/wp-content/uploads/2013/05/PagerAdapter.png" alt="PagerAdapter" width="358" height="564" class="alignnone size-full wp-image-1787" /></a></p>
<p>That brings us to the end of this series on <em>Adapter</em>s. <em>PagerAdapters</em> are somewhat different to the other types of <em>Adapter</em> that we&#8217;ve looked at in this series, but many of the underlying principles are the same. Getting our <em>Adapter</em>s right is an important part of getting our UI to behave in a smooth manner, and therefore improving the overall user experience.</p>
<p>The source code for this article is available <a href="https://bitbucket.org/StylingAndroid/adapters/src/1139bfcb04252461e928bb3c933530c0c7b9818a/?at=Part6">here</a>.</p>
<p style='text-align:left'>&copy; 2013, <a href='http://blog.stylingandroid.com'>Mark Allison</a>. All rights reserved. This article originally appeared on <a href="http://blog.stylingandroid.com">Styling Android</a>.<br/><br/>Portions of this page are modifications based on work created and shared by Google and used according to terms described in the Creative Commons 3.0 Attribution License</p>
<p><a class="a2a_button_delicious" href="http://www.addtoany.com/add_to/delicious?linkurl=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1783&amp;linkname=Adapters%20%E2%80%93%20Part%206" title="Delicious" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/delicious.png" width="16" height="16" alt="Delicious"/></a><a class="a2a_button_stumbleupon" href="http://www.addtoany.com/add_to/stumbleupon?linkurl=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1783&amp;linkname=Adapters%20%E2%80%93%20Part%206" title="StumbleUpon" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/stumbleupon.png" width="16" height="16" alt="StumbleUpon"/></a><a class="a2a_button_reddit" href="http://www.addtoany.com/add_to/reddit?linkurl=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1783&amp;linkname=Adapters%20%E2%80%93%20Part%206" title="Reddit" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/reddit.png" width="16" height="16" alt="Reddit"/></a><a class="a2a_button_digg" href="http://www.addtoany.com/add_to/digg?linkurl=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1783&amp;linkname=Adapters%20%E2%80%93%20Part%206" title="Digg" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/digg.png" width="16" height="16" alt="Digg"/></a><a href="javascript:if(document.all){window.external.AddFavorite('http://blog.stylingandroid.com/archives/1783','Adapters%20&#8211;%20Part%206')}else{var%20b=a2a_config.localize.BookmarkInstructions%20||%20'Press%20Ctrl+D%20to%20bookmark%20this%20page';alert(a2a_config.localize.BookmarkInstructions)}" title="Bookmark/Favorites" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/bookmark.png" width="16" height="16" alt="Bookmark/Favorites"/></a><a class="a2a_button_twitter_tweet addtoany_special_service" data-count="none" data-url="http://blog.stylingandroid.com/archives/1783" data-text="Adapters &#8211; Part 6"></a><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1783&amp;title=Adapters%20%E2%80%93%20Part%206" id="wpa2a_8"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share"/></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/StylingAndroid?a=DDkzqklkb4o:nvsE_sVDWVY:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/StylingAndroid?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/StylingAndroid/~4/DDkzqklkb4o" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.stylingandroid.com/archives/1783/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/</creativeCommons:license>
	<feedburner:origLink>http://blog.stylingandroid.com/archives/1783</feedburner:origLink></item>
		<item>
		<title>Adapters – Part 5</title>
		<link>http://feedproxy.google.com/~r/StylingAndroid/~3/_RnOG5VujB0/1766</link>
		<comments>http://blog.stylingandroid.com/archives/1766#comments</comments>
		<pubDate>Fri, 03 May 2013 10:00:46 +0000</pubDate>
		<dc:creator>Mark Allison</dc:creator>
				<category><![CDATA[Adapter]]></category>
		<category><![CDATA[CursorAdapter]]></category>
		<category><![CDATA[CursorLoader]]></category>
		<category><![CDATA[Loader]]></category>
		<category><![CDATA[androiddev]]></category>

		<guid isPermaLink="false">http://blog.stylingandroid.com/?p=1766</guid>
		<description><![CDATA[Previously in this series we&#8217;ve looked at how to use Adapters in various ways, and how to keep the scrolling of our ListViews smooth. In this article, we&#8217;ll turn our attention to how to bind a ListView to data which is stored in a SQLite database. As this series focuses on Adapters, I&#8217;m not going [...]]]></description>
				<content:encoded><![CDATA[<p>Previously in this series we&#8217;ve looked at how to use <em>Adapters</em> in various ways, and how to keep the scrolling of our <em>ListView</em>s smooth. In this article, we&#8217;ll turn our attention to how to bind a ListView to data which is stored in a SQLite database.<br />
<span id="more-1766"></span></p>
<p>As this series focuses on <em>Adapters</em>, I&#8217;m not going to provide a tutorial on SQLite databases and <em>ContentProviders</em>. For some useful information on these topics, please refer to Lars Vogel&#8217;s excellent <a href="http://www.vogella.com/articles/AndroidSQLite/article.html" target="_blank">tutorial</a>. Grokking Android&#8217;s Wolfram Rittmeyer has also written some useful <a href="http://www.grokkingandroid.com/tutorials/" target="_blank">tutorials</a> on this topic.</p>
<p>For our example, I have set up a simple database and ContentProvider. The database contains two columns: The obligatory ID column, and a column containing arbitrary text. We&#8217;ll simply store a set of numbers in text form (i.e. &#8220;One&#8221;, &#8220;Two&#8221;, &#8220;Three&#8221;, etc). To keep things simple, the database has been limited to the numbers 1-20. I won&#8217;t include this code in the article, but it&#8217;s available in the <a href="https://bitbucket.org/StylingAndroid/adapters/src/ebf9def9b3532a167ecdba5b89f0929b2c012bb6/src/com/stylingandroid/adapters/data?at=Part5">source</a> if you want to look at it.</p>
<p>Before we dive in to the code, it&#8217;s worth looking at a fundamental shift in the recommended usage of CursorAdapters which occurred in API 11 Honeycomb 3.0. Prior to that the accepted usage was to use the <code>FLAG_AUTO_REQUERY</code> flag which would cause the Cursor to be re-retrieved when it detected a change to the database. The only problem with this is that the database queries are performed on the UI thread which can make your UI laggy or, in extreme cases, present the user with the dreaded &#8220;Application Not Responding&#8221; dialog. Looking at the Javadocs for <a href="http://developer.android.com/reference/android/support/v4/widget/CursorAdapter.html" target="_blank">CursorAdapter</a> the suggestion is to use <em>CursorLoader</em> instead, but doesn&#8217;t give much more information. So we&#8217;ll implement things using a <em>CursorLoader</em> to see how to do this.</p>
<p>In actual fact, using a <em>CursorLoader</em> is simplicity itself, and it does a surprising amount for us. We used a Loader in the <a href="/archives/1737" title="Adapters – Part 4">previous article</a>, but this time we&#8217;ll implement our <em>LoaderCallback</em> in our ListFragment instead of in our <em>ViewHolder</em> as we don&#8217;t need a <em>ViewHolder</em> in this case:</p>
<pre class="brush: java; title: ; notranslate">
public class CursorAdapterFragment 
	extends ListFragment 
	implements LoaderCallbacks&lt;Cursor&gt;
{
	private static final String[] columns =
	{ 
		CounterHelper.COLUMN_ID, 
		CounterHelper.COLUMN_TEXT 
	};
	
	private static final int[] controlIds =
	{ 
		android.R.id.text1, 
		android.R.id.text2 
	};

	@Override
	public View onCreateView(LayoutInflater inflater, 
		ViewGroup container,
		Bundle savedInstanceState)
	{
		setHasOptionsMenu(true);
		return inflater.inflate(R.layout.listview, 
			container, false);
	}

	@Override
	public void onActivityCreated(Bundle savedInstanceState)
	{
		super.onActivityCreated(savedInstanceState);
		getLoaderManager().restartLoader(0, null, this);
	}

	@Override
	public Loader&lt;Cursor&gt; onCreateLoader(int id, Bundle args)
	{
		Loader&lt;Cursor&gt; loader = null;
		if (id == 0)
		{
			loader = new CursorLoader(getActivity(),
				CounterContentProvider.CONTENT_URI,
				CounterContentProvider.PROJECTION, 
				null, null,
				CounterHelper.COLUMN_ID + &quot; ASC&quot;);
		}
		return loader;
	}

	@Override
	public void onLoadFinished(Loader&lt;Cursor&gt; loader, 
		Cursor cursor)
	{
		ListAdapter adapter = getListAdapter();
		if (adapter == null || 
			!(adapter instanceof CursorAdapter))
		{
			adapter = new SimpleCursorAdapter(getActivity(),
				android.R.layout.simple_list_item_2, 
				cursor, columns, controlIds, 0);
			getActivity().invalidateOptionsMenu();
			setListAdapter(adapter);
		}
		else
		{
			((CursorAdapter) adapter).swapCursor(cursor);
		}
	}

	@Override
	public void onLoaderReset(Loader&lt;Cursor&gt; loader)
	{
	}
	@Override
	public void onCreateOptionsMenu(Menu menu, 
		MenuInflater inflater)
	{
		inflater.inflate(R.menu.cursor, menu);
	}

	@Override
	public void onPrepareOptionsMenu(Menu menu)
	{
		MenuItem item = menu.findItem(R.id.add);
		if (item != null)
		{
			item.setEnabled(getListAdapter() != null ? 
				getListAdapter().getCount() &lt; 
				CounterHelper.MAX_ROWS : false);
		}
		super.onPrepareOptionsMenu(menu);
	}

	@Override
	public boolean onOptionsItemSelected(final MenuItem item)
	{
		if (item.getItemId() == R.id.add)
		{
			int count = getListAdapter().getCount();
			if(count &lt; CounterHelper.MAX_ROWS)
			{
				item.setEnabled(false);
				AsyncQueryHandler queryHandler = 
					new AsyncQueryHandler(
						getActivity().getContentResolver())
				{
					@Override
					protected void onInsertComplete(int token, 
							Object cookie,
							Uri uri)
					{
						getActivity().invalidateOptionsMenu();
						super.onInsertComplete(token, 
								cookie, uri);
					}
				};
				ContentValues values = new ContentValues();
				values.put(CounterHelper.COLUMN_TEXT,
						CounterHelper.NUMBERS[count]);
				queryHandler.startInsert(0, null, 
						CounterContentProvider.CONTENT_URI, 
						values);
			}
			else
			{
				getActivity().invalidateOptionsMenu();
			}
		}
		return super.onOptionsItemSelected(item);
	}
}
</pre>
<p>In our <code>onActivityCreated()</code> method we kick off the <em>Loader</em> and it is in the <code>onCreateLoader()</code> method where we actually create our <em>CursorLoader</em> using some constants defined in the <em>ContentProvider</em>. We&#8217;re actually using the stock CursorLoader and we don&#8217;t have to subclass it because it actually does an awful lot for us, as we&#8217;ll explore in a while.</p>
<p>In our <code>onLoadFinished()</code> method we check whether a <em>CursorAdapter</em> already exists for the ListView and create one, if necessary. The Adapter that we&#8217;re using is a <em>SimpleCursorAdapter</em> which work in a similar way to the <em>SimpleAdapter</em> that we looked at in <a href="/archives/1702" title="Adapters – Part 2">part 2</a> of this series. It allows us to map columns in our database to controls in the layout rather than the <em>Map</em> that we used in <em>SimpleAdapter</em>.</p>
<p>The remainder of the code is just adding a simple menu which adds a new item to the database which allows us to see quite what the relatively simple <em>CursorLoader</em> &#038; <em>Adapter</em> are actually doing for us.</p>
<p>If we run this we&#8217;ll see an empty list, but if we click the add button a few times, we&#8217;ll see items automatically appear in the list:</p>
<p><a href="http://blog.stylingandroid.com/wp-content/uploads/2013/05/CursorAdapter.png"><img src="http://blog.stylingandroid.com/wp-content/uploads/2013/05/CursorAdapter.png" alt="CursorAdapter" width="359" height="565" class="alignnone size-full wp-image-1773" /><br />
</a></p>
<p>None of the code that we&#8217;ve added detects the data changing, and the reason that it&#8217;s happening is because the <em>CursorLoader</em> does it for us. When we first ran the <em>CursorLoader</em> it registered a <em>ContentObserver</em> on the data so it is automatically run again (on a background thread, of course) whenever the data changes. You can see this happening if you set a breakpoint in the <code>onLoadFinished()</code> method and hit the &#8220;Add&#8221; button.</p>
<p>We also don&#8217;t need to worry about cleaning things up because the <em>CursorLoader</em> is tied to the <em>Activity</em> lifecycle so will be properly cleaned up when our <em>Activity</em> goes out of scope.</p>
<p>All in all we get a lot of functionality for just a few lines of code. </p>
<p>Apologies that this article has focused a little more on <em>CursorLoader</em> than <em>CursorAdpater</em> (and this is, after all a series on Adapters), but the <em>Adapter</em> itself is pretty straightforward if you already understand how SimpleAdapter works, and the implementation is made even easier when we use a <em>CursorLoader</em> instead of acquiring a <em>Cursor</em> directly from the <em>ContentResolver</em>. Of course the <em>CursorLoader</em> pattern is applicable wherever you use <em>Cursors</em> and is not limited solely to <em>CursorAdapter</em>s.</p>
<p>In the next article we&#8217;ll have a look at how we use <em>Adapters</em> to populate <em>ViewPagers</em>. </p>
<p>The source code for this article is available <a href="https://bitbucket.org/StylingAndroid/adapters/src/ebf9def9b3532a167ecdba5b89f0929b2c012bb6/?at=Part5">here</a>.</p>
<p style='text-align:left'>&copy; 2013, <a href='http://blog.stylingandroid.com'>Mark Allison</a>. All rights reserved. This article originally appeared on <a href="http://blog.stylingandroid.com">Styling Android</a>.<br/><br/>Portions of this page are modifications based on work created and shared by Google and used according to terms described in the Creative Commons 3.0 Attribution License</p>
<p><a class="a2a_button_delicious" href="http://www.addtoany.com/add_to/delicious?linkurl=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1766&amp;linkname=Adapters%20%E2%80%93%20Part%205" title="Delicious" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/delicious.png" width="16" height="16" alt="Delicious"/></a><a class="a2a_button_stumbleupon" href="http://www.addtoany.com/add_to/stumbleupon?linkurl=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1766&amp;linkname=Adapters%20%E2%80%93%20Part%205" title="StumbleUpon" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/stumbleupon.png" width="16" height="16" alt="StumbleUpon"/></a><a class="a2a_button_reddit" href="http://www.addtoany.com/add_to/reddit?linkurl=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1766&amp;linkname=Adapters%20%E2%80%93%20Part%205" title="Reddit" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/reddit.png" width="16" height="16" alt="Reddit"/></a><a class="a2a_button_digg" href="http://www.addtoany.com/add_to/digg?linkurl=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1766&amp;linkname=Adapters%20%E2%80%93%20Part%205" title="Digg" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/digg.png" width="16" height="16" alt="Digg"/></a><a href="javascript:if(document.all){window.external.AddFavorite('http://blog.stylingandroid.com/archives/1766','Adapters%20&#8211;%20Part%205')}else{var%20b=a2a_config.localize.BookmarkInstructions%20||%20'Press%20Ctrl+D%20to%20bookmark%20this%20page';alert(a2a_config.localize.BookmarkInstructions)}" title="Bookmark/Favorites" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/bookmark.png" width="16" height="16" alt="Bookmark/Favorites"/></a><a class="a2a_button_twitter_tweet addtoany_special_service" data-count="none" data-url="http://blog.stylingandroid.com/archives/1766" data-text="Adapters &#8211; Part 5"></a><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1766&amp;title=Adapters%20%E2%80%93%20Part%205" id="wpa2a_12"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share"/></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/StylingAndroid?a=_RnOG5VujB0:7nTOBDCSKZM:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/StylingAndroid?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/StylingAndroid/~4/_RnOG5VujB0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.stylingandroid.com/archives/1766/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/</creativeCommons:license>
	<feedburner:origLink>http://blog.stylingandroid.com/archives/1766</feedburner:origLink></item>
		<item>
		<title>Adapters – Part 4</title>
		<link>http://feedproxy.google.com/~r/StylingAndroid/~3/aojVt6VhnTU/1737</link>
		<comments>http://blog.stylingandroid.com/archives/1737#comments</comments>
		<pubDate>Fri, 26 Apr 2013 10:00:18 +0000</pubDate>
		<dc:creator>Mark Allison</dc:creator>
				<category><![CDATA[Adapter]]></category>
		<category><![CDATA[ArrayAdapter]]></category>
		<category><![CDATA[Loader]]></category>
		<category><![CDATA[androiddev]]></category>

		<guid isPermaLink="false">http://blog.stylingandroid.com/?p=1737</guid>
		<description><![CDATA[In the previous article we looked at getting our ListView scrolling smooth by optimising the operations that we are performing in the getView() method of our Adapter. In this article we&#8217;ll look at adding images to each ListView item and consider the performance implications of doing that. Actually adding images to the list item is [...]]]></description>
				<content:encoded><![CDATA[<p>In the <a href="/archives/1710" title="Adapters – Part 3">previous article</a> we looked at getting our <em>ListView</em> scrolling smooth by optimising the operations that we are performing in the <code>getView()</code> method of our <em>Adapter</em>. In this article we&#8217;ll look at adding images to each <em>ListView</em> item and consider the performance implications of doing that.<br />
<span id="more-1737"></span></p>
<p>Actually adding images to the list item is easy enough, but we&#8217;ll compound the problems we face by not only loading images (which is an expensive operation), but also retrieving them from the cloud (another expensive operation). Neither of these operations should be performed in our <code>getView()</code> method, or indeed on the UI thread. To demonstrate this we&#8217;ll create a <em>ListView</em> which loads all of the emoticon icons from the <a href="https://github.com/android/platform_frameworks_base/tree/master/core/res/res" target="_blank">Android AOSP source on github</a>.</p>
<p>First we create an item layout which contains an ImageView:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;RelativeLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;wrap_content&quot;
    android:gravity=&quot;left|center_vertical&quot;
    android:minHeight=&quot;?android:attr/listPreferredItemHeightSmall&quot;
    android:paddingEnd=&quot;?android:attr/listPreferredItemPaddingEnd&quot;
    android:paddingStart=&quot;?android:attr/listPreferredItemPaddingStart&quot; &gt;

    &lt;TextView
        android:id=&quot;@android:id/text1&quot;
        android:layout_width=&quot;wrap_content&quot;
        android:layout_height=&quot;wrap_content&quot;
        android:textIsSelectable=&quot;false&quot; /&gt;

    &lt;ImageView
        android:id=&quot;@android:id/icon&quot;
        android:layout_width=&quot;wrap_content&quot;
        android:layout_height=&quot;wrap_content&quot;
        android:layout_below=&quot;@android:id/text1&quot;
        android:visibility=&quot;gone&quot; /&gt;

    &lt;ProgressBar
        android:id=&quot;@android:id/progress&quot;
        style=&quot;@android:style/Widget.ProgressBar.Small&quot;
        android:layout_width=&quot;wrap_content&quot;
        android:layout_height=&quot;wrap_content&quot;
        android:layout_below=&quot;@android:id/text1&quot;
        android:indeterminate=&quot;true&quot; 
        android:minWidth=&quot;@dimen/image_size&quot;
        android:minHeight=&quot;@dimen/image_size&quot;/&gt;

&lt;/RelativeLayout&gt;
</pre>
<p>We&#8217;re also preempting something that we&#8217;ll require later on &#8211; a <em>ProgressBar</em> to display in place of the image while we&#8217;re loading it.</p>
<p>Our <em>Adapter</em> is pretty similar to what we&#8217;ve used previously, we&#8217;re just overriding <code>getView()</code> and doing the same view recycling and caching that we&#8217;ve done previously:</p>
<pre class="brush: java; title: ; notranslate">
public class ArrayAdapterImageFragment extends ListFragment
{
	public static final String TAG = 
		&quot;ArrayAdapterImageFragment&quot;;
	private static final List&lt;String&gt; items = 
		new ArrayList&lt;String&gt;();

	private class ItemAdapter extends ArrayAdapter&lt;String&gt;
	{

		public ItemAdapter(Context context)
		{
			super(context, 
				android.R.layout.simple_list_item_2, items);
		}

		@Override
		public View getView(int position, View convertView, 
			ViewGroup parent)
		{
			View view = convertView;
			ArrayAdapterImageViewHolder holder = null;
			if (view == null)
			{
				view = LayoutInflater.from(getContext())
					.inflate(R.layout.image_item, parent, false);
				TextView text = (TextView) view
					.findViewById(android.R.id.text1);
				ImageView image = (ImageView) view
					.findViewById(android.R.id.icon);
				ProgressBar progress = (ProgressBar) view
					.findViewById(android.R.id.progress);
				view.setTag(new ArrayAdapterImageViewHolder(
					getContext(), text, image, progress));
			}
			if (holder == null &amp;&amp; view != null)
			{
				Object tag = view.getTag();
				if (tag instanceof ArrayAdapterImageViewHolder)
				{
					holder = 
						(ArrayAdapterImageViewHolder) tag;
				}
			}
			String item = getItem(position);
			if (item != null &amp;&amp; holder != null)
			{
				holder.setName(item);
			}
			return view;
		}
	}

	static
	{
		items.add(&quot;emo_im_angel&quot;);
		items.add(&quot;emo_im_cool&quot;);
		items.add(&quot;emo_im_embarrassed&quot;);
		items.add(&quot;emo_im_foot_in_mouth&quot;);
		items.add(&quot;emo_im_happy&quot;);
		items.add(&quot;emo_im_kissing&quot;);
		items.add(&quot;emo_im_laughing&quot;);
		items.add(&quot;emo_im_lips_are_sealed&quot;);
		items.add(&quot;emo_im_money_mouth&quot;);
		items.add(&quot;emo_im_sad&quot;);
		items.add(&quot;emo_im_surprised&quot;);
		items.add(&quot;emo_im_tongue_sticking_out&quot;);
		items.add(&quot;emo_im_undecided&quot;);
		items.add(&quot;emo_im_winking&quot;);
		items.add(&quot;emo_im_wtf&quot;);
		items.add(&quot;emo_im_yelling&quot;);
	}

	@Override
	public View onCreateView(LayoutInflater inflater, 
		ViewGroup container, 
		Bundle savedInstanceState)
	{
		return inflater.inflate(R.layout.listview, 
			container, false);
	}

	@Override
	public void onActivityCreated(Bundle savedInstanceState)
	{
		super.onActivityCreated(savedInstanceState);
		ListAdapter adapter = new ItemAdapter(getActivity());
		setListAdapter(adapter);
	}

}
</pre>
<p>One thing to note is that we&#8217;re not even attempting to bind anything to the <em>ImageView</em> control within our <code>getView()</code> method &#8211; we&#8217;re going to do this in a <em>Loader</em> to keep the heavy image download and decoding operations outside of our <code>getView()</code> method, and off of the UI thread. For a fuller discussion of this, please refer to the series on <a href="/archives/833" title="Background Tasks – Part 1" target="_blank">Background Tasks</a>.</p>
<p>First let&#8217;s look at the ViewHolder, which does rather more than the simple state holder that we used previously:</p>
<pre class="brush: java; title: ; notranslate">
public class ArrayAdapterImageViewHolder 
		implements LoaderCallbacks&lt;Bitmap&gt;
{
	private static final String TAG = 
		ArrayAdapterImageFragment.TAG;

	private static int nextLoaderId = 0;
	private final int loaderId;
	private final Bundle bundle = new Bundle();
	private final Context context;
	private String name = null;
	public final TextView text;
	public final ImageView image;
	public final ProgressBar progress;

	public ArrayAdapterImageViewHolder(Context context, 
		TextView text, ImageView image, ProgressBar progress)
	{
		this.context = context;
		this.text = text;
		this.image = image;
		this.progress = progress;
		this.loaderId = nextLoaderId++;
	}

	@Override
	public Loader&lt;Bitmap&gt; onCreateLoader(int id, Bundle args)
	{
		return new ArrayAdapterImageLoader(
			context, args.getString(&quot;name&quot;));
	}

	@Override
	public void onLoadFinished(
		Loader&lt;Bitmap&gt; loader, 
		Bitmap bitmap)
	{
		if(bitmap != null)
		{
			image.setImageBitmap(bitmap);
		}
		image.setVisibility(View.VISIBLE);
		progress.setVisibility(View.GONE);
	}

	@Override
	public void onLoaderReset(Loader&lt;Bitmap&gt; loader)
	{
		loader.abandon();
	}
	
	public void setName(String name)
	{
		text.setText(name);
		image.setVisibility(View.GONE);
		progress.setVisibility(View.VISIBLE);
		if(!name.equals(this.name) 
			&amp;&amp; context instanceof FragmentActivity)
		{
			bundle.putString(&quot;name&quot;, name);
			((FragmentActivity)context)
				.getSupportLoaderManager()
				.restartLoader(loaderId, bundle, this);
			Log.d(TAG, &quot;Restarting loader: &quot; + 
				loaderId + &quot; : &quot; + name);
		}
	}

}
</pre>
<p>The first thing to note is that this class implements our <em>LoaderCallbacks</em> interface, so this will handle the work which needs to be performed to set the <em>Loader</em> running, and also update the UI components (which needs to be performed on the UI thread) once the <em>Loader</em>&#8216; background operation is complete.</p>
<p>The entry point is the <code>setName()</code> method. This is called from our <code>getView()</code>, so needs to be really efficient. It sets the text in our <em>TextView</em, show the <em>ProgressBar</em>, hide the <em>ImageView</em>, and then restart the <em>Loader</em> (which will create it, if necessary). It is worth noting that we try and keep object creation to an absolute minimum &#8211; as these are expensive operations &#8211; so we reuse the <em>Loader</em> wherever possible, and also reuse the <em>Bundle</em> object that we use to pass parameters to our <em>Loader</em>.</p>
<p>The final component is the <em>Loader</em> implementation itself:</p>
<pre class="brush: java; title: ; notranslate">
public class ArrayAdapterImageLoader 
	extends AsyncTaskLoader&lt;Bitmap&gt;
{
	private static final String TAG = 
		ArrayAdapterImageFragment.TAG;

	private static String density = null;

	private final String name;
	private boolean cancelled = false;

	public ArrayAdapterImageLoader(Context context, 
		String name)
	{
		super(context);
		this.name = name;
		if (density == null)
		{
			DisplayMetrics dm = 
				context.getResources().getDisplayMetrics();
			switch (dm.densityDpi)
			{
			case DisplayMetrics.DENSITY_LOW:
				density = &quot;ldpi&quot;;
				break;
			case DisplayMetrics.DENSITY_MEDIUM:
				density = &quot;mdpi&quot;;
				break;
			case DisplayMetrics.DENSITY_HIGH:
				density = &quot;hdpi&quot;;
				break;
			case DisplayMetrics.DENSITY_XHIGH:
				density = &quot;xhdpi&quot;;
				break;
			default:
				density = &quot;mdpi&quot;;
				break;
			}
		}
	}

	@Override
	public Bitmap loadInBackground()
	{
		URL url = null;
		Bitmap bitmap = null;
		HttpURLConnection http = null;
		try
		{
			url = new URL(getContext().getString(
				R.string.image_base_url, density, name));
			URLConnection conn = url.openConnection();
			if(conn instanceof HttpURLConnection)
			{
				http = (HttpURLConnection)conn;
				if(http.getResponseCode() == 
						HttpURLConnection.HTTP_OK 
					&amp;&amp; http.getContentType()
						.startsWith(&quot;image&quot;))
				{
					bitmap = BitmapFactory.decodeStream(
						http.getInputStream());
				}
			}
		}
		catch (Exception e)
		{
			Log.e(TAG, &quot;Error loading image&quot;, e);
		}
		finally
		{
			if(http != null)
			{
				http.disconnect();
			}
		}
		return cancelled ? null : bitmap;
	}
	
	@Override
	protected void onStartLoading()
	{
		super.onStartLoading();
		forceLoad();
	}
	
	@Override
	protected void onAbandon()
	{
		super.onAbandon();
		cancelled = true;
	}

}
</pre>
<p>What we&#8217;re doing here is determining the device pixel density so that we can get the correct image for our device. Note that only ldpi, mdpi, hdpi, and xhdpi versions of these images are provided on AOSP, so we only support these.</p>
<p>We then load the image from github by constructing the URL, loading the content and decoding it to create a <em>Bitmap</em> object (all rather expensive operations) within the <code>loadInBackground()</code> method.</p>
<p>If we run this we see he following:</p>
<p><a href="http://blog.stylingandroid.com/wp-content/uploads/2013/04/Images.png"><img src="http://blog.stylingandroid.com/wp-content/uploads/2013/04/Images.png" alt="Images" width="360" height="565" class="alignnone size-full wp-image-1757" /></a></p>
<p>However, you&#8217;ll have to try it out for yourself to see how the <em>ListView</em> scrolling stays smooth.</p>
<p>It is worth pointing out that the code in this article is designed to demonstrate how to keep your <em>ListView</em> scrolling smooth, and your UI responsive, so I have tried to keep the code as simple as possible so that it is clear that the expensive operations are performed in the correct place. However, there are some omissions which should be addressed if you were to attempt to use it in a real app:</p>
<ol>
<li>The handling of pixel densities for which assets do not exist is a little crude (i.e. xxhdpi defaults to mdpi)</li>
<li>There is no handling of network resources that are not found or not available</li>
<li>There is no detection of whether a network connection is available</li>
<li>Currently the images get pulled from the network each time they are loaded. An image cache would improve the user experience considerably</li>
</ol>
<p>In the next article we&#8217;ll look at binding a ListView to a SQLite database.</p>
<p>The source code for this article is available <a href="https://bitbucket.org/StylingAndroid/adapters/src/527044414ef8128a05738971c055e483db1355c7/?at=Part4">here</a>.</p>
<p style='text-align:left'>&copy; 2013, <a href='http://blog.stylingandroid.com'>Mark Allison</a>. All rights reserved. This article originally appeared on <a href="http://blog.stylingandroid.com">Styling Android</a>.<br/><br/>Portions of this page are modifications based on work created and shared by Google and used according to terms described in the Creative Commons 3.0 Attribution License</p>
<p><a class="a2a_button_delicious" href="http://www.addtoany.com/add_to/delicious?linkurl=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1737&amp;linkname=Adapters%20%E2%80%93%20Part%204" title="Delicious" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/delicious.png" width="16" height="16" alt="Delicious"/></a><a class="a2a_button_stumbleupon" href="http://www.addtoany.com/add_to/stumbleupon?linkurl=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1737&amp;linkname=Adapters%20%E2%80%93%20Part%204" title="StumbleUpon" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/stumbleupon.png" width="16" height="16" alt="StumbleUpon"/></a><a class="a2a_button_reddit" href="http://www.addtoany.com/add_to/reddit?linkurl=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1737&amp;linkname=Adapters%20%E2%80%93%20Part%204" title="Reddit" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/reddit.png" width="16" height="16" alt="Reddit"/></a><a class="a2a_button_digg" href="http://www.addtoany.com/add_to/digg?linkurl=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1737&amp;linkname=Adapters%20%E2%80%93%20Part%204" title="Digg" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/digg.png" width="16" height="16" alt="Digg"/></a><a href="javascript:if(document.all){window.external.AddFavorite('http://blog.stylingandroid.com/archives/1737','Adapters%20&#8211;%20Part%204')}else{var%20b=a2a_config.localize.BookmarkInstructions%20||%20'Press%20Ctrl+D%20to%20bookmark%20this%20page';alert(a2a_config.localize.BookmarkInstructions)}" title="Bookmark/Favorites" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/bookmark.png" width="16" height="16" alt="Bookmark/Favorites"/></a><a class="a2a_button_twitter_tweet addtoany_special_service" data-count="none" data-url="http://blog.stylingandroid.com/archives/1737" data-text="Adapters &#8211; Part 4"></a><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1737&amp;title=Adapters%20%E2%80%93%20Part%204" id="wpa2a_16"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share"/></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/StylingAndroid?a=aojVt6VhnTU:3n-mBf39Tpk:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/StylingAndroid?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/StylingAndroid/~4/aojVt6VhnTU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.stylingandroid.com/archives/1737/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/</creativeCommons:license>
	<feedburner:origLink>http://blog.stylingandroid.com/archives/1737</feedburner:origLink></item>
		<item>
		<title>Adapters – Part 3</title>
		<link>http://feedproxy.google.com/~r/StylingAndroid/~3/1TZpYnNJ_30/1710</link>
		<comments>http://blog.stylingandroid.com/archives/1710#comments</comments>
		<pubDate>Fri, 19 Apr 2013 10:00:51 +0000</pubDate>
		<dc:creator>Mark Allison</dc:creator>
				<category><![CDATA[Adapter]]></category>
		<category><![CDATA[ArrayAdapter]]></category>
		<category><![CDATA[androiddev]]></category>

		<guid isPermaLink="false">http://blog.stylingandroid.com/?p=1710</guid>
		<description><![CDATA[In the previous article we got an ArrayAdapter and a slightly more complex SimpleAdapter working, but suggested that we could also achieve the same result as the SimpleAdapter using an ArrayAdapter. In this article we&#8217;ll look at how to do this, but also explore some performance issues which we need to be aware of when [...]]]></description>
				<content:encoded><![CDATA[<p>In the <a href="/archives/1702" title="Adapters – Part 2">previous article</a> we got an <em>ArrayAdapter</em> and a slightly more complex <em>SimpleAdapter</em> working, but suggested that we could also achieve the same result as the <em>SimpleAdapter</em> using an <em>ArrayAdapter</em>. In this article we&#8217;ll look at how to do this, but also explore some performance issues which we need to be aware of when working with <em>Adapters</em>.<br />
<span id="more-1710"></span></p>
<p>In principle, replacing the <em>SimpleAdapter</em> with an <em>ArrayAdapter</em> is relatively simple. We create a class to hold the data for each item:</p>
<pre class="brush: java; title: ; notranslate">
private static class Item
{
	public final String line1;
	public final String line2;
		
	public Item(String line1, String line2)
	{
		this.line1 = line1;
		this.line2 = line2;
	}
}
</pre>
<p>We can then use an <em>ArrayAdapter<Item></em> instead of the <em>ArrayAdapter<String></em> that we used previously. The only problem here is that ArrayAdapter has no implicit knowledge of our Item class, so we need to perform the actual data binding ourselves. We do this by creating our own <em>ArrayAdapter</em> implementation and overriding the <code>getView()</code> method:</p>
<pre class="brush: java; title: ; notranslate">
public class ArrayAdapterObjectFragment 
	extends ListFragment
{
	private static final List&lt;Item&gt; items = 
		new ArrayList&lt;Item&gt;();

	private static class Item
	{
		public final String line1;
		public final String line2;
		
		public Item(String line1, String line2)
		{
			this.line1 = line1;
			this.line2 = line2;
		}
	}
		
	private class ItemAdapter extends ArrayAdapter&lt;Item&gt;
	{

		public ItemAdapter(Context context)
		{
			super(context, 
				android.R.layout.simple_list_item_2, 
				items);
		}
		
		@Override
		public View getView(int position, 
			View convertView, 
			ViewGroup parent)
		{
			/* This implementation is very 
			 * inefficient and should not be used
			 * as is.
			 */
			Item item = getItem(position);
			View view = LayoutInflater.from(
				getContext()).inflate(
					android.R.layout.simple_list_item_2, 
					parent, false);
			((TextView)view.findViewById(android.R.id.text1))
				.setText(item.line1);
			((TextView)view.findViewById(android.R.id.text2))
				.setText(item.line2);
			return view;
		}
	}
	
	static
	{
		items.add(new Item(&quot;Title One&quot;, &quot;Subtitle One&quot;));
		items.add(new Item(&quot;Title Two&quot;, &quot;Subtitle Two&quot;));
		items.add(new Item(&quot;Title Three&quot;, &quot;Subtitle Three&quot;));
		items.add(new Item(&quot;Title Four&quot;, &quot;Subtitle Four&quot;));
		items.add(new Item(&quot;Title Five&quot;, &quot;Subtitle Five&quot;));
	}
	
	@Override
	public View onCreateView(LayoutInflater inflater, 
		ViewGroup container, Bundle savedInstanceState)
	{
		return inflater.inflate(R.layout.listview, 
			container, false);
	}
	
	@Override
	public void onActivityCreated(Bundle savedInstanceState)
	{
		super.onActivityCreated(savedInstanceState);
		ListAdapter adapter = new ItemAdapter(getActivity());
		setListAdapter(adapter);
	}
}
</pre>
<p>Hopefully this should be fairly understandable, and it does precisely what we require:</p>
<p><a href="http://blog.stylingandroid.com/wp-content/uploads/2013/04/ArrayAdapterObject.png"><img src="http://blog.stylingandroid.com/wp-content/uploads/2013/04/ArrayAdapterObject.png" alt="ArrayAdapterObject" width="360" height="569" class="alignnone size-full wp-image-1717" /></a></p>
<p>However, there is a problem with this, as you may be able to guess from the comment in the <code>getView()</code> implementation. To understand the problem, we have to consider how <em>ListView</em> works, particularly when we are scrolling through a list. Each time an item in the <em>ListView</em> comes in to view when scrolling, <code>getView()</code> will be called. Our <code>getView()</code> implementation is performing two quite expensive operations: layout inflation, and finding views within the layout. </p>
<p>Layout inflation is expensive because it requires the parsing of XML and the creation of a number of object instances representing the controls within the XML.</p>
<p>Finding views is expensive because it requires traversal of the view hierarchy in order to find the control that we&#8217;re interested in.</p>
<p>The net result of having these expensive operations within our <code>getView()</code> method is that the scrolling of our <em>ListView</em> will not be smooth. This will be compounded because the items going out of view will need to be garbage collected by the VM in order to free up the memory that will be necessary to create new objects during view inflation, and garbage collection is also an expensive operation.</p>
<p>Fortunately the Adapter framework gives us a mechanism for recycling our item layouts. When items go out of view, their layouts will be recycled and they will be passed in to our getView() method in the <code>convertView</code> argument. So we can perform a null check on this, and only inflate the view if we have to:</p>
<pre class="brush: java; title: ; notranslate">
@Override
public View getView(int position, 
	View convertView, 
	ViewGroup parent)
{
	/* This implementation is better
	 * than before but still 
	 * inefficient and should not be used
	 * as is.
	 */
	Item item = getItem(position);
	View view = convertView;
        if(view == null)
	{
		LayoutInflater.from(
			getContext()).inflate(
			android.R.layout.simple_list_item_2, 
			parent, false);
	}
	((TextView)view.findViewById(android.R.id.text1))
		.setText(item.line1);
	((TextView)view.findViewById(android.R.id.text2))
		.setText(item.line2);
	return view;
}
</pre>
<p>This will optimise performance quite considerably but we&#8217;re still performing these expensive <code>findViewById()</code> calls each time  <code>getView()</code> is called. Now that we are re-using our layouts, the actual <em>TextView</em> objects that we&#8217;re binding to are also being reused so we can cache them. We can do this by using a View Holder pattern where we create a new object containing references to our controls and attach this to the parent layout:</p>
<pre class="brush: java; title: ; notranslate">
public static class ViewHolder 
{
	public final TextView text1;
	public final TextView text2;
		
	public ViewHolder(TextView text1, TextView text2)
	{
		this.text1 = text1;
		this.text2 = text2;
	}
}

@Override
public View getView(int position, 
	View convertView, 
	ViewGroup parent)
{
	View view = convertView;
	ViewHolder holder = null;
	if(view == null)
	{
		view = LayoutInflater.from(
			getContext()).inflate(
				android.R.layout.simple_list_item_2, 
				parent, false);
		TextView text1 = 
			(TextView)view.findViewById(android.R.id.text1);
		TextView text2 = 
			(TextView)view.findViewById(android.R.id.text2);
		view.setTag(new ViewHolder(text1, text2));
	}
	if(holder == null &amp;&amp; view != null)
	{
		Object tag = view.getTag();
		if(tag instanceof ViewHolder)
		{
			holder = (ViewHolder)tag;
		}
	}
	Item item = getItem(position);
	if(item != null &amp;&amp; holder != null)
	{
		holder.text1.setText(item.line1);
		holder.text2.setText(item.line2);
	}
	return view;
}
</pre>
<p>Now we only perform the layout inflation and <code>findViewById()</code> calls when we absolutely have to, thus keeping the code in <code>getView()</code> much more efficient. You should always avoid expensive calls such as filesystem and network operations in the <code>getView()</code> method.</p>
<p>In the next article we&#8217;ll have a look at how we can bind images to an <em>ImageView</em> within our item layout without making expensive calls in <code>getView()</code>.</p>
<p>The source code for this article is available <a href="https://bitbucket.org/StylingAndroid/adapters/src/09a3797d6f9d22f33fdfe647668d04e55cd0c74f/?at=Part3">here</a>.</p>
<p style='text-align:left'>&copy; 2013, <a href='http://blog.stylingandroid.com'>Mark Allison</a>. All rights reserved. This article originally appeared on <a href="http://blog.stylingandroid.com">Styling Android</a>.<br/><br/>Portions of this page are modifications based on work created and shared by Google and used according to terms described in the Creative Commons 3.0 Attribution License</p>
<p><a class="a2a_button_delicious" href="http://www.addtoany.com/add_to/delicious?linkurl=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1710&amp;linkname=Adapters%20%E2%80%93%20Part%203" title="Delicious" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/delicious.png" width="16" height="16" alt="Delicious"/></a><a class="a2a_button_stumbleupon" href="http://www.addtoany.com/add_to/stumbleupon?linkurl=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1710&amp;linkname=Adapters%20%E2%80%93%20Part%203" title="StumbleUpon" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/stumbleupon.png" width="16" height="16" alt="StumbleUpon"/></a><a class="a2a_button_reddit" href="http://www.addtoany.com/add_to/reddit?linkurl=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1710&amp;linkname=Adapters%20%E2%80%93%20Part%203" title="Reddit" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/reddit.png" width="16" height="16" alt="Reddit"/></a><a class="a2a_button_digg" href="http://www.addtoany.com/add_to/digg?linkurl=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1710&amp;linkname=Adapters%20%E2%80%93%20Part%203" title="Digg" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/digg.png" width="16" height="16" alt="Digg"/></a><a href="javascript:if(document.all){window.external.AddFavorite('http://blog.stylingandroid.com/archives/1710','Adapters%20&#8211;%20Part%203')}else{var%20b=a2a_config.localize.BookmarkInstructions%20||%20'Press%20Ctrl+D%20to%20bookmark%20this%20page';alert(a2a_config.localize.BookmarkInstructions)}" title="Bookmark/Favorites" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/bookmark.png" width="16" height="16" alt="Bookmark/Favorites"/></a><a class="a2a_button_twitter_tweet addtoany_special_service" data-count="none" data-url="http://blog.stylingandroid.com/archives/1710" data-text="Adapters &#8211; Part 3"></a><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1710&amp;title=Adapters%20%E2%80%93%20Part%203" id="wpa2a_20"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share"/></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/StylingAndroid?a=1TZpYnNJ_30:w6iD8HLzKTQ:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/StylingAndroid?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/StylingAndroid/~4/1TZpYnNJ_30" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.stylingandroid.com/archives/1710/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/</creativeCommons:license>
	<feedburner:origLink>http://blog.stylingandroid.com/archives/1710</feedburner:origLink></item>
		<item>
		<title>Adapters – Part 2</title>
		<link>http://feedproxy.google.com/~r/StylingAndroid/~3/FvETwL5rs54/1702</link>
		<comments>http://blog.stylingandroid.com/archives/1702#comments</comments>
		<pubDate>Fri, 12 Apr 2013 10:00:43 +0000</pubDate>
		<dc:creator>Mark Allison</dc:creator>
				<category><![CDATA[Adapter]]></category>
		<category><![CDATA[ArrayAdapter]]></category>
		<category><![CDATA[SimpleAdapter]]></category>
		<category><![CDATA[androiddev]]></category>

		<guid isPermaLink="false">http://blog.stylingandroid.com/?p=1702</guid>
		<description><![CDATA[In the previous article we began our look at Adapters by connecting up the List Navigation Spinner in our ActionBar. In this article we&#8217;ll look at applying an Adapter to a ListView. Previously we created a fragment named ListViewFragment which is currently empty, save for inflating a simple layout containing a single ListView. To populate [...]]]></description>
				<content:encoded><![CDATA[<p>In the <a href="/archives/1679" title="Adapters – Part 1">previous article</a> we began our look at Adapters by connecting up the List Navigation <em>Spinner</em> in our <em>ActionBar</em>. In this article we&#8217;ll look at applying an <em>Adapter</em> to a ListView.<br />
<span id="more-1702"></span></p>
<p>Previously we created a fragment named <em>ListViewFragment</em> which is currently empty, save for inflating a simple layout containing a single ListView. To populate this <em>ListView</em> we use an <em>Adapter</em>. Let&#8217;s start by doing something really simple, and very similar to how we connected up our List Navigation <em>Spinner</em>: Use an <em>ArrayAdapter</em>:</p>
<pre class="brush: java; title: ; notranslate">
public class ListViewFragment extends ListFragment
{
	private static final String[] items = new String[] {
		&quot;One&quot;, &quot;Two&quot;, &quot;Three&quot;, &quot;Four&quot;, &quot;Five&quot;
	};
	
	@Override
	public View onCreateView(LayoutInflater inflater, 
		ViewGroup container, Bundle savedInstanceState)
	{
		return inflater.inflate(R.layout.listview, 
			container, false);
	}
	
	@Override
	public void onActivityCreated(Bundle savedInstanceState)
	{
		super.onActivityCreated(savedInstanceState);
		ListAdapter adapter = new ArrayAdapter&lt;String&gt;(
			getActivity(), 
			android.R.layout.simple_list_item_1, items);
		setListAdapter(adapter);
	}
}
</pre>
<p>We&#8217;ve used a static String array, and a different layout, but essentially this is exactly the same as we did with the Navigation <em>Spinner</em>. This demonstrates how the Adapter is completely decoupled from the control that it is binds to. ArrayAdapter extends <em>BaseAdapter</em> which implements both <em>ListAdapter</em> and <em>SpinnerAdapter</em> interfaces which means that it can be used to populate either of these controls.</p>
<p>This gives us the following:</p>
<p><a href="http://blog.stylingandroid.com/wp-content/uploads/2013/04/ArrayAdapterString.png"><img src="http://blog.stylingandroid.com/wp-content/uploads/2013/04/ArrayAdapterString.png" alt="ArrayAdapterString" width="360" height="568" class="alignnone size-full wp-image-1704" /></a></p>
<p>So what if we want to do something slightly more complex. If we want to use <code>android.R.layout.simple_list_item_2</code> instead of the previous layout, it includes two TextView objects which we need to bind to. Using the ArrayAdapter as before will not work because we now have to bind two controls, so we&#8217;ll use a SimpleAdapter instead:</p>
<pre class="brush: java; title: ; notranslate">
public class SimpleAdapterFragment extends ListFragment
{
	private static final List&lt;Map&lt;String,String&gt;&gt; items = 
		new ArrayList&lt;Map&lt;String,String&gt;&gt;();
	private static final String[] keys = 
		{ &quot;line1&quot;, &quot;line2&quot; };
	private static final int[] controlIds = 
		{ android.R.id.text1, 
		android.R.id.text2 };
	
	static
	{
		Map&lt;String, String&gt; map = 
			new HashMap&lt;String, String&gt;();
		map.put(&quot;line1&quot;, &quot;Title One&quot;);
		map.put(&quot;line2&quot;, &quot;Subtitle One&quot;);
		items.add(map);
		map = new HashMap&lt;String, String&gt;();
		map.put(&quot;line1&quot;, &quot;Title Two&quot;);
		map.put(&quot;line2&quot;, &quot;Subtitle Two&quot;);
		items.add(map);
		map = new HashMap&lt;String, String&gt;();
		map.put(&quot;line1&quot;, &quot;Title Three&quot;);
		map.put(&quot;line2&quot;, &quot;Subtitle Three&quot;);
		items.add(map);
		map = new HashMap&lt;String, String&gt;();
		map.put(&quot;line1&quot;, &quot;Title Four&quot;);
		map.put(&quot;line2&quot;, &quot;Subtitle Four&quot;);
		items.add(map);
		map = new HashMap&lt;String, String&gt;();
		map.put(&quot;line1&quot;, &quot;Title Five&quot;);
		map.put(&quot;line2&quot;, &quot;Subtitle Five&quot;);
		items.add(map);
	}
	
	@Override
	public View onCreateView(LayoutInflater inflater, 
		ViewGroup container, 
		Bundle savedInstanceState)
	{
		return inflater.inflate(R.layout.listview, 
			container, false);
	}
	
	@Override
	public void onActivityCreated(Bundle savedInstanceState)
	{
		super.onActivityCreated(savedInstanceState);
		ListAdapter adapter = new SimpleAdapter(
			getActivity(), 
			items, 
			android.R.layout.simple_list_item_2, 
			keys, 
			controlIds );
		setListAdapter(adapter);
	}
}
</pre>
<p>Despite it&#8217;s name, SimpleAdapter is actually a little more complex than the very basic <code>ArrayAdapter<String></code> implementation that we used before. However, it is actually a pretty simple way of binding multiple controls within each item in our ListView.</p>
<p>It works by storing the data that we want to bind to the control within a <em>List</em> of <em>Maps</em>. Each item in the List represents a single item in the <em>ListView</em>, and the <em>Map</em> contains the values which get assigned to the different controls. The two TextViews in the layout have ids of <code>android.R.id.text1</code> and <code>android.R.id.text2</code> and we need to map these values to the controls. This is done using two arrays, <code>keys</code> contains a list of keys used in the <em>Map</em>, and <code>controlIds</code> contains a list of control ids. <em>SimpleAdapter</em> will bind the controls to their respective <em>Map</em> values: </p>
<pre class="brush: java; title: ; notranslate">
controlId[i].setText(map.get(keys[i]));
</pre>
<p>This gives us the following:</p>
<p><a href="http://blog.stylingandroid.com/wp-content/uploads/2013/04/SimpleAdapter.png"><img src="http://blog.stylingandroid.com/wp-content/uploads/2013/04/SimpleAdapter.png" alt="SimpleAdapter" width="360" height="586" class="alignnone size-full wp-image-1707" /></a></p>
<p>So we&#8217;ve seen how we can use ArrayAdapter to perform the simplest of bindings, and then SimpleAdapter to perform something very slightly more complex. Actually we can also use ArrayAdapter to perform this second kind of binding, but there are some optimisations that we need to be aware of before we do so. In the next article we&#8217;ll look at this.</p>
<p>The source code for this article is available <a href="https://bitbucket.org/StylingAndroid/adapters/src/5869409e026d06b58c6b1ab399b2b4e2eba338e6/?at=Part2">here</a>.</p>
<p style='text-align:left'>&copy; 2013, <a href='http://blog.stylingandroid.com'>Mark Allison</a>. All rights reserved. This article originally appeared on <a href="http://blog.stylingandroid.com">Styling Android</a>.<br/><br/>Portions of this page are modifications based on work created and shared by Google and used according to terms described in the Creative Commons 3.0 Attribution License</p>
<p><a class="a2a_button_delicious" href="http://www.addtoany.com/add_to/delicious?linkurl=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1702&amp;linkname=Adapters%20%E2%80%93%20Part%202" title="Delicious" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/delicious.png" width="16" height="16" alt="Delicious"/></a><a class="a2a_button_stumbleupon" href="http://www.addtoany.com/add_to/stumbleupon?linkurl=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1702&amp;linkname=Adapters%20%E2%80%93%20Part%202" title="StumbleUpon" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/stumbleupon.png" width="16" height="16" alt="StumbleUpon"/></a><a class="a2a_button_reddit" href="http://www.addtoany.com/add_to/reddit?linkurl=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1702&amp;linkname=Adapters%20%E2%80%93%20Part%202" title="Reddit" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/reddit.png" width="16" height="16" alt="Reddit"/></a><a class="a2a_button_digg" href="http://www.addtoany.com/add_to/digg?linkurl=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1702&amp;linkname=Adapters%20%E2%80%93%20Part%202" title="Digg" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/digg.png" width="16" height="16" alt="Digg"/></a><a href="javascript:if(document.all){window.external.AddFavorite('http://blog.stylingandroid.com/archives/1702','Adapters%20&#8211;%20Part%202')}else{var%20b=a2a_config.localize.BookmarkInstructions%20||%20'Press%20Ctrl+D%20to%20bookmark%20this%20page';alert(a2a_config.localize.BookmarkInstructions)}" title="Bookmark/Favorites" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/bookmark.png" width="16" height="16" alt="Bookmark/Favorites"/></a><a class="a2a_button_twitter_tweet addtoany_special_service" data-count="none" data-url="http://blog.stylingandroid.com/archives/1702" data-text="Adapters &#8211; Part 2"></a><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1702&amp;title=Adapters%20%E2%80%93%20Part%202" id="wpa2a_24"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share"/></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/StylingAndroid?a=FvETwL5rs54:bJvyc54Nde4:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/StylingAndroid?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/StylingAndroid/~4/FvETwL5rs54" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.stylingandroid.com/archives/1702/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/</creativeCommons:license>
	<feedburner:origLink>http://blog.stylingandroid.com/archives/1702</feedburner:origLink></item>
		<item>
		<title>Adapters – Part 1</title>
		<link>http://feedproxy.google.com/~r/StylingAndroid/~3/eIemFLOStCQ/1679</link>
		<comments>http://blog.stylingandroid.com/archives/1679#comments</comments>
		<pubDate>Fri, 05 Apr 2013 10:00:23 +0000</pubDate>
		<dc:creator>Mark Allison</dc:creator>
				<category><![CDATA[Adapter]]></category>
		<category><![CDATA[ArrayAdapter]]></category>

		<guid isPermaLink="false">http://blog.stylingandroid.com/?p=1679</guid>
		<description><![CDATA[In the past on Styling Android we have covered a variety of topics which make use of Adapters. In the series&#8217; on ListView, ViewPager and ActionBar (to name but a few) we&#8217;ve used Adapters but kept the Adapter implementation really simple so that we may focus on the subject in question. However, on a few [...]]]></description>
				<content:encoded><![CDATA[<p>In the past on Styling Android we have covered a variety of topics which make use of <em>Adapter</em>s. In the series&#8217; on <a href="/archives/605">ListView</a>, <a href="/archives/537">ViewPager</a> and <a href="/archives/1144">ActionBar</a> (to name but a few) we&#8217;ve used <em>Adapter</em>s but kept the <em>Adapter</em> implementation really simple so that we may focus on the subject in question. However, on a few of these articles there are comments asking how to do different behaviours which actually require changes to the <em>Adapter</em> being used rather than the feature being covered in that particular article. In this series we&#8217;ll have a detailed look at <em>Adapters</em>, and the power and versatility that they provide us.<br />
<span id="more-1679"></span></p>
<p>To understand what <em>Adapters</em> do, let&#8217;s think about a simple <em>ListView</em>. The <em>ListView</em> itself is a container for a number of items, and the data for these items may come from vastly different sources. For example one <em>ListView</em> may contain a list of static items which never change throughout the entire lifespan of the app, whereas another <em>ListView</em> may contain a list of items from a SQLite database. In order to keep <em>ListView</em> agnostic about the source of the data for its items an abstraction layer exists, and this is the <em>Adapter</em>. So the role of the <em>Adapter</em> is to keep the control (in this case the <em>ListView</em>) decoupled from the data that it requires to create its child elements.</p>
<p>Part of the flexibility of the Adapter architecture is that polymorphism is used to provide abstraction from the data source. Up until now we&#8217;ve only referred to <em>Adapter</em>s in that abstract form, but in practise we&#8217;ll need to use a concrete <em>Adapter</em> implementation depending on the nature of the data and where it is sourced from. As far as our <em>ListView</em> is concerned the <em>Adapter</em> is simply a <em>ListAdapter</em>, but we can actually provide any concrete <em>Adapter</em> implemenation that we like provided it implements the <em>ListAdapter</em> interface.</p>
<p>An example would help here. We&#8217;ll put together a simple app which will allow us to demonstrate various Adapter implementations and uses,  and we&#8217;ll use List Navigation in the ActionBar to enable us to switch between different fragments. We&#8217;re going to focus purely on the Adapter here, but if you require further information on List Navigation then take a look <a href="/archives/1173">here</a>.</p>
<p>Arguably the simplest for of Adapter that we can use is one which maps to simple, static values:</p>
<pre class="brush: java; highlight: [13,14,15]; title: ; notranslate">
@Override
protected void onCreate(Bundle savedInstanceState)
{
	super.onCreate(savedInstanceState);
	setContentView(R.layout.activity_main);
	final String[] names = getResources()
		.getStringArray(R.array.nav_names);
	final String[] classes = getResources()
		.getStringArray(R.array.nav_classes);
	getActionBar().setNavigationMode(
		ActionBar.NAVIGATION_MODE_LIST);

	ArrayAdapter&lt;String&gt; adapter = 
		new ArrayAdapter&lt;String&gt;(
			getActionBar().getThemedContext(), 
			android.R.layout.simple_spinner_item, names);
	adapter.setDropDownViewResource(
		android.R.layout.simple_spinner_dropdown_item);

	getActionBar().setListNavigationCallbacks(adapter, 
		new OnNavigationListener()
	{
		@Override
		public boolean onNavigationItemSelected(
			int itemPosition, long itemId)
		{
			FragmentTransaction tx = 
				getSupportFragmentManager()
				.beginTransaction();
			tx.replace(R.id.main, 
				Fragment.instantiate(MainActivity.this, 
					classes[itemPosition]));
			tx.commit();
			return true;
		}
	});
}
</pre>
<p>All we are doing here is loading a <em>String</em> array from resources, and we build an <em>ArrayAdapter</em> from that. </p>
<p><em>ArrayAdapter</em> is a generic class which provides an Adapter based upon a simple array of objects. In our case we&#8217;re wrapping a String array which we obtain from resources. The constructor that we&#8217;re using takes 3 parameters: The context in which the Adapter will be used, a layout to use (in this case we&#8217;re using a standard layout from the OS), and the array of objects to use.</p>
<p>What goes on under the bonnet is that <em>ArrayAdapter</em> will create a new layout (actually this is not strictly true, but we&#8217;ll return to this in a later article) for each item in the list objects, each layout will be inflated from the resource ID that we provided. It will then look for a <em>TextView</em> with the id &#8220;android:id/text1&#8243; (which exists in the layout &#8211; see <a href="https://github.com/android/platform_frameworks_base/blob/master/core/res/res/layout/simple_spinner_item.xml" target="_blank">here</a> for proof) and set the text value of that text view to the value of the item in the list. In our case the items are all <em>String</em> values, but for other object classes <em>ArrayAdapter</em> will use the value returned by the <code>toString()</code> method.</p>
<p>To get this to work add a couple of String arrays to our resources (and define a class names ListViewFragment, which you can see in the source, but which we won&#8217;t discuss here):</p>
<pre class="brush: xml; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;resources&gt;

    &lt;string-array name=&quot;nav_names&quot;&gt;
        &lt;item&gt;ListView&lt;/item&gt;
    &lt;/string-array&gt;


    &lt;string-array name=&quot;nav_classes&quot;&gt;
        &lt;item&gt;com.stylingandroid.adapters.ListViewFragment&lt;/item&gt;
    &lt;/string-array&gt;

&lt;/resources&gt;
</pre>
<p>If we run this we can see that our navigation list gets populated accordingly:</p>
<p><a href="http://blog.stylingandroid.com/wp-content/uploads/2013/03/simple-arrayadapter.png"><img src="http://blog.stylingandroid.com/wp-content/uploads/2013/03/simple-arrayadapter.png" alt="simple-arrayadapter" width="360" height="120" class="alignnone size-full wp-image-1683" /></a></p>
<p>Update: As per Jake Wharton&#8217;s comments, the source code has been updated accordingly. Thanks, Jake!</p>
<p>In the next article we&#8217;ll take this a little further and show some alternative approaches that we can use. The source code for this article is available <a href="https://bitbucket.org/StylingAndroid/adapters/src/5d976e34853d?at=Part1">here</a>. </p>
<p style='text-align:left'>&copy; 2013, <a href='http://blog.stylingandroid.com'>Mark Allison</a>. All rights reserved. This article originally appeared on <a href="http://blog.stylingandroid.com">Styling Android</a>.<br/><br/>Portions of this page are modifications based on work created and shared by Google and used according to terms described in the Creative Commons 3.0 Attribution License</p>
<p><a class="a2a_button_delicious" href="http://www.addtoany.com/add_to/delicious?linkurl=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1679&amp;linkname=Adapters%20%E2%80%93%20Part%201" title="Delicious" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/delicious.png" width="16" height="16" alt="Delicious"/></a><a class="a2a_button_stumbleupon" href="http://www.addtoany.com/add_to/stumbleupon?linkurl=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1679&amp;linkname=Adapters%20%E2%80%93%20Part%201" title="StumbleUpon" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/stumbleupon.png" width="16" height="16" alt="StumbleUpon"/></a><a class="a2a_button_reddit" href="http://www.addtoany.com/add_to/reddit?linkurl=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1679&amp;linkname=Adapters%20%E2%80%93%20Part%201" title="Reddit" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/reddit.png" width="16" height="16" alt="Reddit"/></a><a class="a2a_button_digg" href="http://www.addtoany.com/add_to/digg?linkurl=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1679&amp;linkname=Adapters%20%E2%80%93%20Part%201" title="Digg" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/digg.png" width="16" height="16" alt="Digg"/></a><a href="javascript:if(document.all){window.external.AddFavorite('http://blog.stylingandroid.com/archives/1679','Adapters%20&#8211;%20Part%201')}else{var%20b=a2a_config.localize.BookmarkInstructions%20||%20'Press%20Ctrl+D%20to%20bookmark%20this%20page';alert(a2a_config.localize.BookmarkInstructions)}" title="Bookmark/Favorites" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/bookmark.png" width="16" height="16" alt="Bookmark/Favorites"/></a><a class="a2a_button_twitter_tweet addtoany_special_service" data-count="none" data-url="http://blog.stylingandroid.com/archives/1679" data-text="Adapters &#8211; Part 1"></a><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1679&amp;title=Adapters%20%E2%80%93%20Part%201" id="wpa2a_28"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share"/></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/StylingAndroid?a=eIemFLOStCQ:InZpg9MXcyI:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/StylingAndroid?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/StylingAndroid/~4/eIemFLOStCQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.stylingandroid.com/archives/1679/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/</creativeCommons:license>
	<feedburner:origLink>http://blog.stylingandroid.com/archives/1679</feedburner:origLink></item>
		<item>
		<title>Gradient Text</title>
		<link>http://feedproxy.google.com/~r/StylingAndroid/~3/EzqP_OfY1I4/1671</link>
		<comments>http://blog.stylingandroid.com/archives/1671#comments</comments>
		<pubDate>Fri, 29 Mar 2013 10:00:15 +0000</pubDate>
		<dc:creator>Mark Allison</dc:creator>
				<category><![CDATA[Canvas]]></category>
		<category><![CDATA[Gradient]]></category>
		<category><![CDATA[Shader]]></category>
		<category><![CDATA[Text]]></category>
		<category><![CDATA[androiddev]]></category>

		<guid isPermaLink="false">http://blog.stylingandroid.com/?p=1671</guid>
		<description><![CDATA[Recently there was a comment on the article on Text Shadows asking how to fill text with a gradient. In this article we&#8217;ll look at a simple technique for doing precisely that. Creating text filled with a gradient is actually really easy, although it&#8217;s not immediately obvious how to do it in the same was [...]]]></description>
				<content:encoded><![CDATA[<p>Recently there was a comment on the article on <a href="archives/378" title="Text Shadows">Text Shadows</a> asking how to fill text with a gradient. In this article we&#8217;ll look at a simple technique for doing precisely that.<br />
<span id="more-1671"></span></p>
<p>Creating text filled with a gradient is actually really easy, although it&#8217;s not immediately obvious how to do it in the same was as simply changing the text colour. The trick is to use a <a href="http://developer.android.com/reference/android/graphics/Shader.html" target="_blank">Shader</a>, or more specifically a <a href="http://developer.android.com/reference/android/graphics/LinearGradient.html" target="_blank">LinearGradient</a> (which extends <em>Shader</em>), to do all of the work for us. </p>
<p>The constructor for <em>LinearGradient</em> that we&#8217;ll use takes seven arguments, although there is also a more complex form which allows for multiple colour steps to be defined. The first four of these represent the start x &#038; y and end x &#038; y coordinates of the line along which the gradient will be drawn (this effectively controls the direction of the gradient). The next two arguments represent the start and end colours of the gradient, and the final argument dictates how areas outside of the rectangle defined in the first four arguments will be drawn.</p>
<p>So how do we go about applying this? In its simplest form, we can get a reference to a standard <em>TextView</em> object, and set the <em>Shader</em> on it&#8217;s <em>Paint</em> object:</p>
<pre class="brush: java; title: ; notranslate">
Shader myShader = new LinearGradient( 
    0, 0, 0, 100, 
    Color.WHITE, Color.BLACK, 
    Shader.TileMode.CLAMP );
textview.getPaint().setShader( myShader );
</pre>
<p>The TileMode that we&#8217;re using means that the colour of areas outside of the rectangle (0, 0) &#8211; (0, 100) will match the colour of the closest edge of that rectangle &#8211; i.e. extending the colour of the edges of the rectangle.</p>
<p>While this will certainly work, it does suffer from the small drawback that the gradient will need to be static dimensions which are completely detached from the size of the text within the TextView. So what if we want the dimensions of the gradient to actually match our text? We simply need to extend TextView. </p>
<p>Now the obvious thought is to extend <em>TextView</em> and simply override <code>onDraw()</code> to create a new <em>LinearGradient</em> which matches the dimensions of the textView control each time the control is drawn. However this is rather inefficient because it means instantiating a Shader object each time <em>onDraw</em> is called. Object instantiation is a rather expensive business and should be avoided at all costs in your onDraw method. If you perform object instantiation in your onDraw you&#8217;ll find that your frame rates suffer badly as a result.</p>
<p>So if we don&#8217;t do it in <em>onDraw</em>, then where should we do it? The answer is quite obvious when we think about how often we actually need to create a new <em>LinearGradient</em>: only when the size of the <em>TextView</em> changes. Therefore, the most efficient place to do this is actually in <em>onLayout</em>:</p>
<pre class="brush: java; title: ; notranslate">
public class GradientTextView extends TextView
{
    public GradientTextView( Context context )
    {
        super( context, null, -1 );
    }
    public GradientTextView( Context context, 
        AttributeSet attrs )
    {
        super( context, attrs, -1 );
    }
    public GradientTextView( Context context, 
        AttributeSet attrs, int defStyle )
    {
        super( context, attrs, defStyle );
    }

    @Override
    protected void onLayout( boolean changed, 
        int left, int top, int right, int bottom )
    {
        super.onLayout( changed, left, top, right, bottom );
        if(changed)
        {
            getPaint().setShader( new LinearGradient( 
                0, 0, 0, getHeight(), 
                Color.WHITE, Color.BLACK, 
                Shader.TileMode.CLAMP ) );
        }
    }
}
</pre>
<p>So, whenever the layout changes we create and set a new LinearGradient based on the height of the TextView.</p>
<p>Running this gives us the following:</p>
<p><a href="http://blog.stylingandroid.com/wp-content/uploads/2013/03/gradient_text.png"><img src="http://blog.stylingandroid.com/wp-content/uploads/2013/03/gradient_text.png" alt="gradient_text" width="606" height="104" class="alignnone size-full wp-image-1672" /></a></p>
<p>This same technique can be used to apply different kinds of gradients (<a href="http://developer.android.com/reference/android/graphics/LinearGradient.html" target="_blank">LinearGradient</a>, <a href="http://developer.android.com/reference/android/graphics/RadialGradient.html" target="_blank">RadialGradient</a>, <a href="http://developer.android.com/reference/android/graphics/SweepGradient.html" target="_blank">SweepGradient</a>), filling text with a bitmap (<a href="http://developer.android.com/reference/android/graphics/BitmapShader.html" target="_blank">BitmapShader</a>), or even combining shaders (<a href="http://developer.android.com/reference/android/graphics/ComposeShader.html" target="_blank">ComposeShader</a>). The more adventurous can even create their own custom shaders!</p>
<p>While we&#8217;ve only covered a really simple example here, we have covered a very useful technique which is pretty easy to implement, and can give us some impressive results.</p>
<p>The source code for this article is available <a href="https://bitbucket.org/StylingAndroid/gradienttext">here</a>.</p>
<p style='text-align:left'>&copy; 2013, <a href='http://blog.stylingandroid.com'>Mark Allison</a>. All rights reserved. This article originally appeared on <a href="http://blog.stylingandroid.com">Styling Android</a>.<br/><br/>Portions of this page are modifications based on work created and shared by Google and used according to terms described in the Creative Commons 3.0 Attribution License</p>
<p><a class="a2a_button_delicious" href="http://www.addtoany.com/add_to/delicious?linkurl=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1671&amp;linkname=Gradient%20Text" title="Delicious" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/delicious.png" width="16" height="16" alt="Delicious"/></a><a class="a2a_button_stumbleupon" href="http://www.addtoany.com/add_to/stumbleupon?linkurl=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1671&amp;linkname=Gradient%20Text" title="StumbleUpon" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/stumbleupon.png" width="16" height="16" alt="StumbleUpon"/></a><a class="a2a_button_reddit" href="http://www.addtoany.com/add_to/reddit?linkurl=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1671&amp;linkname=Gradient%20Text" title="Reddit" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/reddit.png" width="16" height="16" alt="Reddit"/></a><a class="a2a_button_digg" href="http://www.addtoany.com/add_to/digg?linkurl=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1671&amp;linkname=Gradient%20Text" title="Digg" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/digg.png" width="16" height="16" alt="Digg"/></a><a href="javascript:if(document.all){window.external.AddFavorite('http://blog.stylingandroid.com/archives/1671','Gradient%20Text')}else{var%20b=a2a_config.localize.BookmarkInstructions%20||%20'Press%20Ctrl+D%20to%20bookmark%20this%20page';alert(a2a_config.localize.BookmarkInstructions)}" title="Bookmark/Favorites" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/bookmark.png" width="16" height="16" alt="Bookmark/Favorites"/></a><a class="a2a_button_twitter_tweet addtoany_special_service" data-count="none" data-url="http://blog.stylingandroid.com/archives/1671" data-text="Gradient Text"></a><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1671&amp;title=Gradient%20Text" id="wpa2a_32"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share"/></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/StylingAndroid?a=EzqP_OfY1I4:MNI4ZxPmync:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/StylingAndroid?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/StylingAndroid/~4/EzqP_OfY1I4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.stylingandroid.com/archives/1671/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/</creativeCommons:license>
	<feedburner:origLink>http://blog.stylingandroid.com/archives/1671</feedburner:origLink></item>
		<item>
		<title>Dynamic Icon – Part 2</title>
		<link>http://feedproxy.google.com/~r/StylingAndroid/~3/GQvaQXKa4Cw/1646</link>
		<comments>http://blog.stylingandroid.com/archives/1646#comments</comments>
		<pubDate>Fri, 22 Mar 2013 10:00:28 +0000</pubDate>
		<dc:creator>Mark Allison</dc:creator>
				<category><![CDATA[Bitmap Drawable]]></category>
		<category><![CDATA[Drawables]]></category>
		<category><![CDATA[Transparency]]></category>
		<category><![CDATA[androiddev]]></category>

		<guid isPermaLink="false">http://blog.stylingandroid.com/?p=1646</guid>
		<description><![CDATA[In the previous article we got a basic app set up and got our images set up ready to create an image in which part of the colour could change depending on the values of three SeekBars representing the red, green, and blue components. In this article we&#8217;ll look at how we actually apply those [...]]]></description>
				<content:encoded><![CDATA[<p>In the <a href="/archives/1471">previous article</a> we got a basic app set up and got our images set up ready to create an image in which part of the colour could change depending on the values of three SeekBars representing the red, green, and blue components. In this article we&#8217;ll look at how we actually apply those colour values and create the required image.<br />
<span id="more-1646"></span></p>
<p>Previously we got everything written with the exception of an method named <code>updateImage()</code>, so let&#8217;s look at that:</p>
<pre class="brush: java; title: ; notranslate">
private void updateImage()
{
    if ( foreground != null &amp;&amp; background != null )
    {
        float[] transform =
            { red, 0, 0, 0, 0, 
              0, green, 0, 0, 0, 
              0, 0, blue, 0, 0, 
              0, 0, 0, 1.0f, 0 };
        ColorFilter cf = 
            new ColorMatrixColorFilter( transform );
        image.setImageBitmap( 
            combineImages( background, foreground, cf ) );
    }
}

public Bitmap combineImages( Bitmap bgd, Bitmap fg, 
    ColorFilter filter )
{
    Bitmap cs;

    int width = bgd.getWidth() &gt; fg.getWidth() 
        ? bgd.getWidth() : fg.getWidth();
    int height = bgd.getHeight() &gt; fg.getHeight() 
        ? bgd.getHeight() : fg.getHeight();

    cs = Bitmap.createBitmap( width, height, 
        Bitmap.Config.ARGB_8888 );

    Canvas comboImage = new Canvas( cs );
    comboImage.drawBitmap( bgd, new Matrix(), null );
    paint.setColorFilter( filter );
    comboImage.drawBitmap( fg, new Matrix(), paint );

    return cs;
}
</pre>
<p>There&#8217;s not actually much code there, but it requires a little bit of explanation. If we focus on <code>combineImages</code> to start with, what we are doing is creating a new <em>Bitmap</em> which is maximum width and height of our background and foreground images. Then we&#8217;re creating a <em>Canvas</em> based upon that <em>Bitmap</em>. Then we draw our background image on the <em>Canvas</em> at position 0,0 and we then draw the foreground image on top of this at position 0,0 using a <em>Paint</em> object on which we&#8217;ve set a <em>ColorFilter</em>. We&#8217;ll come back to the <em>ColorFilter</em> in a moment but for now let&#8217;s just assume that it applies the appropriate colour as we draw the foreground image.</p>
<p>The <em>Bitmap</em> containing this combined image can then be applied to our <em>ImageView</em> object. So the combining of the images is pretty straightforward, but this <em>ColorFilter</em> requires some further explanation.</p>
<p>If we look at the creation of the <em>ColorFilter</em> it looks pretty scary. The constructor takes an array of 20 float values:</p>
<pre class="brush: java; title: ; notranslate">
float[] transform =
    { red, 0, 0, 0, 0, 
      0, green, 0, 0, 0, 
      0, 0, blue, 0, 0, 
      0, 0, 0, 1.0f, 0 };
ColorFilter cf = new ColorMatrixColorFilter( transform );
</pre>
<p>It becomes a little less daunting if we break this down in to 4 groups of 5 floats. Each group corresponds to one of the 4 colour channels: red, green, blue, and alpha (transparency). Each of the values in each group represents part of the calculation to determine the new value for that colour channel for that pixel.</p>
<p>Let&#8217;s break it down a little further. If we have the following matrix:</p>
<p><code>{<br />
a, b, c, d, e,<br />
f, g, h, i, j,<br />
k, l, m, n, o,<br />
p, q, r, s, t<br />
} </code></p>
<p>and we apply this to an arbitrary colour represented by four values to represent the red, green, blue, and alpha components:</p>
<p><code>[ R, G, B, A ]</code></p>
<p>The resulting colour will be made up of four new red, green, blue, and alpha components. Each of these is based upon a quite simple calculation. Let&#8217;s consider the new red value first, which is calculated as follows:</p>
<p><code>R' = R*a + G*b + B*c + A*d + e</code></p>
<p>So the new red value can be influenced by *any* of the existing colour channel values, which can be really useful for doing things like inverting the colours of an image. In our case, we use the following values:</p>
<p><code>a = red (the value from our red <em>SeekBar</em>)<br />
b = 0<br />
c = 0<br />
d = 0<br />
e = 0</code></p>
<p>So the calculation can be simplified to:</p>
<p><code>R' = R*a<br />
G' = G*g<br />
B' = B*m</code></p>
<p>So if we think about our mask image, all of the pixels were either white or transparent. When the matrix is applied to a white pixel (which has 0xFF red component) from the mask, the new red value will be used. The green and blue values will be calculated in the same way, and for this reason it is important that the &#8220;on&#8221; pixels in our mask are white because the output values will depend on the green and blue components of the mask pixel.</p>
<p>But what about those transparent pixels from the mask, how does that work? When the transform applied to the alpha channel the alpha channel part of the matrix will be used:</p>
<p><code>p = 0<br />
q = 0<br />
r = 0<br />
s = 1.0<br />
t = 0</code></p>
<p>So the calculation is:</p>
<p><code>A' = A*s</code></p>
<p>This is actually an identity transformation where the value output will match the value input. So in our case where the mask pixel is transparent, the output will be transparent (i.e. the background image will show through) and where the mask pixel is opaque the foreground image will overwrite the background image.</p>
<p>For the sake of clarity, our mask only contains fully opaque or fully transparent pixels. However by using varying levels of transparency we can allow parts of the background image to show through. </p>
<p>If we look at what this does to our app we can see that our colour is now applied to the image:</p>
<p><a href="http://blog.stylingandroid.com/wp-content/uploads/2013/03/working_app.png"><img src="http://blog.stylingandroid.com/wp-content/uploads/2013/03/working_app.png" alt="working_app" width="360" height="215" class="alignnone size-full wp-image-1653" /></a>  </p>
<p>Specifying a light colour demonstrates that the border of the background image is showing through our colourised mask:</p>
<p><a href="http://blog.stylingandroid.com/wp-content/uploads/2013/03/working_app_light.png"><img src="http://blog.stylingandroid.com/wp-content/uploads/2013/03/working_app_light.png" alt="working_app_light" width="360" height="213" class="alignnone size-full wp-image-1657" /></a></p>
<p>That concludes this short series of articles, but we&#8217;ve barely scratched the surface of what a colour matrix transform can do but, suffice it to say, they are extremely powerful!</p>
<p>The source code for this article is available <a href="https://bitbucket.org/StylingAndroid/dynamicicon/src/9e0d653bf706f824d1f4b58edd02f67c1d3a72d1/?at=Part2" target="_blank">here</a>.</p>
<p style='text-align:left'>&copy; 2013, <a href='http://blog.stylingandroid.com'>Mark Allison</a>. All rights reserved. This article originally appeared on <a href="http://blog.stylingandroid.com">Styling Android</a>.<br/><br/>Portions of this page are modifications based on work created and shared by Google and used according to terms described in the Creative Commons 3.0 Attribution License</p>
<p><a class="a2a_button_delicious" href="http://www.addtoany.com/add_to/delicious?linkurl=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1646&amp;linkname=Dynamic%20Icon%20%E2%80%93%20Part%202" title="Delicious" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/delicious.png" width="16" height="16" alt="Delicious"/></a><a class="a2a_button_stumbleupon" href="http://www.addtoany.com/add_to/stumbleupon?linkurl=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1646&amp;linkname=Dynamic%20Icon%20%E2%80%93%20Part%202" title="StumbleUpon" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/stumbleupon.png" width="16" height="16" alt="StumbleUpon"/></a><a class="a2a_button_reddit" href="http://www.addtoany.com/add_to/reddit?linkurl=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1646&amp;linkname=Dynamic%20Icon%20%E2%80%93%20Part%202" title="Reddit" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/reddit.png" width="16" height="16" alt="Reddit"/></a><a class="a2a_button_digg" href="http://www.addtoany.com/add_to/digg?linkurl=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1646&amp;linkname=Dynamic%20Icon%20%E2%80%93%20Part%202" title="Digg" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/digg.png" width="16" height="16" alt="Digg"/></a><a href="javascript:if(document.all){window.external.AddFavorite('http://blog.stylingandroid.com/archives/1646','Dynamic%20Icon%20&#8211;%20Part%202')}else{var%20b=a2a_config.localize.BookmarkInstructions%20||%20'Press%20Ctrl+D%20to%20bookmark%20this%20page';alert(a2a_config.localize.BookmarkInstructions)}" title="Bookmark/Favorites" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/bookmark.png" width="16" height="16" alt="Bookmark/Favorites"/></a><a class="a2a_button_twitter_tweet addtoany_special_service" data-count="none" data-url="http://blog.stylingandroid.com/archives/1646" data-text="Dynamic Icon &#8211; Part 2"></a><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1646&amp;title=Dynamic%20Icon%20%E2%80%93%20Part%202" id="wpa2a_36"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share"/></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/StylingAndroid?a=GQvaQXKa4Cw:PGCwuEKyG_Q:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/StylingAndroid?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/StylingAndroid/~4/GQvaQXKa4Cw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.stylingandroid.com/archives/1646/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/</creativeCommons:license>
	<feedburner:origLink>http://blog.stylingandroid.com/archives/1646</feedburner:origLink></item>
		<item>
		<title>Dynamic Icon – Part 1</title>
		<link>http://feedproxy.google.com/~r/StylingAndroid/~3/WlkE8LXN4tc/1471</link>
		<comments>http://blog.stylingandroid.com/archives/1471#comments</comments>
		<pubDate>Fri, 15 Mar 2013 10:00:26 +0000</pubDate>
		<dc:creator>Mark Allison</dc:creator>
				<category><![CDATA[Bitmap Drawable]]></category>
		<category><![CDATA[Drawables]]></category>
		<category><![CDATA[androiddev]]></category>

		<guid isPermaLink="false">http://blog.stylingandroid.com/?p=1471</guid>
		<description><![CDATA[Recently in my day job for Byte Squared I wanted to have an ImageButton in which a part of the image should change colour to match the a value selected by the user. In other words the icon needed to change dynamically. In this series of articles we&#8217;ll look at a method of achieving this. [...]]]></description>
				<content:encoded><![CDATA[<p>Recently in my day job for <a href="http://www.bytesquared.com">Byte Squared</a> I wanted to have an ImageButton in which a part of the image should change colour to match the a value selected by the user. In other words the icon needed to change dynamically. In this series of articles we&#8217;ll look at a method of achieving this.<br />
<span id="more-1471"></span> </p>
<p>When the requirement first became apparent, the graphic designer had provided an image in which the afre that needed to change colour was a simple rectangle, so my initial thought was to simply use a canvas to draw a filled rectangle on top of the bitmap. While this would have certainly worked, it would have been made more complex by having to adapt the dimensions of the rectangle based upon different screen densities, and subtle differences in the image assets provided for mdpi, hdpi, xhdpi etc. The graphic designer then started working on some alternative assets where there was a non-uniform shape which needed the colour applying, and this new non-uniform shape would be difficult to mimic accurately by drawing directly to a canvas.</p>
<p>The solution which sprang to mind was to use a mask in much the same way as you would in and image manipulation package whereby you create a mask corresponding to the areas that you want to apply the colour to, and apply the appropriate colour to these areas.</p>
<p>So, let&#8217;s begin by setting up an basic Android 4.2 project with a package name of <code>com.stylingandroid.dynamicicon</code>, and a main activity named <code>DynamicIconActivity</code>. Next we&#8217;ll create a layout in <span style="color: #0000ff">res/layout/main.xml</span> consisting of three <em>SeekBar</em>s corresponding to the red, green, and blue components of the colour that we wish to apply, as well as an ImageView to hold the image that will be our dynamic icon:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;GridLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
            xmlns:tools=&quot;http://schemas.android.com/tools&quot;
            android:id=&quot;@+id/GridLayout1&quot;
            android:layout_width=&quot;match_parent&quot;
            android:layout_height=&quot;wrap_content&quot;
            android:columnCount=&quot;2&quot;
            android:padding=&quot;8dp&quot;
            tools:context=&quot;.MainActivity&quot;&gt;

    &lt;TextView
            android:layout_gravity=&quot;right|center_vertical&quot;
            android:text=&quot;@string/red&quot;/&gt;

    &lt;SeekBar
            android:id=&quot;@+id/redSeek&quot;
            android:layout_gravity=&quot;center_vertical|fill_horizontal&quot;
            android:paddingTop=&quot;4dp&quot;
            android:paddingBottom=&quot;4dp&quot;
            android:layout_marginLeft=&quot;8dp&quot;/&gt;

    &lt;TextView
            android:layout_gravity=&quot;right|center_vertical&quot;
            android:text=&quot;@string/green&quot;/&gt;

    &lt;SeekBar
            android:id=&quot;@+id/greenSeek&quot;
            android:layout_gravity=&quot;center_vertical|fill_horizontal&quot;
            android:paddingTop=&quot;4dp&quot;
            android:paddingBottom=&quot;4dp&quot;
            android:layout_marginLeft=&quot;8dp&quot;/&gt;

    &lt;TextView
            android:layout_gravity=&quot;right|center_vertical&quot;
            android:text=&quot;@string/blue&quot;/&gt;

    &lt;SeekBar
            android:id=&quot;@+id/blueSeek&quot;
            android:layout_gravity=&quot;center_vertical|fill_horizontal&quot;
            android:paddingTop=&quot;4dp&quot;
            android:paddingBottom=&quot;4dp&quot;
            android:layout_marginLeft=&quot;8dp&quot;/&gt;

    &lt;ImageView
            android:id=&quot;@+id/image&quot;
            android:layout_columnSpan=&quot;2&quot;
            android:layout_gravity=&quot;center&quot;
            android:contentDescription=&quot;@string/drawable_holder&quot;
            android:minWidth=&quot;40dp&quot;/&gt;

&lt;/GridLayout&gt;
</pre>
<p>There are some string definitions required also in <span style="color: #0000ff">res/values/strings.xml</span>:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;resources&gt;

    &lt;string name=&quot;app_name&quot;&gt;Dynamic Icon&lt;/string&gt;
    &lt;string name=&quot;red&quot;&gt;Red&lt;/string&gt;
    &lt;string name=&quot;green&quot;&gt;Green&lt;/string&gt;
    &lt;string name=&quot;blue&quot;&gt;Blue&lt;/string&gt;
    &lt;string name=&quot;drawable_holder&quot;&gt;Drawable Holder&lt;/string&gt;

&lt;/resources&gt;
</pre>
<p>This is all pretty standard stuff, so we won&#8217;t go in to details. </p>
<p>The next thing that we need to look at is the image that we want to transform. As a simple example, I&#8217;ll use one of the standard menu icons within Android: <a href="https://github.com/android/platform_frameworks_base/blob/master/core/res/res/drawable-xhdpi/ic_menu_play_clip.png" target="_blank">ic_menu_play_clip</a> and the mask that corresponds to the areas that we intend to fill with colour:</p>
<div style="background-color: #888">
<a href="http://blog.stylingandroid.com/wp-content/uploads/2013/03/ic_menu_play_clip.png"><img src="http://blog.stylingandroid.com/wp-content/uploads/2013/03/ic_menu_play_clip.png" alt="ic_menu_play_clip" width="64" height="64" class="alignnone size-full wp-image-1636" /></a><a href="http://blog.stylingandroid.com/wp-content/uploads/2013/03/ic_menu_play_clip_mask.png"><img src="http://blog.stylingandroid.com/wp-content/uploads/2013/03/ic_menu_play_clip_mask.png" alt="ic_menu_play_clip_mask" width="64" height="64" class="alignnone size-full wp-image-1637" /></a>
</div>
<p>Although it is difficult to determine by comparing the two images, the mask corresponds to the area inside the dark border on the left hand image. This means that the dark border will always be drawn, but we&#8217;ll control the colour inside that border.</p>
<p>The key advantage of this approach is that the mask can be any shape that the graphic designer wants. As long as he provides an appropriate mask, we can apply it. Also this still works when we have different image drawables for different pixel densities because we can have a separate mask for each, as well.</p>
<p>For the sake of simplicity, I&#8217;ve only included xhdpi versions in the example project as I am only targeting my Galaxy Nexus for screen shots. However in a production app, you would provide more coverage for different screen densities. </p>
<p>Next we need to add some basci wiring to our Activity:</p>
<pre class="brush: java; title: ; notranslate">
    private float red = 1.0f;
    private float green = 1.0f;
    private float blue = 1.0f;

    private ImageView image = null;
    private Bitmap background = null;
    private Bitmap foreground = null;

    private Paint paint = new Paint();

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        background = BitmapFactory.decodeResource( getResources(), R.drawable.ic_menu_play_clip );
        foreground = BitmapFactory.decodeResource(getResources(), R.drawable.ic_menu_play_clip_mask);
        SeekBar redSeek = (SeekBar) findViewById(R.id.redSeek);
        SeekBar greenSeek = (SeekBar) findViewById(R.id.greenSeek);
        SeekBar blueSeek = (SeekBar) findViewById(R.id.blueSeek);
        image = (ImageView) findViewById(R.id.image);

        image.setBackgroundColor( Color.WHITE );
        image.setImageResource( R.drawable.ic_menu_play_clip );

        redSeek.setMax(0xFF);
        redSeek.setProgress(0xFF);
        redSeek.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener()
        {

            @Override
            public void onStopTrackingTouch(SeekBar arg0)
            {
            }

            @Override
            public void onStartTrackingTouch(SeekBar arg0)
            {
            }

            @Override
            public void onProgressChanged(SeekBar arg0, int pos, boolean arg2)
            {
                red = (float) pos / (float) 0xFF;
                updateImage();
            }
        });
        .
        .
        .
        updateImage();
    }
}
</pre>
<p>For the sake of brevity I have removed pretty much duplicate code for the <em>OnSeekBarChangeListener</em> implementation for the green and blue <em>SeekBar</em>s. So what we have is three <em>SeekBar</em>s which will each update a respective colour value when the position changes.</p>
<p>If we run this we can see the basic test app, but nothing yet happens when we move the SeekBars:</p>
<p><a href="http://blog.stylingandroid.com/wp-content/uploads/2013/03/basic_app.png"><img src="http://blog.stylingandroid.com/wp-content/uploads/2013/03/basic_app.png" alt="basic_app" width="360" height="222" class="alignnone size-full wp-image-1641" /></a></p>
<p>Note how the dark border makes the icon visible when it is displayed on top of a white background.</p>
<p>So we have our basic test app in place, but we don&#8217;t yet have an implementation for the <em>updateImage()</em> method which is going to perform the transformation of our image. In the concluding article in this series we&#8217;ll look at this code.</p>
<p>The source code for this article is available <a href="https://bitbucket.org/StylingAndroid/dynamicicon/src/da7fc66cb3933c45ea8aa653949a4141962a2ce6/?at=Part1" target="_blank">here</a>.</p>
<p style='text-align:left'>&copy; 2013, <a href='http://blog.stylingandroid.com'>Mark Allison</a>. All rights reserved. This article originally appeared on <a href="http://blog.stylingandroid.com">Styling Android</a>.<br/><br/>Portions of this page are modifications based on work created and shared by Google and used according to terms described in the Creative Commons 3.0 Attribution License</p>
<p><a class="a2a_button_delicious" href="http://www.addtoany.com/add_to/delicious?linkurl=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1471&amp;linkname=Dynamic%20Icon%20%E2%80%93%20Part%201" title="Delicious" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/delicious.png" width="16" height="16" alt="Delicious"/></a><a class="a2a_button_stumbleupon" href="http://www.addtoany.com/add_to/stumbleupon?linkurl=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1471&amp;linkname=Dynamic%20Icon%20%E2%80%93%20Part%201" title="StumbleUpon" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/stumbleupon.png" width="16" height="16" alt="StumbleUpon"/></a><a class="a2a_button_reddit" href="http://www.addtoany.com/add_to/reddit?linkurl=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1471&amp;linkname=Dynamic%20Icon%20%E2%80%93%20Part%201" title="Reddit" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/reddit.png" width="16" height="16" alt="Reddit"/></a><a class="a2a_button_digg" href="http://www.addtoany.com/add_to/digg?linkurl=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1471&amp;linkname=Dynamic%20Icon%20%E2%80%93%20Part%201" title="Digg" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/digg.png" width="16" height="16" alt="Digg"/></a><a href="javascript:if(document.all){window.external.AddFavorite('http://blog.stylingandroid.com/archives/1471','Dynamic%20Icon%20&#8211;%20Part%201')}else{var%20b=a2a_config.localize.BookmarkInstructions%20||%20'Press%20Ctrl+D%20to%20bookmark%20this%20page';alert(a2a_config.localize.BookmarkInstructions)}" title="Bookmark/Favorites" rel="nofollow" target="_blank"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/icons/bookmark.png" width="16" height="16" alt="Bookmark/Favorites"/></a><a class="a2a_button_twitter_tweet addtoany_special_service" data-count="none" data-url="http://blog.stylingandroid.com/archives/1471" data-text="Dynamic Icon &#8211; Part 1"></a><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fblog.stylingandroid.com%2Farchives%2F1471&amp;title=Dynamic%20Icon%20%E2%80%93%20Part%201" id="wpa2a_40"><img src="http://blog.stylingandroid.com/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share"/></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/StylingAndroid?a=WlkE8LXN4tc:5aV-Wk3TUtc:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/StylingAndroid?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/StylingAndroid/~4/WlkE8LXN4tc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.stylingandroid.com/archives/1471/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/</creativeCommons:license>
	<feedburner:origLink>http://blog.stylingandroid.com/archives/1471</feedburner:origLink></item>
	</channel>
</rss>
