Pages

Thursday, 26 May 2011

First Steps - Introducing Themes

How do I use themes in my app?
This post extends my previous post introducing styles, so if you've not used styles in android before I would recommend reading that first.

A theme is specified for an entire application or individual activities within the manifest. It encapsulates a number of visual style settings, such as text and button styling.

Android has a default theme which is the 'dark' theme, black background with white text, that you will see it you were to open the Settings menu for example. When you create an android app you do not need to specify the theme as the dark theme is used by default.

It is likely that you will at some point want to hide the application title bar, this can be done by setting the theme to Theme.NoTitleBar. Android also has a 'light' theme built in (black on white) which can be used by setting the theme to Theme.Light. You can also chain the theme settings to allow combinations, for example Theme.Light.NoTitleBar. Themes are applied in the manifest as shown below:

Manifest sample:
<application
  android:icon="@drawable/ic_launcher"
  android:label="@string/app_name"
  android:theme="@android:style/Theme.Light">
  <activity
    android:name=".Main"
    android:theme="@android:style/Theme.Light.NoTitleBar">

System styles are prefixed for the @android tag. Much like styles, custom themes are defined within an XML file within your resources and each theme must have a name and can optionally have a parent, for inheriting properties:

res/values/themes.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="Theme.myTheme" parent="android:Theme.Light.NoTitleBar">
     <item name="textSize">20sp</item>
    </style>
</resources>

You can then apply your own theme within your project manifest, as shown below.

Manfiest sample:
...
<application
    android:icon="@drawable/icon"
    android:label="@string/app_name"
    android:theme="@style/Theme.myTheme">
    ...

Wednesday, 25 May 2011

First Steps - An introduction to Styles

How do I use styles in my app?
Use of styles allows you to define reusable visual settings to help maintain a consistent look-and-feel to your app.
The simple example below shows how to create a style for titles, which will be larger text, and warnings which will be red. Each style must have a name and can then list multiple properties:

values/styles.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="myTitle">
      <item name="android:textSize">16sp</item>
    </style>
    <style name="myWarning" parent="@style/myTitle">
      <item name="android:textStyle">bold</item>
      <item name="android:textColor">@colors/myRed</item>
    </style>
</resources>

