5COSC005W - Tutorial 9 Exercises
As part of this tutorial for this week, you should complete ALL the tasks described in the following links and specifications: (make sure that you ask questions to your tutor for anything that you do not understand or if you are stuck at any point):
1 Options Menus
a) Implement an Android application which contains an actions overflow
menu with two entries: Settings and Options2 which when
selected they create a pop up Toast
with their name:
b) Add a Favourites icon in the main app bar options menu (not the overflow menu) which is always displayed and when clicked in displays a toast message:
2 Contextual Menus
Extend the application so that it contains a textview with a contectual menu containing 2 entries Edit and Share:
Choosing option Edit
should display a dialog with 2 options:
Choosing option Share
should send some random text to an application
that the user can choose from (hint: use an impliciti intend with an
ACTIONSEND).
3 Contextual Action Bars
Modify the application so that the textview created uses a contextual action bar instead displaying an edit icon which when selected it displays the same dialog to the user as the one displayed with the Edit entry above in the implementation of contextual menus:
4 Popup Menus
Add an ImageView
in your application so that displays one of the
images which are included with the assets of Android studio as in the
image above. The image view should be associated with a popup window
displaying 2 user options Forwards and ReplyAll (they do not need
to do anything once chosen):
5 The DatePicker
Add a button to the application so that when it is clicked it
displays a DatePickerDialog
.
When the user clicks on the OK button a Toast
is displayed with
the selected date in the format day/month/year
, e.g. 14/3/2021
:
6 The TimePicker
Add a button so that the application displays a TimePickerDialog
when it is clicked. Once the user picks up a time, a toast with the
time is displayed.
7 Solutions
The main activity MainActivity.java
:
package uk.ac.westminster.menustest; import android.content.DialogInterface; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.view.ActionMode; import android.view.ContextMenu; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.ImageButton; import android.widget.PopupMenu; import android.widget.TextView; import android.widget.Toast; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; import androidx.fragment.app.DialogFragment; public class MainActivity extends AppCompatActivity { TextView tv; ImageButton bt1; ActionMode mActionMode; android.view.ActionMode.Callback mActionModeCallback; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mActionModeCallback = new ActionMode.Callback() { @Override public boolean onCreateActionMode(ActionMode actionMode, Menu menu) { actionMode.getMenuInflater().inflate(R.menu.menu_context_bar, menu); return true; } @Override public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) { return false; } @Override public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) { switch (menuItem.getItemId()) { case R.id.edit_option: editNote(); actionMode.finish(); return true; default: return false; } } @Override public void onDestroyActionMode(ActionMode actionMode) { mActionMode = null; } }; tv = findViewById(R.id.tv); registerForContextMenu(tv); bt1 = findViewById(R.id.button_popup); bt1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { PopupMenu pop = new PopupMenu(MainActivity.this, bt1); pop.getMenuInflater().inflate(R.menu.menu_popup, pop.getMenu()); pop.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem menuItem) { switch (menuItem.getItemId()) { case R.id.forward: return true; default: return false; } } }); pop.show(); } }); /*** Comment out this segment of code to use a contextual menu instead of the * contectual action bar *****/ tv.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View view) { if (mActionMode != null) return false; else { MainActivity.this.startActionMode(mActionModeCallback); return true; } } }); /*** segment of code for contextual action bar ends here ***/ } @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.option_favourites: showFavourites(); return true; case R.id.option_settings: showSettings(); return true; default: return super.onOptionsItemSelected(item); } } void showFavourites() { Toast t = Toast.makeText(this, "Favourites shown", Toast.LENGTH_SHORT); t.show(); } void showSettings() { Toast t = Toast.makeText(this, "Settings shown", Toast.LENGTH_SHORT); t.show(); } @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); getMenuInflater().inflate(R.menu.menu_context, menu); } @Override public boolean onContextItemSelected(MenuItem item) { if (item.getItemId() == R.id.context_edit) { editNote(); return true; } else if (item.getItemId() == R.id.context_share) { shareNote(); return true; } else return super.onContextItemSelected(item); } void editNote() { AlertDialog.Builder dialog = new AlertDialog.Builder(this); dialog.setTitle("Edit choice22727"); dialog.setPositiveButton("OK", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { } }); dialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { } }); dialog.show(); } void shareNote() { Intent i = new Intent(Intent.ACTION_SEND); i.setType("text/plain"); i.putExtra(Intent.EXTRA_TEXT, "gsutytygsg"); i = Intent.createChooser(i, "Report from app"); startActivity(i); } public void onDateClick(View view) { DialogFragment df = new DatePickerFragment(); df.show(getSupportFragmentManager(), "datepicker"); } public void showSomething(int year, int month, int day) { Toast t = Toast.makeText(this, "" + day + "/" + month + "/" + year, Toast.LENGTH_SHORT); t.show(); } }
The layout file activity_main.xml
:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity"> <TextView android:id="@+id/tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="24sp" android:layout_gravity="center" android:text="TextView with a Contextual menu" /> <ImageButton android:id="@+id/button_popup" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:src="@drawable/ic_action_popup" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text="Click me" android:textSize="24sp" android:onClick="onDateClick"/> </LinearLayout>
The menu files are below (they need to be placed under the res/menu/
directory.
The menu_main.xml
file:
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" > <item android:id="@+id/option2" android:title="Option2" android:orderInCategory="90"/> <item android:id="@+id/option_settings" android:title="Settings" android:orderInCategory="60" android:icon="@drawable/ic_action_settings"/> <item android:id="@+id/option_favourites" android:title="Favourites" app:showAsAction="ifRoom" android:icon="@drawable/ic_favourites" android:orderInCategory="30" /> </menu>
The menu_context
file:
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/context_edit" android:title="Edit"/> <item android:id="@+id/context_share" android:title="Share" /> </menu>
The menu_context_bar.xml
file:
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/edit_option" android:title="Edit" android:icon="@drawable/ic_action_edit"/> </menu>
The menu_popup.xml
file:
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/forward" android:title="Forwards" /> <item android:id="@+id/replyall" android:title="ReplyAll"/> </menu>
The DatePickerFragment.java
file:
package uk.ac.westminster.menustest; import android.app.DatePickerDialog; import android.app.Dialog; import android.os.Bundle; import android.widget.DatePicker; import androidx.annotation.NonNull; import androidx.fragment.app.DialogFragment; /** * A simple Fragment subclass. */ public class DatePickerFragment extends DialogFragment implements DatePickerDialog.OnDateSetListener { @NonNull public Dialog onCreateDialog(Bundle savedInstanceState) { return new DatePickerDialog(getActivity(), this, 2019, 2, 14); } @Override public void onDateSet(DatePicker datePicker, int i, int i1, int i2) { MainActivity activity = (MainActivity) getActivity(); activity.showSomething(i, i1, i2); } }
8 Dealing with a TimePicker
Extend the application so that at the bottom it displays an additional
buton called Time. The button is associated with a
TimePickerDialog
. When the user selects a time in the dialog, the
selected time is displayed in a TextView
at the bottom of the main
activity.
9 Adding new Items in the Options menu.
Extend the application so that it displays an additional menu item (choose an icon of your choice) next to the "Favourites" item. When the item is clicked, it should open a browser displaying your favourite URL. (Hint: use an implicit intent, something we covered in Week 3).
10 Persisting Settings in an Application
Modify the application so that the Settings option found in the
overflow menu displays a date dialog picker which then user can use to
select the date of the birthday of his/her best friend. The date
should be persisted as part of the application settings (use
SharedPreferences
) so that the next time that the application
restarts the birthday of the user's best friend is displayed.