Getting Started with Android Development – Part 2

This is a blog post by iOS Tutorial Team member Ali Hafizji, an iOS and Android developer living in India. This tutorial is a continuation of Getting Started with Android Development, this site’s first foray into developing for a non-Apple platform! Check it out if you haven’t already. If you were following along last time, […] By Ray Wenderlich.

Leave a rating/review
Save for later
Share
You are currently viewing page 2 of 3 of this article. Click here to view the first page.

Editing Quotes

When it comes to editing a quote in QuoteReader, there are two steps. The first is changing the actual text of the quote. The second is changing the full-size image displayed above the quote.

Step 1: Editing the Text

First and foremost, to edit a quote you need to use EditText, which is simply an editable version of TextView. To use EditText, first open res\layout\quote_details.xml and change the TextView to EditText.

We’ll also make some tweaks to some of the parameters and change the layout to a LinearLayout. Modify the file so the final layout looks like this:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >
    <LinearLayout 
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content"
        android:orientation="vertical">        
        <ImageView
            android:id="@+detail/image"
            android:layout_width="fill_parent"
            android:layout_height="350dip"
            android:layout_marginLeft="5dip" />        
        <EditText 
            android:id="@+detail/quote"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:inputType="text"
            android:textSize="24dip"
            />        
    </LinearLayout> 
</ScrollView>

OK, time to test this out! First make some changes to QuoteDetail.java:

// Change mQuote from TextView to EditText
private EditText mQuote;

// Delete line creating mDataSource variable and add this instead
private DataSourceItem mItem;

// Change cast of mQuote to an EditText
mQuote = (EditText) findViewById(R.detail.quote);

// Replace lines setting imageView and Quote with this
mItem = DataSource.getDataSourceInstance(this).getmItemsData().get(mPosition);
mImageView.setImageBitmap(mItem.getmHdImage());
mQuote.setText(mItem.getmQuote());

And make the following changes to QuoteReaderActivity.java:

// Replace line creating mDataSource in QuoteAdapter constructor
mDataSource = DataSource.getDataSourceInstance(mContext);

// Replace lines setting thumbnail and quote in getView
thumbnail = (ImageView) convertView.findViewById(R.list.thumb);
thumbnail.setImageBitmap(mDataSource.getmItemsData().get(position).getmThumbnail());
quote = (TextView) convertView.findViewById(R.list.text);
quote.setText(mDataSource.getmItemsData().get(position).getmQuote());

Now compile and run the program. You’ll notice that when you enter the detail page, you’re presented with a keyboard to enter text for the quote. You can type whatever you like, but if you navigate back to the QuoteReader activity (by tapping your back button on your device), you’ll notice your changes didn’t actually take effect.

To make the changes permanent, you need to modify the entry in the data source. To do this you need to create a listener to give a callback as soon as the user has finished editing the text. Once you know that the user has finished editing, you can change the quote in the respective item of the data source.

Add the following lines to QuoteDetail.java at the end of the onCreate method:

mQuote.addTextChangedListener(new TextWatcher() {

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        mItem.setmQuote(s.toString());
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count,
            int after) {

    }

    @Override
    public void afterTextChanged(Editable s) {

    }
});

Notice the addition of TextChangedListener to EditText. This listener gives three callbacks, but the most significant is onTextChanged, which is fired as soon as the user finishes editing the quote.

Build and run the project. Try editing a quote. Now you’ll notice that the quotes list isn’t updating. That is, you can edit a quote from the detail page, and the edits will be preserved there, but when you return to the quotes list you will see only the original, unchanged quotes.

The problem is that the list adapter does not realize the data source has changed. So all you need to do is tell the list adaptor about the new data set and the list view will be refreshed.

To do this add, implement the onResume method in QuoteReaderActivity.java like the following:

@Override
protected void onResume() {
    super.onResume();
    if(mListView != null) {
        QuoteAdapter adapter = (QuoteAdapter) mListView.getAdapter();
        adapter.notifyDataSetChanged();
    }
}

Build and run the project. Everything should now work correctly!

Modifying text in a list view on Android

