Skip to the content.
This is the Spring 23 final website.

as2: Layout

Last revised: 4 April, 2023
Assigned:
  • Part 1-5 Wed 5-Apr
Due:
  • Part 1-2 Checkpoint 10:00 pm, Wed 12-Apr
  • Part 3-4 (Code) & Part 5 (Reflection) 10:00pm, Thur 20-Apr

HCI Goals:

  • Use interactor hierarchies for application design and implementation
  • Create concise and efficient constraints to build responsive layouts
  • Apply the theory of layout design to build complex layouts
  • Design, develop, and implement reusable layouts
  • Apply understanding of scrolling and how varying layout sizes can influence screen display

Android Goals:

  • Develop a generalizable and reusable layout for any number of images
  • Use Android layout GUI, XML, and Android programmatic layout API appropriately
  • Apply Android constraints implementation
  • Proficiently and accurately handle portrait vs. landscape orientation and fixed vs. variable sized container views
  • Successfully use layout Inflators, and analyze which inflation method is appropriate for the given situation.

Turn-in links

Assignment Description

For this assignment, you will be exploring multiple ways to build layouts in Android, in particular creating subclasses of ViewGroup that can be reused across an app.

Scroll down to the development strategies sections for some tips curated from past students!

App Overview

The final app for this assignment has five tabs, roughly corresponding to the four parts of the assignment with an additional prebuilt “testbench” tab.

Inheritance Hierarchy

Like Doodle, our app is divided into multiple tabs using a BottomNavigationView. However instead of switching between Activity objects, we’re switching between View objects. CaptionedImageView, ImageListView, and TwoColumnLayout each inherit from various subclasses of ViewGroup. CustomInterfaceView inherits from a ConstraintLayout to allow for the most flexibility in your creative portion of this assignment.

In this class diagram, classes in blue are part of the Android SDK.

classDiagram AppCompatActivity <|-- MainActivity FrameLayout <|-- CaptionedImageView ScrollView <|-- ImageListView ViewGroup <|-- TwoColumnLayout ConstraintLayout <|-- CustomInterfaceView ViewGroup <|-- FrameLayout FrameLayout <|-- ScrollView ViewGroup <|-- ConstraintLayout cssClass "AppCompatActivity,ViewGroup,FrameLayout,ConstraintLayout,ScrollView" androidClass link AppCompatActivity "https://developer.android.com/reference/androidx/appcompat/app/AppCompatActivity" "Open Android Documentation" link FrameLayout "https://developer.android.com/reference/android/widget/FrameLayout" "Open Android Documentation" link ScrollView "https://developer.android.com/reference/android/widget/ScrollView" "Open Android Documentation" link ViewGroup "https://developer.android.com/reference/android/view/ViewGroup" "Open Android Documentation" link ConstraintLayout "https://developer.android.com/reference/androidx/constraintlayout/widget/ConstraintLayout" "Open Android Documentation"

Part 1

Tasks:

For Part 1 you will be building a scrollable list of images with XML. Your layout must look equally nice horizontally and vertically. You will use constraints to achieve this, using the ConstraintLayout we provide in part1.xml. part1.xml can be found in the res/layout directory in Android Studio once the layout project has been opened.

The result should look like this:

Portrait screenshot for part 1 Landscape screenshot for part 1

When it comes to layout, working directly with XML can be a pain, especially when there are several attributes to keep track of on each element. Luckily, Android Studio provides a visual editor that you can use to build your app layout. You may find it helpful to switch back and forth between the visual editor and the XML.

In part1.xml you will accomplish the following:

This video shows Part 1 in action:


A (slightly simplified) view of the interactor hierarchy for Part 1 is shown below. Two notes about the interactor diagrams in this specification:

