Search This Blog

Saturday 21 July 2012

Custom Dialogs

Today we will look at creating custom dialogs.  When creating my own custom dialog for my Maths Test App,  I found the following website very useful (Although I did find an issue with the code which I had to correct for, more about that later):


A custom dialog is effectively a user interface, remember that user interfaces in android are called layouts and are defined in xml.  We have covered creating user interfaces and handling user inputs in previous posts, so I will not repeat myself here.  However step 1 in creating your custom dialog is creating a layout in xml.

Step 1 in creating custom dialog is to define a layout

The following layout is the one used in the example on the above website.  The layout contains an ImageView and a TextView.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:id="@+id/layout_root"
              android:orientation="horizontal"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent"
              android:padding="10dp"
              >
    <ImageView android:id="@+id/image"
               android:layout_width="wrap_content"
               android:layout_height="fill_parent"
               android:layout_marginRight="10dp"
               />
    <TextView android:id="@+id/text"
              android:layout_width="wrap_content"
              android:layout_height="fill_parent"
              android:textColor="#FFF"
              />
</LinearLayout>
In the example on the website the following code is used to set the text for the TextView and the image for the ImageView.


Step 2 is to setup the layout in code
Context mContext = getApplicationContext();
Dialog dialog = new Dialog(mContext);

dialog.setContentView(R.layout.custom_dialog);
dialog.setTitle("Custom Dialog");

TextView text = (TextView) dialog.findViewById(R.id.text);
text.setText("Hello, this is a custom dialog!");
ImageView image = (ImageView) dialog.findViewById(R.id.image);
image.setImageResource(R.drawable.android);
Everything covered so far should be familiar from previous posts.  The next bit is the key bit for displaying a custom dialog.  It is step 3 and is inflating the xml layout.

Step 3 is inflating the xml layout
AlertDialog.Builder builder;
AlertDialog alertDialog;

Context mContext = getApplicationContext();
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.custom_dialog,
                               (ViewGroup) findViewById(R.id.layout_root));

TextView text = (TextView) layout.findViewById(R.id.text);
text.setText("Hello, this is a custom dialog!");
ImageView image = (ImageView) layout.findViewById(R.id.image);
image.setImageResource(R.drawable.android);

builder = new AlertDialog.Builder(mContext);
builder.setView(layout);
alertDialog = builder.create();
The line highlighted in yellow is the line I had to correct.  I had to replace


LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(LAYOUT_INFLATER_SERVICE);

with


LayoutInflater inflater = (LayoutInflater) myActivity.getSystemService(LAYOUT_INFLATER_SERVICE);


I will leave you to mull over the details of this post and see if you can create your own custom dialogs.  If you have any issues then please get in touch.



Friday 20 July 2012

Creating alerts

In this post we will learn how to create alerts.  You can see an example of an Alert Dialog in my Maths Test App (If you have not already downloaded it, then locate the Maths Test App by searching the Android Market / Google Play for "Sundev Pabla").

In the Maths Test App I use an alert to inform the user if they enter a game duration of less than 10s - originally all I wanted to do was handle the situation where the  user enters a null duration but then I decided to force the user to play for a minimum of 10s.  In order to set the Game Duration press the menu button before starting the game and select 'Set Game Preferences'.  The following code extract is taken from my Maths Test App:


            if (cUserPreferences.gameDuration < 10)
            {
            AlertDialog.Builder builder = new AlertDialog.Builder(myActivity);
            builder.setTitle("Warning")
            .setMessage("You entered a game duration of less than 10s. Your game duration has been defaulted to the minimum value of 10 seconds.")
            .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                 public void onClick(DialogInterface dialog, int which) {
                  cUserPreferences.gameDuration = 10;
                 }
              });
          AlertDialog alert =builder.create();
          alert.show();
         
            }

In the above extract I first check if the user has entered a game duration of less than 10 (If the user entered a null duration then I have already set the game duration to zero in order to force entry into the if block).  In the if block I create an instance of the AlertDialog.Builder class and use it to set the title of my alert dialog to "Warning", I then also use it to set the message I want displayed to the user.  The builder  is also used to create an ok button with a button click listener.  When the user clicks the "OK" button I set the game duration to 10s.  Finally I use the builder to create my alert dialog and then call show on the alert dialog.

I think this is enough for today, I will leave you to have a play with Alerts and next time we will look at displaying custom dialogs to the user (like  the one I use to get user preferences in the Maths Test App).

All the best until next time.

Saturday 14 July 2012

Disabling menu options when they are not applicable

In the last post we learned how to present the user with menu options when they press the menu button on their phone.  Today we will look at how to disable menu options when they are not applicable.  For example in my Maths Test App, I do not want the user to be able to change Game Preferences in the middle of a game, so I disable the Game Preferences option while a game is in progress (download the Maths Test App from the Android Market / Google Play by searching for Sundev Pabla).

In order to enable and disable menu options at runtime you must override the onPrepareOptionsMenu.  The following extract shows the overridden onPrepareOptionsMenu from my Maths Test App:


    @Override
    public boolean onPrepareOptionsMenu(Menu menu)
    {
    super.onPrepareOptionsMenu(menu);
    // Don't display menu in the middle of a game
    if (!gameOver)
    {
    menu.getItem(0).setEnabled(false);
    }
    else
    {
    menu.getItem(0).setEnabled(true);
   
    }
    return true;    
    }
