# Hall of Shame (from [CSE 154](https://courses.cs.washington.edu/courses/cse154/19au/lectures/lec05-css-iii-more-layout/index.html#/4)) ![:img Terrible website from gatesnfences.com, 60%, width](https://courses.cs.washington.edu/courses/cse154/19au/lectures/lec05-css-iii-more-layout/images/gatesnfences.png) Thoughts? .footnote[[gatesnfences.com](http://www.gatesnfences.com/)] --- ![:img Windows tablet screen with a grid of interactive squares... icons along the side for invoking menus... and a colorful background picture,70%, width](img/layout/windowsLayout.png) Thoughts? ??? Key Issues - where do components get placed? - how much space should they occupy? --- name: inverse layout: true class: center, middle, inverse --- # Layout I: Introduction to Layout Lauren Bricker CSE 340 Winter 23 --- name: normal layout: true class: --- [//]: # (Outline Slide) # Today's goals - Announcements - Peer reviews - Will be assigned on Canvas Friday night (automatically) for anyone who turns in a video. - Will be assigned manually for anyone who does not submit a video by Saturday morning - Due Sunday night. - Layout will be released soon (part 1-2 due next Wednesday) - Reminder: review the last part of [Animation](/courses/cse340/23wi/slides/wk02/animation.html#35) - Start Layout - Interface tree construction - Using tree for layout - Container components - Android Support for Layouts --- # Why do we need layout? .left-column30[
![:img Color Meter Mac App -- shows the RGB values for whatever pixel the cursor is over, 100%, width](img/layout/colormeter.png) ] .right-column60[ How can you center something? How can you lock it to an edge? How can you design layout that reacts (responds) well to turning your phone? Examples for web - c0FFEE shop with [no layout](https://courses.cs.washington.edu/courses/cse154/19au/lectures/lec05-css-iii-more-layout/code/coffee-shop-starter/coffee-shop.html) - c0FFEE shop with [layout](https://courses.cs.washington.edu/courses/cse154/19au/lectures/lec05-css-iii-more-layout/code/coffee-shop-solution/coffee-shop.html) ] .footnote[from [CSE 154](https://courses.cs.washington.edu/courses/cse154/19au/lectures/lec05-css-iii-more-layout/index.html#/6)] --- # Interface tree construction .left-column30[![:img Color Meter Mac App -- shows the RGB values for whatever pixel the cursor is over, 100%, width](img/layout/colormeter.png)] .right-column60[ Circle all of the interactors in this interface. ] --- # Interface tree construction .left-column30[![:img Color Meter Mac App -- shows the RGB values for whatever pixel the cursor is over, 100%, width](img/layout/colormetercircled.png)] .right-column60[ Circle all of the interactors in this interface. ] --- # What is the interactor hierarchy? .left-column30[![:img Color Meter Mac App -- shows the RGB values for whatever pixel the cursor is over, 100%, width](img/layout/colormeter.png)] ??? naive version --- # What is the interactor hierarchy? .left-column30[ ![:img Color Meter Mac App -- shows the RGB values for whatever pixel the cursor is over, 100%, width](img/layout/colormeter.png)] .right-column60[ A naive approach might look like this:
graph TD W(Window) --> M[Icon:Mag Window] W --> A[Slider:Aperture Size x y w h] W --> C[Menu:Choice x y w h] W --> I[Icon:Color x y w h] W --> T[Text:RGB x y w h] W --> La[Text:Label x y w h] class W green class M,A,C,I,T,La blue
] -- count: false .right-column60[ If we had special (hidden to the user) layouts and interactors to help us with positioning, where might we put the interactors we put them in this tree? ] --- # What is the interactor hierarchy? .left-column30[ ![:img Color Meter Mac App -- shows the RGB values for whatever pixel the cursor is over, 100%, width](img/layout/colormeter.png) ] .right-column60[ Exercise: Add your interactors into the tree (In class worksheet/interactive drawing) ![:img Color Meter Mac interactor hierarchy with just layouts and spacers, 100%, width](img/layout/colormeter-layout.png)] --- # What is the interactor hierarchy? .right-column60[
graph TD W(Window) --> L(LeftSide:DisplayVert) W --> R(RightSide:DisplayVert) L --> Z[Space:Fixed] L --> M[Icon:Mag Window] L --> A[Slider:Aperture Size] L --> Y[Space:Stretchy] R --> C[Menu:Choice] R --> D(RGB DisplayHor) D --> V[Space:Fixed] D --> I[Icon:Color] D --> T[Text:RGB] D --> U[Space:Flexible] R --> Q[Text:Label] class Y,Z,V,U darkblue class W bluegreen class L,R,D green class Z,Y,V,U yellow class M,A,C,I,T,Q blue
] .left-column40[ What information is contained in an interactor hierarchy? ] -- count: false .left-column40[ - z order - position - size - layout hints - event delivery - damage (when to redraw) ... ] -- .left-column40[ What else? ] --- # All of this specified through Views Example: What if you wanted to change background color of all of the buttons to red? ```java for (int i = 0; i < layout.getChildCount(); i++) { view = layout.getChildAt(i); view.setBackgroundColor(Color.RED); } ``` --- [//]: # (Outline Slide) # Today's goals - Interface tree construction - Using tree for layout - **Container components** - Android Support for Layouts --- # Containers can hold views They handle a lot of things for us invisibly - Layout out their children - "Decorating" their children - Deciding who should get input events - Passing down information (such as redraw requests) --- # Container Components in Android .row[ .left-column50[ - Views - Base class for __all__ UI elements - Interactors (e.g buttons, labels, image views, etc) - ViewGroups - Encapsulates one or more views (e.g. Android Components, **Layouts**) - Can define specific **layout** properties ] .right-column50[
graph TD W(ViewGroup) --> V[ViewGroup] W --> V1[View] W --> V2[View] V --> V3[View] V --> V4[View] V --> V5[View] class W,V darkblue class V1,V2,V3,V4,V5 blue
] ] .row[We will use the word *Components* to include both layout components and interactors (Views) since you don't generally "interact" with layouts] --- # Example (Layout Assignment) .left-column50[![:img Picture of Pinterest, 60%, width](img/layout/pinterest-android.png) ] .right-column30[ ![:img Picture of layout part 3, 100%, width](img/layout/pinterest-replica.png) ] ??? This is the kind of stuff we can do thanks to viewgroups --- # Example (Layout Assignment, part 3) .left-column50[ I've highlighted things that are visible (as opposed to just doing layout work)
graph TD C[ViewGroup:ConstraintLayout] C --> Column1[ViewGroup:Column1] C --> Column2[ViewGroup:Column2] Column1 --> V1[View:Fox] Column1 --> V2[View:Squirrel] Column1 --> V3[...] Column2 --> V4[View:Duckling] Column2 --> V5[...] class C,Column1,Column2 blue class V1,V2,V3,V4,V5 darkblue
] .right-column30[ ![:img Picture of layout part 3,60%, width](img/layout/pinterest-replica.png) ] ??? This is the kind of stuff we can do thanks to viewgroups --- # Android's runtime view of the same .left-column30[ VERY IMPORANT debugging tool ![:img Picture of the android studio tools menu with Layout Inspector highlighted, 100%, width](img/layout/layout-inspector-menu.png) ] .right-column60[ ![:img Picture of Part3 of the assignment running with the related interactor hierarchy at right, 100%, width](img/layout/part3-runtime.png) ] --- [//]: # (Outline Slide) # Today's goals - Interface tree construction - Using tree for layout - Container components - **Android Support for Layouts** --- # Demo: Spot the Heron .left-column40[ ![:img Spot the heron low fidelity prototype, 55%, width](img/layout/spottheheron-prototype.png) ] .right-column60[ First design your idea by sketching on a piece of paper. Then use the is Android's GUI layout editor to help you create your app! We'll do this live in class, the next few slides are to help you later. ] -- .right-column60[ If you want to follow along, - clone the starter [Spot the Heron](https://gitlab.cs.washington.edu/cse340/exercises/cse340-spot-the-heron) code. - in the terminal type `git checkout layout` ] --- name: xml-layouts # Designing XML Layouts in Android .left-column50[ ![:img A simple layout on an android watch with a textview and two buttons (save and discard),100%, width](img/layout/layout-demo.png) ] .footnote[These slides are for reference after the demo] ??? This is Android's GUI layout editor Where's the interactor hierarchy here? point out the "space" --- template: xml-layouts count: false .right-column50[ This is Android's GUI layout editor Where's the interactor hierarchy here? - It's the component tree! - The XML is a visual way of specifying the hierarchy that exists once the XML is loaded into the application What are the leaf nodes? Do you see anything unusual? ] ??? point out the "space" --- # What is a spacer? .left-column50[ ![:img A simple layout on an android watch with a textview and two buttons (save and discard),100%, width](img/layout/layout-demo.png) ```xml
``` ] .right-column50[ What is a Space? - Works extra well with layout containers - We can add *struts* - Think of it like a strut in a building - They hold things a fixed distance apart - We can also add *springs* - they push things apart as much as possible ] .footnote[These slides are for reference after the demo] ??? see next slide! --- template: xml-layouts .right-column50[ In this case, they are in a `LinearLayout` - It always has a direction (horizontal or vertical) - And it places its kids, in order, in that direction, within its bounds Where is the linear layout on the screen? ] --- template: xml-layouts .right-column50[ It's the box around 'Save and Discard' - We call this a *Layout Container* - Note: this is not visible in the actual GUI, it's a hidden interactor tree element ] --- template: xml-layouts .right-column50[ A Layout Container can - automate a lot of the layout tasks - make it much simpler to ensure reliable results - use these whenever they do the job - you will implement one for your assignment ] --- # Designing XML Layouts in Android Many layout and other attributes for components. You should explore! ![:img Picture of the whole android layout interface showing the possible components that can be added; the component tree (interactor hierarchy; and the attributes for the Save Button; which is selected, 90%, width](img/layout/design-view.png) .footnote[These slides are for reference after the demo] ??? Talk about how there's many layout and other attributes for components that they should explore! --- # Containers and spacers .row[ .left-column30[![:img Color Meter Mac App -- shows the RGB values for whatever pixel the cursor is over, 100%, width](img/layout/colormeter.png)] ] .row[
graph TD W(Window) --> L(LeftSide:DisplayVert) W --> R(RightSide:DisplayVert) L --> Z[Space:Fixed] L --> M[Icon:Mag Window] L --> A[Slider:Aperture Size] L --> Y[Space:Stretchy] R --> C[Menu:Choice] R --> D(RGB DisplayHor) D --> V[Space:Fixed] D --> I[Icon:Color] D --> T[Text:RGB] D --> U[Space:Flexible] R --> Q[Text:Label] class W bluegreen class L,R,D green class Z,Y,V,U yellow class M,A,C,I,T,Q blue
] --- # Vertical Container Components .row[ .left-column30[ ![:img Color Meter Mac App -- shows the RGB values for whatever pixel the cursor is over, 100%, width](img/layout/colormeter.png) ] .right-column70[ Linear (1D) layout of components - Always layout in the same direction - Places its direct descendants, in order, in that direction ] ] .row[
graph TD W(Window) --> L(LeftSide:DisplayVert) W --> R(RightSide:DisplayVert) L --> Z[Space:Fixed] L --> M[Icon:Mag Window] L --> A[Slider:Aperture Size] L --> Y[Space:Stretchy] R --> C[Menu:Choice] R --> D(RGB DisplayHor) D --> V[Space:Fixed] D --> I[Icon:Color] D --> T[Text:RGB] D --> U[Space:Flexible] R --> Q[Text:Label] class L,R darkblue class W bluegreen class D green class Z,Y,V,U yellow class M,A,C,I,T,Q blue
] --- # Horizontal Container Components .row[ .left-column30[ ![:img Color Meter Mac App -- shows the RGB values for whatever pixel the cursor is over, 100%, width](img/layout/colormeter.png) ] .right-column70[ Same: Linear (1D) layout of components - Always layout in the same direction - Places its kids, in order, in that direction ] ] .row[
graph TD W(Window) --> L(LeftSide:DisplayVert) W --> R(RightSide:DisplayVert) L --> Z[Space:Fixed] L --> M[Icon:Mag Window] L --> A[Slider:Aperture Size] L --> Y[Space:Stretchy] R --> C[Menu:Choice] R --> D(RGB DisplayHor) D --> V[Space:Fixed] D --> I[Icon:Color] D --> T[Text:RGB] D --> U[Space:Flexible] R --> Q[Text:Label] class D darkblue class W bluegreen class L,R,D green class Z,Y,V,U yellow class M,A,C,I,T,Q blue
] --- # Spacers .row[ .left-column30[ ![:img Color Meter Mac App -- shows the RGB values for whatever pixel the cursor is over, 100%, width](img/layout/colormeter.png) ] .right-column70[ - Work extra well with layout containers - *Fixed Space* (struts) hold things a fixed distance apart - *Stretchy Space* (springs) push things apart as much as possible ] ] .row[
graph TD W(Window) --> L(LeftSide:DisplayVert) W --> R(RightSide:DisplayVert) L --> Z[Space:Fixed] L --> M[Icon:Mag Window] L --> A[Slider:Aperture Size] L --> Y[Space:Stretchy] L --> C[Menu:Choice] R --> D(RGB DisplayHor) D --> V[Space:Fixed] D --> I[Icon:Color] D --> T[Text:RGB] D --> U[Space:Flexible] R --> Q[Text:Label] class Y,Z,V,U darkblue class W bluegreen class L,R,D green class Z,Y,V,U yellow class M,A,C,I,T,Q blue
] --- # Some Layout Types in Android .footnote[More on https://developer.android.com/guide/topics/ui/declaring-layout.html] - [FrameLayout](https://developer.android.com/reference/android/component/FrameLayout.html) - good for position views on top of each other, or encapsulating a bunch of views. Used in [Doodle](/courses/cse340/23wi/assignments/doodle). - [__LinearLayout__](https://developer.android.com/reference/android/component/LinearLayout.html) - places views one after the other in order according to the orientation (Horizontal or Vertical). Used in [Layout](/courses/cse340/23wi/assignments/layout). - [RelativeLayout](https://developer.android.com/reference/android/widget/RelativeLayout) - Positions of the children are desribed in relation to one another - [TableLayout](https://developer.android.com/reference/android/component/TableLayout.html) - Rows and columns style way of declaring a layout - [GridLayout](https://developer.android.com/reference/android/component/GridLayout.html) - Uses an [*adapter*](https://developer.android.com/reference/android/interactor/Adapter.html) that provides items to display in a grid - [ConstraintLayout](https://developer.android.com/reference/android/component/ConstraintLayout.html) Let's you use constraints to specify how things should lay out. Used in [Layout](/courses/cse340/23wi/assignments/layout). ??? We'll talk more about Constraint layouts later --- ## Example: Linear Layout of Email .left-column[ [Linear Layout Tutorial](https://developer.android.com/guide/topics/ui/layout/linear) ![:img Linear layout of an email message with to line subject line and message arranged vertically, 100%, width](img/layout/linearlayout.png) ] .right-column[ ```xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="16dp" android:paddingRight="16dp" android:orientation="vertical" > <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/to" /> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/subject" /> <EditText android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:gravity="top" android:hint="@string/message" /> <Button android:layout_width="100dp" android:layout_height="wrap_content" android:layout_gravity="right" android:text="@string/send" /> </LinearLayout> ``` ] ??? Can implement all of the things we discussed earlier using constraints note that they can be hard to debug? Discussion of specific inheritance hierarchy for constraints - Only have to write once when we use classes properly - can mix and match things --- # How to view the XML - The Layout XML View completely specifies what was in the GUI (and vice versa) - Get to it by clicking 'Text' (next to 'Design') .left-column50[ ![:img Picture of the android layout interface showing the xml which completely specifies what was in the other image,45%, width](img/layout/text-view.png) ![:img A simple layout on an android watch with a textview and two buttons (save and discard),50%, width](img/layout/watch.png) ] .right-column50[ ```xml <?xml version="1.0" encoding="utf-8"?> <-...-> <TextView <-...-> <LinearLayout <-...-> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/Save" /> <-...-> </LinearLayout> ``` ] ??? What examples do we have here? - Layout container (linearlayout) - Spacer - springiness - struts - constraints --- # Reminder about XML and Android .left-column[ ![:img Picture of the android ide file system with an xml file inside of res highlighted, 70%, width](img/layout/xml-files.png) ] .right-column[ Android puts XML in `res`/[`layout`|`values`|`...`], where all sorts of static properties can be specified In XML you can set variables that we can access later in XML or code - In XML access a value (such as `vMargin` from our assignment) using `@(file name)/(value name)` , where the file name is a file somewhere in `res` and the value name is an xml value found in that file. i.e., for `vMargin`, you can use `"@dimen/vMargin"` - In code, you refer to that value by `R.(file name).(value name)` ] --- # Runtime Instantiation *FROM XML* XML layouts are particularly useful - We can add them to the interactor hierarchy using **Inflation**. - We can do this many times over (for example if a sub-layout is repeated a lot) We use a [LayoutInflater](https://developer.android.com/reference/android/view/LayoutInflater) pass it in the id of the xml we're interested in (`R.layout.part1`). (To do inflation in your code you need to `import [package].R;`) --- # XML Layout Inflation Inflation can be done by any `Context` object. For example in `MainActivity.java` ```java 1. // ask the Context for the inflater 2. LayoutInflater inflater = getLayoutInflater(); 3. // newView is at the root of the inflated tree 4. View newView = inflater.inflate(R.layout.part1, contents); 5. // params here is a set of layout paramaters for the new view 6. contents.addView(newView, PARAMS); ``` Line 2 could also be done as: ```java LayoutInflater inflater = LayoutInflater.from(context); // The rest is the same ``` ??? Remind that you can inflate once but use many times --- # XML Layout Inflation four ways There are four overloaded versions of `LayoutInflater#inflate` - the resource versions are relevant to this class/assignment: ```java // Inflate the view from a resource and attach it to the given root public View inflate (int resource, ViewGroup root) // Inflate the view from a resource, to the given root, if the boolean value is true. public View inflate (int resource, ViewGroup root, boolean attachToRoot) // Inflate the view from an XML DOM node and attach it to the given root. public View inflate (XmlPullParser parser, ViewGroup root) // Inflate the view from an XML DOM node , to the given root, if the boolean value is true. public View inflate ((XmlPullParser parser, ViewGroup root, boolean attachToRoot) ``` --- # Specifying layout parameters in code ```java *RelativeLayout.LayoutParams params; params = new RelativeLayout.LayoutParams( RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT); ... ``` Use [ViewGroup#addView(View, ViewGroup.LayoutParams)](https://developer.android.com/reference/android/view/ViewGroup#addView%28android.view.View,%20android.view.ViewGroup.LayoutParams%29) method on the parent to add it to the Interactor Hierarchy (with the params) ```java Part2View p2v = new Part2View(this, getImageStrings(), vMargin); *contents.addView(p2v, params); ``` --- # Specifying layout parameters in code There are a lot of options for layout parameters, study the documentation! This is different for [RelativeLayout.LayoutParams](https://developer.android.com/reference/android/widget/RelativeLayout.LayoutParams) and [ConstraintLayout.LayoutParams](https://developer.android.com/reference/android/support/constraint/ConstraintLayout.LayoutParams) ![:img Four different permuations of the MATCH_PARENT or WRAP_CONTENT layout parameters, 75%, width](img/layout/layoutparams.png) --- # Lots of Examples in Layout Look for `addView([view], PARAMS)` in the code You'll need to do this for the `ImageView` objects you create and add For example in `MainActivity#onCreate(Bundle)` we see ```java contents.addView(getLayoutInflater().inflate(R.layout.part1, null), PARAMS); ``` This statement loads `res/layout/part1.xml`. ```xml
``` ??? Looking deeper we see that contains a `RelativeLayout` which contains a `ScrollView` and the `BottomNavigationView`. --- # Specifying Ids .left-column50[ - Set the IDs in your layout XML when you create things! - Use good ID names (like variables in programming) - Access it programmatically using `[Component].getId()` and `[Component].setID()`. - Access all Ids using `R.id.[ID]` - We use this to implement the tab navbar in Layout ![:img Picture of the android layout toolbar, 50%, width](img/layout/layouttoolbar.png) ] -- .right-column50[ In `MainActivity.java` for Layout ```java // Set window contents based on selected item. *switch (item.getItemId()) { * case R.id.tab_demo: contents.addView(getLayoutInflater().inflate(R.layout.demo, null), PARAMS); return true; * case R.id.tab_static_images: contents.addView(getLayoutInflater().inflate(R.layout.part1solution, null), PARAMS); return true; //... } ``` ] --- # Using that id So we find the `contents` (a `ViewGroup`) by that unique id ```java ViewGroup contents = findViewById(R.id.tab_contents); ``` --- # Layout Assignment .left-column[ ![:img Part1: picture of animals a button and a big textbox in a phone held vertically, 65%, width](img/layout/1_portrait.png) You can scroll this and the images are all equidistant. ] .right-column[ - Part 1 is about basic reactive layout using XML and constraints for a fixed number of images - Part 2 asks you to create two custom layout classes (subclasses of `ViewGroup`), then add an arbitrary number of images - Part 3 you create a *Layout Container* that can do a fancier layout, for an arbitrary number of images **Pinterest** style! - Part 4 you try to recreate a layout of your choice! ] --- # Layout Assignment .left-column30[ ![:img Part1: diagram of images evenly spaced stacked vertically, 110%, width](img/layout/part1-diagram.png) ] .right-column70[ Part 1 is a basic reactive layout using XML - Use constraints for the left/right/top/bottom of each image - Set `adjustViewBounds`, `scaleType`, `width`, `height` appropriately - Set the `margin` using best practices - a pre-defined dimension - Ensure each image is accessible by adding a good `contentDescription` Note: the image on the left is what we are calling a __Layout Wireframe__ ] --- # Layout Assignment .left-column30[ ![:img Part1: diagram of images evenly spaced stacked vertically, 110%, width](img/layout/part1-diagram.png) ] .right-column70[ Part 1 is about basic reactive layout using XML and constraints Part 2 asks you to reproduce this (with captions) in code - Not all that different from creating views in Doodle - What are the key steps here? ] ??? instantiate add to the hierarchy Just now we will also add layout containers --- # Layout Assignment .left-column30[ ![:img Part1: diagram of images evenly spaced stacked vertically, 110%, width](img/layout/part1-diagram.png) ] .right-column70[ Part 1 is about basic reactive layout using XML and constraints Part 2 asks you to create two custom layout classes (subclasses of `ViewGroup`) - a `CaptionedImageView` combines an image and a caption into a single `View`. - `ImageListView` builds a scrollable list of `CaptionedImageViews` programmatically. which allows an arbitrary list of images. - What are the key steps here? - instantiate (create the `View`) - add to the hierarchy ] --- # Layout Assignment .left-column30[ ![:img Part4: Spot the heron low fidelity prototype, 55%, width](img/layout/spottheheron-prototype.png) ![:img Part4: Spot the heron layout wireframe, 70%, width](img/layout/spottheheron-wireframe.png) ] .right-column70[ Part 3 you create a *Layout Container* that can do a fancier layout, for an arbitrary number of images **Pinterest** style! Part 4 is about designing and creating your own mock up of another app layout - Make sure you do the design first - Create your Layout Wireframe (see left) - Create your interactor hierarchy ]