graph LR subgraph activity_main.xml R(ConstraintLayout) --> F[FrameLayout] R --> T[TabView] end subgraph part1.xml F --> S[ScrollView] S --> C[ConstraintLayout] C --> I1[ImageView] C --> I2[ImageView] C --> I3[ImageView] C --> I4[ImageView] C --> I5[ImageView] end classDef greenlarge fill:#dbf0db,stroke:#333,stroke-width:2px,font-size:16px,padding:0px,height:50px,top:1px; classDef bluelarge fill:#99ccff,stroke:#333,stroke-width:4px,font-size:16px,padding:0px,height:50px,top:1px; classDef groupSubgraph fill:#EEE,stroke:#000 class R,F,T,S,C greenlarge class I1,I2,I3,I4,I5 bluelarge class activity_main.xml,part1.xml groupSubgraph

We can represent this same interactor hierarchy visually in a Layout Wireframe. An example of a Layout Wireframe for Part 1 is shown below which details the visual nesting of the interactors, and margin spacing between the interactors. Layout Wireframe diagrams are a design tool to help you visualize how your app will function programatically. For instance, in this sample, we can see that you will only be adding images inside the ConstraintLayout. (Note: this layout diagram should be more detailed and also include labels for the ImageView and other objects).

This Layout Wireframe highlights that you will only be configuring the ImageViews as they relate to the ConstraintLayout(shown in blue). Note that this Layout Wireframe is simplified representation of what you would see in the Layout Inspector.

Reference image for parts 1 and 2 showing how each image is staked vertically with image_margin space on every side; below; above; and between images

You will be drawing Layout Wireframes for Part 4 of assginment as well in other parts of this course. The Layout Wireframes you produced must be more complex than what you see here. You will be expected to explicitly label each View, layout container, spacing, etc, and as well as specify any relevant information about orientation (such as Vertical vs Horizontal LinearLayout).

Part 2

In Part 2 you will create two custom layout classes (subclasses of ViewGroup):

In this way you will demonstrate two ways to make generalizable layout classes that can be reused across an app.

The CaptionedImageView and ImageListView starter code can be found in the cse340.layout directory in Android Studio.

CaptionedImageView

CaptionedImageView will build its layout by inflating from an XML file (captioned_image.xml). Inflating is the process of converting view hierarchies specified in an XML file into Java objects that can be displayed and interacted with. This is exactly what was done by MainActivity to display your part1.xml. By doing the inflation within a View class, you can reuse the same layout simply by creating instances of that class.

CaptionedImageView inherits from FrameLayout. captioned_image.xml should use a ConstraintLayout to arrange the image and text. The resulting interactor hierarchy will look like this:

graph LR CaptionedImageView --> ConstraintLayout ConstraintLayout --> ImageView ConstraintLayout --> TextView

Tasks:

The Part 2 section of the testing tab, showing two captioned images of animals

ImageListView

ImageListView will build its layout by creating View objects programmatically in Java code. This allows you to add any arbitrary number of images, not limited by what has been defined in XML.

ImageListView inherits from ScrollView. For Part 2, it should create create a child LinearLayout programmatically, and add CaptionedImageViews to that LinearLayout. The resulting interactor hierarchy will look like this:

graph LR ImageListView --> LinearLayout LinearLayout --> CI1[CaptionedImageView] LinearLayout --> CI2[CaptionedImageView] LinearLayout --> CI3[CaptionedImageView]

Tasks:

The third tab, showing a series of captioned images of animals

Reminder: Turn in your completed Part 1 and 2 to the appropriate Gradescope assignment for your check point. The course staff will give quick feedback about the correctness of part 1-2 while you are completing the balance of your assignment.

Part 3

In Part 3 we will create a custom Layout class in that can organize an arbitrary series of Views into a Pinterest-like arrangement. Pinterest is a great example of a high-profile app that can be built with relatively simple layout instructions. Your implementation, TwoColumnLayout, will be a custom ViewGroup that can be used similarly to other layout classes like LinearLayout: you assign child views either with XML or programmatically, and the View arranges those children according to rules which you will define.

Screenshot of pinterest layout from https://newsroom.pinterest.com/en

The TwoColumnLayout starter code can be found in the cse340.layout directory in Android Studio.

Child Views are organized into one of two columns of equal width. To determine which column a child View should go in, we use “pinterest” ordering. You must track the height of the Views in each column and add the next View to the shorter column (or the left column if equal).