Essentially what this code is doing is getting the first menu option in my menu collection and either enabling or disabling the menu option depending on the state of the game (In the case of my Maths Test App, I only have one Menu Option so I know it will be the first one in the collection - 0 is used because the collection of menu items is zero based).

Its been a fairly small lesson today, but I believe in doing things in small bite size chunks.  Join me next time to learn how to present the user with custom dialogs and alerts (For example take a look at the dialog that is displayed when the user selects the 'Set Game Preferences' menu option on my Maths Test App).

Good bye for now.

Sunday 8 July 2012

Displaying menu options when the user presses the menu button on their phone

Today we will look at how to add menus to your Android App.  In the latest version of my Maths Test App (If you haven't already downloaded it, then download it now by searching for 'Sundev Pabla' on the Android Market) the user is presented with a "Set Game Preferences" menu option when they press the menu button on their phone.

Creating a menu using xml

Like user interfaces (layouts), menus are also defined in xml files.  The following xml defines the one menu option for my Maths Test App:


<?xml version="1.0" encoding="utf-8"?>
<menu
  xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/menu_setPreferences"
    android:icon="@android:drawable/ic_menu_preferences"
    android:title="Set Game Preferences"></item>  
</menu>

In the xml file I am giving the menu option an id, so that I can refer to it in code, I'm setting an icon for the menu option and I am setting the title displayed to the user for the menu option.

Loading the Menu by overriding the onCreateOptionsMenu function

To load your menu, you must override the onCreateOptionsMenu function in your code.  The following code extract is the onCreateOptionsMenu for my Maths Test App:



    @Override
    public boolean onCreateOptionsMenu(Menu menu)
    {
    super.onCreateOptionsMenu(menu);
    MenuInflater mi = getMenuInflater();
    mi.inflate(R.menu.main_menu, menu);
    return true;
    }

The MenuInflater is used to load the menu.  In my case the xml file is called main_menu.xml and is located in res/menu folder in the project and can be accessed from the R class as shown in the extract above.

Handling the selection of a menu option by overriding onMenuItemSelected function

In order to handle a user clicking on a menu option you must override the onMenuItemSelected function. This function is called when the user clicks on a menu option, an object of type MenuItem is passed into the function and can be interrogated to determine which menu option the user clicked on.  The following code extract is the onMenuItemSelected function for my Maths Test App:


    // Handle selection of menu item
    @Override
    public boolean onMenuItemSelected(int featureId, MenuItem item)
    {
    switch(item.getItemId())
    {
    case R.id.menu_setPreferences:
    cUserPreferences.handlePreferenceSettings(this);

    }
    return super.onMenuItemSelected(featureId, item);
    }
In this function I check the id of the menu item/option clicked by the user and then use a case statement to handle the option clicked by the user (I only have the one menu option, so I didn't need to check the id or use a case statement, but this way I have future proofed my app in case I add in more menu options in the future.).  When the user clicks the menu option I call a function called handlePreferenceSettings - in this function I display a dialog to the user in which they can set their game preferences.    More on custom dialogs in a future posts - for now just have a play with creating menu options.  See if you can use what you have learnt above to present menu options to a user, maybe you could use Google to work out how to display a dialog to the user when they select a menu option. Good luck and all the best until next time.



Thursday 5 July 2012

Moving Forwards

As per last time apologies for the lack of posts.  What with the day job, family and having to actually do some Android Programming to write a blog about it - things can get a bit hectic.

In my last post the excuse for the lack of posts was that I had been increasing my presence on the Android Market.  I had done this by creating Addition, Subtraction, Multiplication and Division only variants of my Maths Test app which asks random Maths questions.  In addition to believing that it would be beneficial to increase my presence on the Android Market, I also believed there would be demand for these variants of the apps because you may want to start a child going with addition before moving on to subtraction, multiplication and division.  There was next to no new learning of Android concepts in creating these variants of the Maths Test app, thus the lack of posts because I had learnt nothing new to tell you about.

This time the excuse for lack of posts is that I have been learning new Android concepts.  I have done this by increasing the functionality of the original Maths Test app.  The functionality has actually been increased to a level where the four variants I had created are now obsolete and have been removed from the Android Market.  The latest version of Maths Test on the Android Market boasts the following functionality.

  • Duration of the game is now user specified (Guess what I used to get bored playing the game for 3 minutes as well).
  • The user can now choose from the following game types (Addition, Subtraction, Multiplication, Division and Random).  This is what has made the variants of Maths Test obsolete and prompted me to remove them from the Android Market.
  • The user can now choose from 5 different levels ranging from Very Easy to Very Hard.
  • A new scoring system has been introduced and user feedback has been improved.  The feedback now tells you how many questions you got correct, how many you got wrong and a score calculated using the following formula: 
(Correct Answers - Wrong Answers) * (60/Game Duration in Seconds)

In improving the functionality of the Android App I have learnt some new Android concepts and will be telling you about these in forthcoming posts.  The new concepts I have learned include the following:
  • Displaying menu options when the user presses the menu button on their phone
  • Disabling menu options when they are not applicable
  • Creating custom dialogs to get user input
  • Displaying dialogs and alerts to the user
For now go and search 'Sundev Pabla' on the Android Market.  Download the latest version of Maths Test and spend some time playing with the app.  This way you will have a better idea of what I am talking about in subsequent posts.  Enjoy playing Maths Test.  As always if you have any questions, advice or want a chat about Android then please get in touch.