as5: Menus

Last revised: 9:00pm, Sunday, February 16th, 2020
Assigned:
  • February 19th, 2020
Due:
  • Part 0-3 (programming part)
    - Due February 26th, 2020
    - Lock February 28th, 2020
  • Part 4-5 (analysis part)
    - Due March 2nd, 2020
    - Lock March 4th, 2020

Android Goals:

  • Further practice using callbacks; `onDraw()`
  • Further practice with translate
  • Gain more experience working with callbacks.
  • Further practice with state machines and event handling

HCI Goals:

  • Record user study data
  • Produce plausible experiment results (within expected ranges)
  • Understand pie menus
  • Design your own interactor
  • Collect, parse, and interpret results collected from a study.

Accept the Assignment / Turn-in the Assignment / Review your Submissions

Overview of assignment

This is a two part assignment.

You will create three menus – a linear menu, a pie menu, and a custom menu that you design. You will also test them in an experiment.

The coding re-uses many concepts from ColorPicker. Please start early, and reach out if you find you are spending more than 10 hours.

The user study will include the following: Write your consent form using our template and print out recruit, consent and run 5 participants; Download your data and import it into the spreadsheet we provide; Analyze the data and write the report.

NOTE: If you are unable to finish parts 1-3, you can borrow a phone with working code installed to finish parts 4-5.

Key Files to look at

Classes that have functions and fields you may need (your classes inherit from them)

Other files you may want to look at

Part 0: Overview

Read this spec and take a look at the classes listed above.

You will be implementing a class that can display a pie menu, a class that can display a linear menu, and a custom menu of your design, for use in an experiment comparing which is faster for the user to select menu items from. By menu items we mean the individual items in a menu, such as the number 1 in the sample video.

In this experiment we will have 9 conditions, each of which will include the number of trials (where totalTrials = NUM_REPEATS*ITEM_MAX trials). You can think of this as a three dimensional array

  Menus    
Tasks PIE NORMAL CUSTOM
LINEAR totalTrials totalTrials totalTrials
RELATIVE totalTrials totalTrials totalTrials
UNCLASS totalTrials totalTrials totalTrials
       


The three menu types (specified in an Enum in the code) are PIE (round), NORMAL (linear) and CUSTOM (your custom menu).

The three task types (also an Enum) are LINEAR (menu items such as 1,2,4,8,16,32,64,128) ; RELATIVE (menu items such as Up/UpRight/Right/Down/etc…); and UNCLASS (menu items such as Print/Cast/Bookmark/etc);

The trials are specific combinations of menu item, task type, and menu type. So for example, one trial might involve showing the user a pie menu, with the numbers 1..128 in it, and asking them to select number 3. The participant can select any option, no matter what as soon as they complete a selection, the result is recorded and the next trial begins.

For any given session (one user’s worth of trials), each combination of menu type, task type, and menu item, will be repeated NUM_REPEATS times (NUM_REPEATS is specified in ExperimentSession.java). In addition, for any specific combination of menu type and task type, at most ITEM_MAX items (a total of ITEM_MAX*NUM_REPEATS trials) will be shown to the user. If you set both of these to 1 for testing, you can test all your conditions very quickly. Make sure to set them to the required values for user testing: ITEM_MAX must be at least 4 and NUM_REPEATS must be 3.

In the second half (week 2) of this project, you will recruit 5 friends or students and have them complete one session each. Thus, you will have a total of 5 (participant sessions) * 9 (conditions) * ITEM_MAX*NUM_REPEATS, or 540, data points when you have completed this assignment. You will analyze the data from this experiment in part 2 of this project.

We have implemented in ExperimentSession the code for you to generate all of the trials from a setup file called menuContents.csv found in the assets directory. Make sure that you understand the createTrials() method provided in ExperimentSession.java which sets up conditions for the whole experiment. ExperimentSession is an iterator, so to run the trials for a given session you just use session.next() as long as session.getNext() is true.

Note: that we give the user feedback two ways.

Part 1: Implement MenuExperimentView and MainActivity

Tasks

For this part, you will be working in MenuExperimentView.java and MainActivity. This section will entail defining the functions which power your menu experiment. The MenuExperimentView class includes several methods that you will need to implement. You will implement the state machine logic in onTouchEvent (similar to what you’ve done in ColorPicker).