Step 2: Editing Full-Size Images

To edit the image shown to the user in the detail page, you’re going to allow the user to navigate to the gallery app, select an image and use that image in place of the one shown. This is why you’re using bitmaps instead of resource ids in the DataSourceItem class.

First set up a click listener to listen for click events on the ImageView.

Make the following changes to QuoteDetail.java:

Add the following lines to the QuoteDetail class in the onCreate method:

// Add new private constant variable
private static final int SELECT_PHOTO = 100;

// Add to end of onCreate
mImageView.setOnClickListener(new View.OnClickListener() {

    @Override
    public void onClick(View v) {
        Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
        photoPickerIntent.setType("image/*");
        startActivityForResult(photoPickerIntent, SELECT_PHOTO);
    }
});

To launch the gallery app, you first send out an intent. Notice the use of “ACTION_PICK ” to create the intent. This will launch the gallery app such that it will allow the user to pick a single image. The type of the intent is also set to “image/*” to specify the type of data to return: in this case, just an image.

Note: If the user has any other app that can handle the ACTION_PICK intent and return an image, Android will display a selection menu so that the user can choose which app to use.

A function called onActivityResult is called automatically when the user picks an image. You need to override that method to get the image the user picked to display.

So add the following lines to QuoteDetail.java:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    switch(requestCode) { 
    case SELECT_PHOTO:
        if(resultCode == RESULT_OK){  
            Uri selectedImage = data.getData();

            try {
                InputStream imageStream = getContentResolver().openInputStream(selectedImage);
                Bitmap yourSelectedImage = BitmapFactory.decodeStream(imageStream);
                mItem.setmHdImage(yourSelectedImage);
                mImageView.setImageBitmap(yourSelectedImage);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }
    }
}

The Intent that is passed to onActivityResult can be used to get the URI of the selected image. A URI is a unique ID that can be used to identify a resource. The code above uses the URI to get the bitmap of the image, and that bitmap is set as the source of your ImageView. The same bitmap is also set as the full-size image to be used for the quote in the DataSource.

Time to build and run again! You should now be able to edit both the text and the image of each quote.

Adding Rating Bars

Android has a view called RatingBar, provided by the SDK. You’re now going to take advantage of it.

Open the quote_detail.xml file and add the RatingBar view. The numStars parameter indicates the total number of stars used by the rating bar. Set it to 5.

The layout file contents are show below.

<?xml version="1.0" encoding="utf-8"?>
<ScrollView
	xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="fill_parent"
	android:layout_height="fill_parent">
	<LinearLayout 
		android:layout_width="fill_parent" 
		android:layout_height="wrap_content"
		android:orientation="vertical">
		<ImageView
			android:id="@+detail/image"
			android:layout_width="fill_parent"
			android:layout_height="350dip"			
			android:layout_marginLeft="5dip" />
		<RatingBar
		    android:id="@+id/rating_bar"
		    android:layout_width="wrap_content"
		    android:layout_height="wrap_content"
		    android:numStars="5" />
		<EditText
			android:id="@+detail/quote"
			android:layout_width="fill_parent"
			android:layout_height="wrap_content"
			android:inputType="text"
			android:textSize="24dip" />
	</LinearLayout>
</ScrollView>

Then open up QuoteDetail.java and make the following changes:

//Create a new variable for this view
private RatingBar mRatingBar;

// Add the following lines to the end of the onCreate method:
mRatingBar = (RatingBar) findViewById(R.id.rating_bar);
mRatingBar.setRating(mItem.getmRating());
mRatingBar.setOnRatingBarChangeListener(new RatingBar.OnRatingBarChangeListener() {

    @Override
    public void onRatingChanged(RatingBar ratingBar, float rating,
            boolean fromUser) {
        //write the rating back to the data source :]
        mItem.setmRating(rating);
    }
});

Here you find the view by the ID you set up in the XML file, set the initial rating, set up an event listener to detect when the rating changes, and update the view correspondingly.

Build and run. You should now have an awesome-looking rating bar for each quote!

Contributors

Over 300 content creators. Join our team.