A few students seem to be using GridViews, and I’ve seen a couple of applications where the order of images is being randomised, and a user has to click on the right one.

A popular kid song plays.  Touch the picture that matches the song.  Compete against the clock to see how fast they can guess the song, or just play for the pure fun of hearing the songs and picking the picture.  I know how to play the music.  How can I display pictures, so that the user can choose?
Adeeb



Using a GridView is often as easy as copy and pasting the example on the Android developer site.

http://developer.android.com/guide/tutorials/views/hello-gridview.html

You’ll have a local copy of this page too, as it came with your SDK documentation.  Here, we are customising an adapter, and overriding getView(), just like we did in the previous example, for the list.

So that sorts out displaying a picture in a GridView, and listening for click events.  What about randomising the order of pictures.  I do this using a mapping array.


protected static final int[][] SHUFFLE = {{1,2,3,0},{3,0,1,2},{2,1,0,3},{0,3,2,1},{2,0,3,1}};

It’s a two dimensional array that maps a position to a randomised position.  The first index is a random number. (You can add more ‘random’ combinations if you wish, eg: {3,1,0,2}, etc. etc…)


reorder = random.nextInt(SHUFFLE.length);

Then access your array like this:-


imageView.setImageResource(PICTURES[SHUFFLE[reorder][position]]);

When the user clicks on a picture, you use the SHUFFLE[reorder] array again to unravel the ‘randomisation’, and check if they have the right answer:-


if (song == SHUFFLE[reorder][position]) {
}

Here is the entire example:-


public class SingAlong extends Activity implements OnItemClickListener {

	protected static final int DECREMENT = 5;
	protected static final int DELAY = 1000;
	protected static final int[] PICTURES = {R.drawable.blacksheep,R.drawable.humpty,R.drawable.rowboat,R.drawable.starsmoon};
	protected static final int[] LYRICS = {R.string.blacksheep,R.string.humpty,R.string.rowboat,R.string.twinkle};
	protected static final int[][] SHUFFLE = {{1,2,3,0},{3,0,1,2},{2,1,0,3},{0,3,2,1},{3,1,0,2}};

	protected ProgressBar progressBar;
	protected Handler handler = new Handler();
	protected GridView gridview;
	protected TextView lyrics;
	protected int progress = 100;
	protected Random random = new Random();
	protected int reorder = 0;
	protected int song = 0;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

        progressBar = (ProgressBar)findViewById(R.id.progress);

        gridview = (GridView)findViewById(R.id.gridview);
        gridview.setBackgroundColor(0xffffffff);
        gridview.setOnItemClickListener(this);

        lyrics = (TextView) findViewById(R.id.lyrics);

        handler.postDelayed(new TickTick(),DELAY);
        newSong();
    }

    protected void newSong() {
    	song = random.nextInt(LYRICS.length); //Which song?
    	reorder = random.nextInt(SHUFFLE.length); //Shuffle pictures
    	progress = 100;
    	progressBar.setProgress(progress);
    	gridview.setAdapter(new ImageAdapter(this));
    	lyrics.setText(LYRICS[song]);
    	playTheMusic(song);
    }

    protected void playTheMusic(int song) {
    	//Play the song.  0=blacksheep, 1=humpty, 2=rowboat, 3=twinkle
    }

    public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
        if (song == SHUFFLE[reorder][position]) {
            Toast.makeText(this, "CORRECT - WELL DONE!", Toast.LENGTH_SHORT).show();
            newSong(); //Play another song again if they get it right
        }
        else {
        	Toast.makeText(this, "no - try again", Toast.LENGTH_SHORT).show();
        }
    }

    protected class TickTick implements Runnable {
   	   public void run() {
   		  progress-=DECREMENT;
   		  if (progress<0) {
   			Toast.makeText(SingAlong.this, "TRY AGAIN", Toast.LENGTH_SHORT).show();
   			newSong();
   		  }
   		  else {
   	   		  progressBar.setProgress(progress);
   		  }
   		handler.postDelayed(this, DELAY);
   	   }
   	}

    protected class ImageAdapter extends BaseAdapter {
        private Context mContext;

        public ImageAdapter(Context c) {
            mContext = c;
        }

        public int getCount() {
            return PICTURES.length;
        }

        public Object getItem(int position) {
            return null;
        }

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

        public View getView(int position, View convertView, ViewGroup parent) {
            ImageView imageView;
            if (convertView == null) {
                imageView = new ImageView(mContext);
                imageView.setLayoutParams(new GridView.LayoutParams(85, 85));
                imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
                imageView.setPadding(8, 8, 8, 8);
            } else {
                imageView = (ImageView) convertView;
            }

            imageView.setImageResource(PICTURES[SHUFFLE[reorder][position]]);
            return imageView;
        }
    }
}

Notice that I’ve used a Handler as a timer, to update a progress bar of remaining time. I introduced this Handler trick to you a couple of days ago. see: https://sagemobile.wordpress.com/2010/09/12/dr-android-answers-threads-and-the-ui/

Here’s the layout file:-

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
<LinearLayout
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_weight="1"
    android:gravity="center" >
<TextView
	android:id="@+id/lyrics"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
	android:textStyle="bold"
	android:gravity="center_vertical|center_horizontal"
	android:textSize="8pt"/>
</LinearLayout>
<LinearLayout
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_weight="1"
    android:gravity="bottom">
<GridView
    android:id="@+id/gridview"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:numColumns="2"
    android:verticalSpacing="10dp"
    android:horizontalSpacing="10dp"
    android:stretchMode="columnWidth"
    android:gravity="center"/>
  <ProgressBar android:id="@+id/progress"
    style="?android:attr/progressBarStyleHorizontal"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"/>
</LinearLayout>
</LinearLayout>
Advertisements