Screenshot of part 3    Screenshot of part 3 scrolled

Note that the aspect ratio of child Views may vary (they may have an arbitrary width and height). For this reason, you will need to measure the Views’s height once it is scaled to fit within the width of its column.

Since the TwoColumnLayout determines both the sizes and positions of its child Views, you must implement both the measure and layout stages of the measure-layout-draw sequence. You will do this by overriding the onMeasure() and onLayout() methods, which should call measure() and layout() on the View’s children recursively. By implementing both of these methods, your View can respond to both its container’s size, as well as its children’s calculated sizes (for example, images whose heights scale proportionally to their widths).

Keep in mind that similar to Parts 1 and 2, your TwoColumnLayout should be responsive to device orientation. When rotated your layout should maintain the proper positioning (margins, spacing, and aspect ratios should remain the same while Views scale to fill the extra space.)

Demo: Two-Column Layout

Tasks:

It can be very frustrating to write a ton of code only to have the result be a blank screen. Since both onMeasure() and onLayout() must work correctly for any images to appear, you may run into this problem in Part 3. With this in mind, we recommend starting out by trying to display all children in the left column only, then once that’s working moving on to the second column. This will reduce the amount of code you have to write before you get some kind of visual feedback.

The Part 3 section of the testing tab, showing a two-column arrangement of various Views

Part 4

For Part 4 you are to re-create an interface from another popular app such as Twitter, Facebook, Instagram, etc. Most commercial products, however, are very complicated, so this is your chance to be creative in the design and implement your own version of the app. The goal is for you to synthesize what you have learned in class as well as explore other features (such as other types of Common Layouts) that we have not covered in class.

Your layout must meet the following requirements:

The CustomInterfaceView starter code can be found in the cse340.layout directory. It extends from ConstraintLayout to give you maximum flexibility to allow you to add anything you need to achieve your desired design.

You may use the same images that are used in Part 3. If you wish to do so, you should simply call the appropriate method in MainActivity.java. There is a note on how to do this in the CustomInterfaceView constuctor.

And finally, recall that there are four methods for inflating an XML file - research which one is appropriate for your creative layout implementation.

Tasks:

Past students have found the following links helpful in designing and implementing Part 4:

Part 5 (Reflection)

For this part, you will submit your reflection on this assignment to Gradescope. Create a MS Word, Google or other type of document and copy the following questions (in italics below) into that document. Add your responses below each question. You can have more than one answer per page, but if you can, please try to avoid page breaks in the middle of a question. Insert page breaks between questions as needed.

  1. Diagrams and images
    • The Layout Wireframe you drew for Part 4.
    • The interactor hierarchy you drew for Part 4. (Do not turn in a screen shot of the layout inspector for this).
    • A screenshot of the interface you are emulating, in both portrait and landscape mode. You must explicitly specify if the app you are emulating does not have a landscape mode.
    • A screen shot of your final interface in both portrait and landscape mode.
  2. For every interface there are generally multiple ways of laying it out, particularly if the interface is a complicated one. Reflect on your design and implementation of Part 4. What other ways you could emulate the same interface using different ViewGroups/Layouts. What would be the benefits or drawbacks to using these other Layouts?
  3. Many people have migrated away from Twitter to Mastodon, so it seems a good time to analyze it! Perhaps this will give you some good ideas for your (eventual) final project screens. The images below are from three screens from the Mastodon app. Choose one and do the following
    • Specify which screen you chose to analyze and briefly say why you chose that screen.
    • Draw a Layout Wireframe for the portion of the screen you chose. Your Wireframe should contain a minimum of four layouts. It may help to check out the Common Layouts. Briefly justify the reason why you chose those particular layouts.
    • Draw the interactor hierarchy for the portion of the screen you chose. You may indicate repeating patterns of interactors (or groups of interactors) as long as it is clear you defined the first of the repeating set clearly.
    The Mastodon news screen The Mastodon posts screen The Mastodon hashtag screen
    A screenshot of the Mastodon News screen A screenshot of the Mastodon posts screen A screenshot of the Mastodon posts screen
  4. Responsive design is when you create an application that “responds” to dynamic changes in the screen size or orientation of the device. Why are responsive designs important in user interfaces, software development and software engineering, as well as real life applications? Think beyond just an app on a screen…
  5. This class is part theory, part implementation. As such, lecture and section may not have provided you all of the information necessary to complete the layout program. How did you approach the independent learning required to complete this assignment? List at least one resource you used in your learning that would recommend to a friend taking this class in the future.
  6. Acknowledgements: Cite anything (website or other resource) or anyone that assisted you in creating your solution to this assignment. Remember to include all online resources (other than information learned in lecture or section and android documentation) such as Stack Overflow, other blogs, students in this class, or TAs and instructors who helped you during OH.