A few things to note here, firstly that you can put any styling name into the item tag that you would use within your layout definitions. Also note that myWarnings has its parent set as myTitle and so inherits the 16sp text size defined there. Finally, the textColor value could be a standard hex colour (i.e. #FF0000) but it is good practice to put colours into a separate resource so that one you only need to update one location if you want to change it:

values/colors.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="myRed">#FF0000</color>
</resources>

Now it is simply the case of applying the style within your layouts:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

<TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="My styled text view"
        style="@styles/myWarning" />
</LinearLayout>

Note that the style attribute is not prefixed by the android tag.

Tuesday, 24 May 2011

Referencing a drawable in code

A very quick one here, but I often forget how to get a reference in code to my drawable resources, so here it is...

Drawable d = getResources().getDrawable(R.drawable.icon);

The getResources() method available depending upon context. If you need to reference it from within your own class then you'll need to pass a context in.

First Steps Series, Getting Started with Android

My First Steps guides are intended to assist those new to Android development. I thought I should have an index of them all, so here it is.

1. Welcome to Android Elements
A welcome and how to get started with links to good resources.

2. Android Building Blocks
The basics of how an app is structured.

3. My First Android Project
Walkthrough of building your first project; a simple app with a button.

4. My Second Android Project
Extending the simple app using addition controls and settings.

5. Common Pitfalls
Common pitfalls and how to avoid them.

6. Android Project Structure in Eclipse
An overview of the structure of an Android project within Eclipse.

7. Introduction to Styles
Simple guide to using styles when building an app.

8. Introducing Themes
Expansion of introduction to styles into themes.

9. Passing values to an Activity
Simple example of passing values into an Activity using an Intent.

10. Returning values from an Activity
Simple example of returning a value from an Activity.

I will continue to add to the series over time,

Monday, 23 May 2011

Displaying the Version number of your app

How do I display the versionName from my manifest file in my app?

The versionName value in your project manifest file is a 'friendly' version number that is displayed to the user on the market screen and in the application list. The versionCode value is the integer that allows you to version and publish updates to your app on the market (refer to the official documentation on Versioning Your Applications).

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.androidelements.myProject"
      android:versionCode="1"
      android:versionName="1.0.0">

You might want to display the version name in your app, on a splash or about screen perhaps. To do this you need to use the PackageInfo class, here's how...

Add the following imports:
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;

Use the following code to display the value in a TextView:
String versionName = "";
try {
    final PackageInfo packageInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
    versionName = packageInfo.versionName;
} catch (NameNotFoundException e) {
    e.printStackTrace();
}
TextView tv = (TextView) findViewById(R.id.tvVersion);
tv.setText(versionName);

Sunday, 22 May 2011

Defining a custom button with background and textcolor styles

How do I define a custom button with background and text color styles?

This is a simple guide to styling buttons within your Android app. We start of with a button in your Layout, and set the style to a custom style name:

<Button
  android:id="@+id/myButton"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:text="Tap me!"
  style="@style/button" />

It is a good idea to use a style rather than set the background directly as it allows you to set the text properties as well as background graphic options. It also makes it very easy to re-use your style.

res/values/styles.xml
<style name="button">
  <item name="android:background">@drawable/button</item>
  <item name="android:textColor">#FFF</item>
  <item name="android:textSize">16sp</item>
  <item name="android:gravity">center_vertical|center_horizontal</item>
</style>

The background of a Button is expected to be a Drawable (image), but we are able to define this as a shape with an item for each state (pressed, focussed or default). To keep this simple we'll stick to simple colour changes:

res/drawable/button.xml
<?xml version="1.0" encoding="utf-8"?>    
<selector xmlns:android="http://schemas.android.com/apk/res/android">

  <item android:state_pressed="true" >
    <shape>
      <solid android:color="#FF0000" />
    </shape>
  </item>

  <item android:state_focused="true" >
    <shape>
      <solid android:color="#DDDDDD" />
    </shape>
  </item>

  <item>
    <shape>
      <solid android:color="#FFFFFF" />
    </shape>
  </item>

</selector>

You may want to produce more fancy buttons, in which case you will need to use more shape options (such as rounding and strokes) or produce a Drawable image for each state. If you want to use images, these should be 9-Patch PNGs that allow Android to stretch the image to fit any content. I will cover these another day!

Thursday, 19 May 2011

Advanced Lists: Using class object within ListView

How do I build a ListView to display my custom class items?

One of the most common interface elements used in Android apps is the ListView. This presents to the user a scrollable list of tappable items. The best place to start with this is and Android Developers ListView Tutorial which will cover the basics of creating an activity with the ListView control and displaying a list of items from a string array.

In a real world app you will probably want to build a list with something other than a string array. Commonly you will have a collection of your own type of object, or you may want to display listview items with an icon. I will show you how to use a ListView to display these objects and also handle the tap event.

Let's start with the class object that will consist of a text label, a drawable for the icon and also an index value to track item selection:

CustomListItem.java
package com.example.advancedList; import android.graphics.drawable.Drawable; public class CustomListItem { private int mIndex; private String mLabel; private Drawable mPicture; public CustomListItem(final int index, final String label, final Drawable pic) { mIndex = index; mLabel = label; mPicture = pic; } public int getIndex() { return mIndex; } public String getLabel() { return mLabel; } public Drawable getPicture() { return mPicture; } }
Now that we have our class defined, let's create the layout that will be used to display the individual list item, which is a simple RelativeView with an ImageView for the icon and a TextView for the label:

Create res/layout/list_item.xml :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
  
   <TextView
       android:id="@+id/txtLabel"
       android:layout_width="fill_parent"
       android:layout_height="wrap_content" 
       android:text="List item" />
   <ImageView
       android:id="@+id/txtImgIcon"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content" 
       android:src="@null"
       android:layout_toRightOf="@id/txtLabel" />
  
</RelativeLayout>

Hopefully so far everything has been quite straight forward. We now need to define a custom list adapter that extends the BaseAdapter class, this will allow us to fully control the way the ListView is constructed.

Create a class named MyListItemAdapter.java:
package com.example.advancedList;

import java.util.List;

import android.content.Context;
import android.graphics.Bitmap;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;

// Custom list item class for menu items
public class MyListItemAdapter extends BaseAdapter {

    private List<CustomListItem> items;
    private Context context;
    private int numItems = 0;

    public MyListItemAdapter(final List<CustomListItem> items, Context context) {
        this.items = items;
        this.context = context;
        this.numItems = items.size();
    }
 
    public int getCount() {
        return numItems;
    }

    public CustomListItem getItem(int position) {
        return items.get(position);
    }

    public long getItemId(int position) {
        return 0;
    }

    public View getView(int position, View convertView, ViewGroup parent) {
       
        // Get the current list item
        final CustomListItem item = items.get(position);
        // Get the layout for the list item
        final RelativeLayout itemLayout = (RelativeLayout) LayoutInflater.from(context).inflate(R.layout.list_item, parent, false);
        // Set the icon as defined in our list item
        ImageView imgIcon = (ImageView) itemLayout.findViewById(R.id.imgIcon);
        imgIcon.setImageDrawable(item.getPicture());
     
        // Set the text label as defined in our list item
        TextView txtLabel = (TextView) itemLayout.findViewById(R.id.txtLabel);
        txtLabel.setText(item.getLabel());

        return itemLayout;
    }
 
}

Next let's knock together a simple layout for the main activity. This will consist of a ListView for our items and a TextView that is displayed if the list is ever empty. Note here the use of special Android reserved IDs for the controls. This allows the list to be picked up for the ListActivity we'll use and also know to only display the TextView if there is no data in the ListView.

We'll call the file res/layout/list_example.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_height="fill_parent"
    android:layout_width="fill_parent">

    <ListView
      android:id="@id/android:list"
      android:layout_height="wrap_content"
      android:layout_width="fill_parent" />
     
   <TextView
      android:id="@id/android:empty"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:text="Nothing to list" />
</LinearLayout>

We now need to build our main Activity which extends the ListActivity class using our layout defined previously. Within the activity's onCreate method we create a List of our CustomListItem type and add 3 new items to it. We then populate a new ListAdapter using our myListItemAdapter class and assign to it our list of items:

src/com.example.advancedList/Main.java :
package com.example.advancedList;

import java.util.ArrayList;
import java.util.List;

import android.app.ListActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.AdapterView.OnItemClickListener;

public class Main extends ListActivity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.list_example);
        