One tricky thing about context menus – they can appear anywhere in your user interface. To support this, we set things up so that the menu view is going to MATCH_PARENT width and height (i.e. its bounding box is the whole screen). However, the menu itself should show up right where the user presses down. To make this easier for your menus, you will translate the canvas so that they can draw themselves in a logical location given where the finger pressed in onDraw(). Then you will call drawMenu() with this translated canvas, which is what each specific menu implements to draw itself properly.

Handling Touch Events

You will handle touch input by implementing the onTouchEvent method. This is the event handler that is invoked when a touch occurs in this view. The state machine defined in onTouchEvent should work, without changes, for every menu you implement. The only menu-specific code is in essentialGeometry() (it finds the current index). Thus onTouchEvent() is implemented in the parent class, MenuExperimentView and is not changed in the child classes.

MenuExperimentView’s implementation of onTouchEvent makes use of your menu’s essentialGeometry() function to determine the relative position of the user’s finger. Essential geometry will be passed the finger’s position relative to the menu’s (0,0), i.e. where the user pressed. You should implement your linear menu so this is its top left corner, and your pie menu so that the user’s finger is in the center of the pie.

You MUST NOT perform any assignments within essentialGeometry(), as it violates the utility of that function. Instead, essentialGeometry() will return the index associated with the desired view, allowing the function calling it to act on that value.

You need to keep track of two main states: START and SELECTING. When in the SELECTING state you need to distinguish between the event type to determine if the user has selected an option or if they are still in the middle of making a choice.

Relevant touch events include ACTION_DOWN, ACTION_MOVE, and ACTION_UP; think about how these touch events relate to the change and how the UI should respond to these events.

More details about essentialGeometry(), specific to each menu, are below.

graph LR S((.)) --> A((Start)) A -- "Press:startSelection()" --> I(Selecting) I -- "Release:endSelection()" --> E[End] I -- "Drag:updateModel()" --> I classDef finish outline-style:double,fill:#d1e0e0,stroke:#333,stroke-width:2px; classDef normal fill:#e6f3ff,stroke:#333,stroke-width:2px; classDef start fill:#d1e0e0,stroke:#333,stroke-width:4px; classDef invisible fill:#FFFFFF,stroke:#FFFFFF,color:#FFFFFF class S invisible class A start class E finish class I normal

Details for startSelection(), endSelection() and updateModel() can be found in MenuExperimentView. Note that there are no guards on these transitions – any click inside the menu causes it to appear, and once it appears, dragging causes updateModel() to be called no matter where the finger is. Similarly, the menu must be removed when selection ends, and the trial recorded, no matter where the finger is. You do not need to check whether the user clicked on the correct menu item when you call endTrial(). This data will be recorded automatically by ExperimentSession.

Drawing your Menu

Your menu should ONLY BE VISIBLE when you are in the SELECTING state. You can check this in onDraw(). In addition, it needs to redraw whenever something important changes (like the selected item). Be sure to call invalidate() in the appropriate methods of the state machine to make this happen.

For onDraw(), your will do some setup that will allow your subclasses to draw properly. First, you will need to check if you are in the proper state to draw (you should only draw when in the SELECTING state).

Next, you really want to draw from the (0,0) location of the menu, rather than the (0,0) of the parent. But remember that your width and height are set using MATCH_PARENT. To fix this, we need to change the coordinate system of the canvas so that (0,0) is at the startPoint for this interaction.

Finally, since this is an abstract class, we need to call the real drawing method, which our children will implement. This is called drawMenu() and should be overridden by PieMenuView, NormalMenuView, and CustomMenuView. Therefore, your onDraw() implementation in MenuExperimentView.java will be pretty short.

Implementing MainActivity

In MainActivity you will implement part of the method showMenuForTrial(ExperimentTrial trial). Your main job is to register a callback with it that knows what to do when a trial is completed.

MainActivity also needs to implement the code to respond to onTrialCompleted(), a method of the TrialListener interface. In particular, this code should always remove the current menu being shown. Then it should check if the session is over (remember the session is an iterator), and if not call showMenuForTrial() with the next trial. If the session is over, it should update text of InstructionTextView to say that the session is completed, and also display a Toast to the same effect.

Note: This means that until the next session is started, the system should not display any menus if the user clicks.

Part 2: Implement Pie and Normal Menus

Tasks

Both PieMenuView and NormalMenuView extend MenuExperimentView. You will implement essentialGeometry() for each and determine what menu item the touch event maps to. You’ll have to come up with the math logic to map from touch event to an item index.

You will also implement drawMenu() which at a minimum draws the menus as shown in the screenshots. If you want to do something different, you may, as long as the size and position of each menu item does not change. For example, you can override the paint properties defined in MenuExperimentView, position the text differently, or draw more decorations on the menus.