Testing

Just like in Doodle, we have included screenshot tests which compare all 5 screens of the app with our solution. Again we highly recommend running these tests continuously as you work on each part of the assignment.

Note that the images used for the tests are different than the images you see when you run the app. Instead of animals, you will see abstract rectangles and circles. The purpose of these placeholder images is to reduce noise if your images are placed in slightly different positions than the solution. The replacement images all have the same size as the animal pictures, so the resulting layouts should be identical

Two animal pictures and their corresponding placeholder images

Development Strategies

Rotation buttons on emulated android device

These buttons will allow you to rotate the emulated device clockwise/counter-clockwise.

Code quality and commenting your code

We expect that you will maintain the same Code Quality and Commenting standards as you did with our Doodle assignment. For details please see those sections.

Debugging tips and tricks

private static final String TAG = "Layout";

Log.i(TAG, "Hello world!");

To make full use of Logcat, make sure to configure the priority level (in this case, “Info”) and use the correct tag (in this case, “Layout”). It’s also good to check that you have the correct device/emulator selected.

Note: Remember to take your Log.i debugging calls out of your code before turning it in.

Android Log.* | Using Logcat

Turn in

Code Submission Instructions

We will test layout on emulators with different screen sizes. Please use constraints correctly. Don’t just try to match pixels in our sample screenshots.

You will turn in your source code files to the appropriate Gradescope assignments for Part 1-2 and then for Part 3-4.

We are allowing you to turn in Part 1-2 early for a checkpoint to see how closely you match our tests. You will get 1 point for turning in code that compiles and passes up to half of the tests. If you pass more than half the tests, we will award you 2 points.

Make sure you only edited the following files/directories for submission:

- CaptionedImageView.java
- CustomInterfaceView.java
- ImageListView.java
- TwoColumnLayout.java
- any additional View classes you created
- res/drawable/*
- res/layout/captioned_image.xml
- res/layout/part1.xml
- any additional layouts
- res/values/strings.xml
- res/values/dimens.xml
- any additional CSV files

Note: While you can edit the above files, please do not remove any of the existing drawables, Strings, or dimensions from them.

Do not edit any of the other files that we have given you, do not delete any of the images in the res/drawable folder, and do not delete any existing strings in res/values/strings.xml (you may add bitmaps and strings of course.)

If you add your own images or other files for Part 4, please make sure to add, commit, and push them to your repository in the appropriate directories before turning in your assignment. If your images are not there, your custom layout will not work for others and you will NOT get credit for the work you did.

Note: Large images can be problematic both for running your app and for committing to your gitlab repository (there are size limit imposed on both Gradescope and Allen School resources). If you choose to add your own images, add at most 10MB of data (you will not be able to turn in your assignment in if it is larger than that). One solution is to resize your high resolution images before using them in your creative application.

Reflection submission

The reflection will be turned in to Gradescope.

Grading (50pts)

The Layout assignment will be out of 50 points and will roughly (subject to small adjustments) be distributed as:

Part 1-2 checkpoint (2 pts) Note: this MUST be turned in on time to receive points. No late assignment for part 1-2 will be accepted.

Final checkpoint (48 pts)

IDE Errors/Warnings you can ignore

Note: DO NOT assume that because an error/warning can be ignored for this assignment, it can be ignored for all assignments. ALWAYS check the spec for each assignment before deciding what is OK to ignore.