// Create list of items based upon class
        final List<CustomListItem> items = new ArrayList<CustomListItem>(3);
     
        items.add(new CustomListItem (1, "Item 1", getResources().getDrawable(R.drawable.icon)));
        items.add(new CustomListItem (2, "Item 2", getResources().getDrawable(R.drawable.icon)));
        items.add(new CustomListItem (3, "Item 3", getResources().getDrawable(R.drawable.icon)));
     
        // Populate the list view
        ListAdapter adapter = new myListItemAdapter(items, this);
        ListView lv = getListView();  // Because we are extending ListActivity we cal  this but could specify
        lv.setAdapter(adapter);
        lv.setTextFilterEnabled(true);
     
        // Add listener for item clicks
        lv.setOnItemClickListener(new OnItemClickListener() {
            public void onItemClick(AdapterView<?> parent, View view,
                    int position, long id) {
             
                  // Retrieve our class object and use index to resolve item tapped
                    final MenuListItem item = items.get(position);
                    final int menuIndex = item.getIndex();
                    switch (menuIndex) {
                    case 1:                      
                        break;
                    case 2:                      
                        break;
                    case 3:
                        break;
                    default:
                        break;
                    }
            }
        });      
    }
 
}

You'll see that once we have our list adapter set up it is applied to the list view. We then assign a listener to the list view to pick up click events. Within this the first thing we do it obtain the item from the list that was clicked. We then have the freedom to make our code react to any aspect of our object.

I have used this approach several times and in fact have never displayed a list from a string array. I hope you find this guide useful.


Tuesday, 17 May 2011

Best Eclipse Shortcuts

There are many sites listing their top Eclipse shortcuts, but for what it's worth I would like to add my most used keyboard shortcuts since starting with Eclipse...

Ctrl + Shift + O = organise and import missing imports
Alt + Shift + R = refactor (rename variable or method)

Ctrl + 1 (one) = Quick fix popup
Ctrl + D = Delete line
Ctrl + O = Outline (easily navigate to parts of project)
Ctrl + M (or double-click tab) = Maximise source when coding
Ctrl + . = Jump next error or warning


Alt + UP / Alt + DOWN = Move selection up or down
Alt + LEFT / Alt + RIGHT = Jump to recently edited sections


Ctrl + Shift + R = open resource (start typing any file name - like indexed search)
Ctrl + Shift + F - Formats code to settings defined under Window > Preferences > Java > Code Style > Formatter

Monday, 16 May 2011

Setting a style on dynamically created view control

How do I set a TextView or Button style in code?
Styling within Android allows you to define a reusable look-and-feel, much like styles in CSS on a web page. These are very easy to assign in your XML layouts, however you cannot set the style of a View control programmatically. This is a pain if you are building a layout dynamically.

To get around this you can create a template layout xml file with the style assigned, for example in res/layout create tvtemplate.xml as with the following content:

res/layout/tvtemplate.xml
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="This is a template"
        style="@style/my_style" />

then inflate this to instantiate your new TextView:

TextView myText = (TextView)getLayoutInflater().inflate(R.layout.tvtemplate, null);

You can then continue to work with your TextView as usual. There may be other workarounds for this, if you have any please feel free to comment. It's also possible that an Android API update will add a property for this in future.

Wednesday, 11 May 2011

Adding views to a layout dynamically

How do I add a button to my layout in code?

Firstly add the appropriate import to your Activity class for the view to add, in this case a button:

import android.widget.Button;

Then create a new button object within the activity onCreate method:

Button myButton = new Button(this);
myButton.setText("Tap Me");

Finally add the button to the layout:

LinearLayout layout = (LinearLayout) findViewById(R.id.layout1);
layout.addView(myButton);

Obviously the same logic applies to other views (TextViews, etc).

You might also want to apply fonts to your controls, if so take a look at Using a True-Type Font in your Android app.

Tuesday, 10 May 2011

Official Android Ice Cream Sandwich image

Tweeted by @AndroidDev earlier today at IO2011...

Share photos on twitter with Twitpic

First Steps: Android project structure in Eclipse

Android Project structure in Eclipse
This article is a quick guide to the breakdown of the project structure of a typical, simple Android project within Eclipse. The numbered items below refer to the image to the right.
  1. Project root folder (see 7 for details of individual files)
  2. src folder. This is where your java code files are stored.
  3. package folder. This is organised by package name with the java class files within.
  4. Main.java is a java class file, in this case the main activity. Note the exclamation denoting a compilation warning.
  5. Web.java is another java class (without warnings or errors).
  6. gen folder. The generated compiled files when a project is built. You do not need to venture into this folder.
  7. Google APIs folder. The API library folder.
  8. assets folder. This is where you place additional assets for use in your project, such as font (ttf) files.
  9. res folder. This is where the resource files are stored, such as your drawables (images), layouts and string values.
  10. drawable-hdpi folder. High density drawables (images) for use in your project.
  11. drawable-ldpi folder. Low density drawables (images) for use in your project.
  12. drawable-mdpi folder. Medium density drawables (images) for use in your project.
  13. layout folder. This contains the XML layout files that define the screens in your project.
  14. main.xml. This is the layout for the Main activity, defined in Main.java.
  15. web.xml. This is the layout for the Web activity, defined in Web.java.
  16. values folder. This is where your string (text) definitions are stored. To support multiple languages you would find a values folder per language, for example values-fr.
  17. strings.xml. A standard XML file containing named string definitions.
  18. AndroidManifest.xml - The hub of your project containing the details on the Activities, Permissions within your app.
  19. default.properties -An auto-generated configuration file storing the basic project properties.
  20. proguard.cfg - ProGuard can be used to obfuscate your code to prevent nasty code thieves from stealing your secrets. By default this is not applied to the code but the configuration file is still present.
Typically you will place any additional referenced Java libraries (.jar files) into a libs folder.

Hopefully this will help an Android newbie opening up a new project for the first time.

Friday, 6 May 2011

Using a True-Type Font in your Android app

Android supports true-type fonts, but these have to be set in code, you cannot specify the fonts in the layout XML.

Firstly copy the font file into your assets folder. I usually create a fonts sub-folder:

project/assets/fonts/myfont.ttf

Second, and finally, apply the font to a TextView in code:

TextView tv = (TextView)findViewById(R.id.TextView1);
Typeface face = Typeface.createFromAsset(getAssets(), "fonts/myfont.ttf");
tv.setTypeface(face);

TextViews, Buttons, CheckedTextView and RadioButtons all have the setTypeface method, but as a note of warning, not all .ttf files will necessarily display in your Android app, if it fails your app will force close with the following error: RuntimeException: native typeface cannot be made.

Wednesday, 4 May 2011

How to Fix Screen Orientation

How do I stop my Android app rotating?

There are a number of reasons that you may want to prevent your screen from rotating. When an Android device is rotated, by default the currently running activity is restarted. This will often require you to code to maintain the state that the activity was in prior to rotation. Alternatively you may simply want to display only in landscape, perhaps for a game.

To fix your screen orientation, simply set the screenOrientation attribute of the activity within your project manifest, as shown below, to either portrait or landscape:

<activity
    android:name=".myActivity"
    android:screenOrientation="portrait">

You can also do the same thing in code:

myActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

Please refer to the official documentation for more details.