Be sure to check the AbstractMenuExperimentView starter code for any additional values that you should use when creating your menus.

NormalMenuView

For the NormalMenuView, essentialGeometry() will return -1 if the pointer is outside the bounds of the menu in any direction or has moved less than MIN_DIST (inherited from AbstractMenuExperimentView) since interaction started. Otherwise it should return the item number of the menu item that the pointer is currently inside of.

The width of each item in the normal menu is CELL_WIDTH and the height is CELL_HEIGHT.

PieMenuView

For the PieMenuView, essentialGeometry() will return -1 if the pointer has moved less than MIN_DIST since selection started, and otherwise it will return the item number currently being selected. Item number is the menu item that a ray from the center of the menu to the pointer intersects, with the first item being at the top of the pie. The pie menu has no maximum diameter, so anything outside of the radius MIN_DIST around the finger will return a selection.

For PieMenuView, the given RADIUS corresponds to the outer radius. The inner radius is defined by RADIUS - TEXT_SIZE * 2. The radius of the circle in the pie menu is RADIUS - TEXT_SIZE * 2.

Some additional hints for the pie menu

Related APIs

Part 3: Implement a Custom Menu

Create a new menu! Working off of the provided MenuExperimentView interface, build your own third menu. This menu should be different from the Pie/Normal menus. You are encouraged to explore user interactions here, and you will receive credit as long as your code shows significant effort. Your menu does not have to be great here – if you choose, you can aim to create the “worst menu ever” for this submission. Alternatively, you can aim to outcompete our provided menu views!

Be sure to make use of the same abstractions (essentialGeometry() and a state machine) in this implementation.

Part 4: Conduct and Write Up User Study

(not due at the same time as the code portion)

Tasks

Conduct User Study

To finalize the consent form, you will need to copy over the text from our sample consent form and modify it in all of the places marked as such. You should print out two copies of the consent form for each participant – one for them and one for you.

You will need to try out your own program as a participant to fill in the consent form (since you’ll need to know how long it takes). This is also a good time to double check that your data is not lost by downloading it.

Downloading your data

You can use the Android Studio Device File Explorer to access the file. This allows you to directly access the files on your Android device (emulated or physical) through a GUI window.

It will likely be in /storage/emulated/0/CSE340_Menus/TestResult.csv or /sdcard/CSE340_Menus/TestResult.csv`.

Create a clean CSV

You should use the hamburger menu in the app you just implemented to Clear Result CSV before starting your study so that your data does not contaminate your results. Make sure that you do not clear the results between submissions! This will erase your trial data.

Our implementation uses the ExperimentSession object to create, manage, and record experiment data to the CSV. If you are interested, check out the recordResult function on line 213 of ExperimentSession.java (as always, modify at your own risk!)

Recruit participants and have them sign your consent form

You can ask friends or classmates for help. Do not coerce anyone into participating in your study. Make sure they know they have a choice, and have read and signed the consent form. You will be required to turn in signed consent forms with your report. The language used in your consent form is key, so ensure that it does not come off as forceful or coercive.

Collect data

Have each participant complete a session. Once all participants are done, you and download your final data file. It should have at least ITEM_MAX*NUM_REPARTS*NUM_PARTICIPANTS (540) data points in it. You can use the emulator or your phone for this, and any mouse you want. You will need to turn in your final data file with your report.

When collecting data, you should inform users that all interactions will begin with tapping on the center of the screen. This should help avoid cases where your menu is unusable due to the screen format.

Write a Report

You will need to write up a brief report about your study. We have provided a template for you to use here. Please reference this template as necessary when writing this report.

Reflection

Lastly, you should also write a reflection. Please answer the questions separately. Tell us:

Re-read our Properties of People Design Tips for Vision and Motor. Which of these design tips did you employ when creating your Custom menu? List at least one Visual design tip and one Motor design tip.

Given the structure of our Pie/Normal menus, how would you create an accessible menu when working with the MenuExperimentView class? What might be hard about this?

How could you better account for the case where a menu appears off of the phone screen? For instance, if a user attempts to access the Normal menu from the bottom of the screen.

Submission Instructions

You will change the following files:

Part 0-3:

Part 4-5:

Your reflection and report will be uploaded to Gradescope. The code will be submitted to GitGrade.

We will provide a method for submitting the csv file. It should NOT be put in your report.

Grading Rubric

First Half (30 points)

Second Half (30 points)