In the second part of the tutorial we want to create the form to add new books to the library. We also need some mechanism to create new authors. In order to achieve all this, we need to utilize different form elements, that android provides and tweak them a little bit, to do exactly what we want.

The complete source code of this tutorial can be found at: http://androrm.com/src/downloads/book_tutorial.tar.gz.

Creating the form

First of all we need the layout for the form itself. So what do we want to achieve? We want to enter the name of the book. Also the authors should be selectable from a list of all authors, that we know. And last but not least, we also need to buttons. One to show a dialog to create a new author and one to save the book to the database. Entering text is easy. Android provides a class called
EditText
, that will do exactly, what we need. We can also create the item for the authors pretty easy, by using the
Spinner
class. All the other stuff in the following layout file is basically getting the items to their correct position. We use a
TableLayout
so that we can display a label in front of each editor and a
LinearLayout
to place a button at the bottom of the form.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:orientation="vertical">
  
  <LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_weight="1">
  
      <TableLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">
      
        <TableRow
            android:layout_width="fill_parent"
            android:layout_height="wrap_content">
        
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="15dp"
                android:text="Title" />
                
            <EditText
                android:id="@+id/title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:hint="Title..." 
                android:layout_weight="1" />
        
        </TableRow>
      
        <TableRow
            android:layout_width="fill_parent"
            android:layout_height="wrap_content">
        
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="15dp"
                android:text="Author" />
            
            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                android:layout_weight="1">
                
                <Spinner
                    android:id="@+id/spinner"
                    android:layout_width="fill_parent"
                    android:layout_height="wrap_content" />
                    
                <Button
                    android:id="@+id/add_author"
                    android:layout_width="fill_parent"
                    android:layout_height="wrap_content"
                    android:text="New Author" />
            
            </LinearLayout>
        
        </TableRow>
      
      </TableLayout>
  
  </LinearLayout>

  <LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_weight="0">

      <Button
        android:id="@+id/save"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Save Book" />
        
  </LinearLayout>  
  
</LinearLayout>

Setting up the form elements

The
Spinner

Now that we have created the layout, we need to implement the actual
Activity
. Create a plain activity and set its
contentView
to the layout file, we just created. For now, we don't need to change anything on the
EditText
widget. But we want our authors to be displayed in the
Spinner
. In order to achieve this, we have to first query the database for all authors. Do you think SQL right now? Forget it! This line does the job:
mAuthors = Author.objects(getApplicationContext()).all();
Unfortunately android does not support
QuerySets
natively ;) We need to provide the authors, as a list, that it can handle. calling
toList()
on the
QuerySet
does the job. Now we are able to set up the handler android needs in order to show the
Spinner
correctly.
Spinner authors = (Spinner) findViewById(R.id.spinner);
mSpinnerAdapter = new ArrayAdapter(getApplicationContext(), 
                                           R.layout.spinner_item, 
                                           mAuthors);

authors.setAdapter(mSpinnerAdapter);
Now the spinner will show all the authors, we currently have in the database. But what happens, if there are no authors in the database?

Adding authors

If we don't have an author in our database, we want to give the user the opportunity to add a new one on the fly. When a users clicks the "Add new author" button, a dialog should pop open, giving him the possibility, to enter the name of the new author. Achieving this is trickier, than you might think. We have to implement our one
Dialog
class. But luckily the implementation is not very hard.

First of all (as always), we need to define the layout for the dialog. As we only want a very simplistic one, it is not very large.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:padding="15dp"
    android:orientation="vertical">

    <EditText
        android:id="@+id/name"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:hint="Name..." /> 

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" >

    <Button
        android:id="@+id/button_ok"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Save"
        android:layout_weight="1" />

    <Button
        android:id="@+id/button_cancel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Cancel"
        android:layout_weight="1" />

    </LinearLayout>
  
</LinearLayout>
Again, we define an
EditText
, so that the user is able to enter the name of the new author and we add two buttons, ok and cancel, giving him the opportunity to either save the new author or cancel.
public class AddAuthorDialog extends Dialog {

    public AddAuthorDialog(Context context) {
        super(context);
        setContentView(R.layout.new_author_dialog);
        
        setTitle("Add a new author");
        
        registerOkButton();
        registerCancelButton();
    }
    
    private void registerOkButton() {
        final EditText name = (EditText) findViewById(R.id.name);
        Button ok = (Button) findViewById(R.id.button_ok);
        
        ok.setOnClickListener(new View.OnClickListener() {
            
            @Override
            public void onClick(View v) {
                String value = name.getText().toString();
                
                if(value.trim().equals("")) {
                    return;
                }
                
                Author author = new Author();
                author.setName(value);
                author.save(getContext());
                    
                AddBook activity = (AddBook) getOwnerActivity();
                activity.addAuthor(author);
                
                name.setText("");
                dismiss();
            }
        });
    }
    
    private void registerCancelButton() {
        Button cancel = (Button) findViewById(R.id.button_cancel);
        cancel.setOnClickListener(new View.OnClickListener() {
            
            @Override
            public void onClick(View v) {
                dismiss();
            }
        });
    }
    
}
In the
Dialog
class itself, note how the new author is being crated and saved using androrm. Also the owner activity, which is our form is notified, that a new author has been added, so it can update the
Spinner
.
Author author = new Author();
author.setName(value);
author.save(getContext());
    
AddBook activity = (AddBook) getOwnerActivity();
activity.addAuthor(author);
We also had to assure, that no "empty" authors are saved. You see, that we check for an empty
string
before we create and save the
Author
object.

Creating the new book

The last step is very simple. If a user clicks on the
save
button at the bottom of the form, a new book should be created and saved to the database. But before we blindly save books, we first have to check if an author has been selected and if the user has entered a title for the book. If the provided data is correct, we can go ahead and set-up and save the book.
Button saveBook = (Button) findViewById(R.id.save);
    saveBook.setOnClickListener(new OnClickListener() {
    
    @Override
    public void onClick(View v) {
        EditText title = (EditText) findViewById(R.id.title);
        String value = title.getText().toString();
        
        if(value.trim().equals("")) {
            showDialog(NO_TITLE);
        } else {
            if(mSelectedAuthor == null) {
                mSelectedAuthor = mSpinnerAdapter.getItem(0);
            }
            
            Book book = new Book();
            book.setTitle(value);
            book.setAuthor(mSelectedAuthor);
            book.save(getApplicationContext());
            
            resetForm();
        }
    }
});
That's it! You created the form to create new books.
androrm on github Django is a registered trademark of the Django Foundation. Android is a registered trademark of Google Inc.