--- name: inverse layout: true class: center, middle, inverse --- # Layout II - More on Android Layout Lauren Bricker CSE 340 Spring 2020 --- name: normal layout: true class: --- [//]: # (Outline Slide) # Today's goals - Announcements - Peer reviews technically due Tuesday, please do them early - Reflection due Wednesday (no late days) - Layout 1-2 due Friday (no late days) - Specifying Layout in XML - Inflation - Laying out views programatically - Wednesday we will talk about the theory behind layout. --- # Why do we need layout? .left-column60[ ![:img Yahoo in 1996 with no layout other than centering, 40%](http://blogoscoped.com/files/yahoo-1996-large.png) ![:img screen capture of modern yahoo with blocks laying out different news articles, 50%](img/layout-ii/modern-yahoo.png) ] .right-column30[ - Visual appeal - Organization (think about Properties of People Design tip #10: Use well-tested visual grouping strategies) ] --- # Reminder: User Interfaces on Android .left-column-half[ - 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 We will use the word *Components* to include both layout components and interactors (Views) since you don't generally "interact" with layouts ] .right-column-half[
graph TD W(ViewGroup) --> V[ViewGroup] W --> V1[View] W --> V2[View] V --> V3[View] V --> V4[View] V --> V5[View] classDef blue font-size:14pt,text-align:center classDef darkblue font-size:14pt,text-align:center class W,V darkblue class V1,V2,V3,V4,V5 blue
] --- # Layout in Android Where we left off: "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%](img/layout-ii/design-view.png) ??? Talk about how there's many layout and other attributes for components that they should explore! --- # Layout Types in Android - [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](/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](/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](/assignments/layout). - More on https://developer.android.com/guide/topics/ui/declaring-layout.html ??? We'll talk more about Constraint layouts later --- .left-column[ ## Example: Linear Layout of Email [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%](img/layout-ii/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 --- # Layout in Android - The Layout XML View completely specifies what was in the GUI (and vice versa) - Get to it by clicking 'Text' (next to 'Design') .left-column-half[ ![:img Picture of the android layout interface showing the xml which completely specifies what was in the other image,45%](img/layout-ii/text-view.png) ![:img A simple layout on an android watch with a textview and two buttons (save and discard),50%](img/layout-ii/watch.png) ] .right-column-half[ ```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 --- # More about XML and Android .left-column[ ![:img Picture of the android ide file system with an xml file inside of res highlighted, 70%](img/layout-ii/xml-files.png) ] .right-column[ Android has XML, where all sorts of static properties can be specified Every Android app has a `layout` directory and a `values` directory and several others. We'll use these in this assignment 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)` ] --- # The importance of ID .left-column-half[ In `MainActivity.java` for Layout ```java // Set window contents based on selected item. *switch (item.getItemId()) { * case R.id.action_part_1: * setCurrentTabId(R.id.action_part_1); contents.addView(getLayoutInflater().inflate(R.layout.part1, null), PARAMS); // params here is a set of layout paramaters for this view return true; * case R.id.action_part_2: * setCurrentTabId(R.id.action_part_2); contents.addView(new Part2View(this, getImageStrings()), PARAMS); return true; //... } ``` ] .right-column-half[ - 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%](img/layout-ii/layouttoolbar.png) ] --- # Lots to unpack here `PARAMS` is a class constant added to `MainActivity` to hold the parameters for the layout: ```java *public static final RelativeLayout.LayoutParams PARAMS = * new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, * RelativeLayout.LayoutParams.MATCH_PARENT); ... switch (item.getItemId()) { // Set window contents based on selected item. case R.id.action_part_1: setCurrentTabId(R.id.action_part_1); * contents.addView(getLayoutInflater().inflate(R.layout.part1, null), PARAMS); return true; case R.id.action_part_2: setCurrentTabId(R.id.action_part_2); * contents.addView(new Part2View(this, getImageStrings()), PARAMS); return true; //... } ``` --- # PARAMS ```java public static final RelativeLayout.LayoutParams PARAMS = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT); ``` .left-column40[ - There are a lot of options for layout parameters, study the documentation! [Here](https://developer.android.com/reference/android/widget/RelativeLayout.LayoutParams) is the documentation for the `RelativeLayout` `LayoutParams` - Width and height are often set as either `MATCH_PARENT` or `WRAP_CONTENT` (could be used to wrap the bounding box wrap around the text in your `TextView` in Doodle) ] .right-column-half[ ![:img Four different permuations of the MATCH_PARENT or WRAP_CONTENT layout parameters, 100%](img/layout-ii/layoutparams.png) ] --- # Two ways to create Interactors - Specify elements in WYSIWYG* editor, which will automatically create and initialize the objects via XML. - You could also hand type the XML the editor would produce. - Done in `Doodler#onCreate(Bundle)` - the line `setContentView(R.layout.activity_main);` - Will be done in Part 1, Part 3, and Part 4 for Layout ```java * contents.addView(getLayoutInflater().inflate(R.layout.part1, null), PARAMS); ``` - Instantiate UI classes at runtime. - We did this creating new views in Doodle at runtime! - Will do this in Part 2, Part 3, and Part 4 for Layout ```java * contents.addView(new Part2View(this, getImageStrings()), PARAMS); ``` .footnote[\*WYSIWYG = What You See Is What You Get] --- # Where are these views getting added? Looking at `MainActivity#onCreate(Bundle)` we see `setContentView(R.layout.activity_main);` This statement loads `activity_main.xml`. Looking deeper we see that contains a `RelativeLayout` which contains a `ScrollView` and the `BottomNavigationView`. ```
``` --- # Using that id So we find the `contents` (a `ScrollView`) by that unique id `ScrollView contents = findViewById(R.id.tab_contents);` --- # Runtime Instantiation *FROM XML* In part 1 we instantiate (create) `part1.xml` into the hierarchy of view which will be the children of the `ScrollView contents` using **Inflation**. 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`). Once inflated, we add it to the ScrollView. ```java * contents.addView(getLayoutInflater().inflate(R.layout.part1, null), PARAMS); ``` To do Inflation in your code you need to `import [package].R;` --- # Programatic creation of the hierarchy In part 2, we recreate his hierarchy programatically by instantiating an `Part2View` object and adding that to the view. ```java * contents.addView(new Part2View(this, getImageStrings()), PARAMS); ``` Just like with Part 1, we need to create a `ConstraintLayout` then add that to the ScrollView. We did that for you... Your job is to add `ImageView` objects to the `ConstraintLayout`. Hint: create and use `ConstraintLayout.LayoutParams` for specifying the constraints on the `ImageView` objects you create. You'll probably want to look at the [documentation](https://developer.android.com/reference/android/support/constraint/ConstraintLayout.LayoutParams) --- # Constraint Layout in Android .left-column-half[ ![:img A simple layout on an android watch with a textview and two buttons (save and discard) and the constraints highlighted,90%](img/layout-ii/constraint-editor.png) ] .right-column-half[ This assignment also uses **Constraints** (the `ConstraintLayout`) You can see little lines connecting the `textView` to its container and it's sibling (the `linearLayout`). - This specifies how it's attached (can change type by clicking on right) - If you were to change the interface (e.g. a different sized screen), it would stay attached and keep filling the space - All ends up in XML you can explore too ] --- # Constraint Layout in Android .left-column-half[ ![:img A simple layout on an android phone instead of a watch with a textview and two buttons (save and discard),100%](img/layout-ii/explore-devices.png) ] .right-column-half[ You can test this: modify the aspect ratio of your display, and flip it to horizontal to test things ] ??? Demonstration: consider demoing this interface live PRINT THIS LIST - Show dragging things to create layout - Show different size and orientation phones - Show editing attributes - Show clicking on constraints in box to change type - Show simple interface hierarchy - Show simplifying xml - Show changing button names/ids --- # What are Constraints? .left-column[ ![:img A simple layout on an android watch with a textview and two buttons (save and discard) and the constraints highlighted,110%](img/layout-ii/watch3.png)] .right-column[ - Very general - Can reproduce most other things - Can operate on multiple axes - Can enhance other layout options ] --- # What are Constraints? .left-column[ ![:img A simple layout on an android watch with a textview and two buttons (save and discard) and the constraints highlighted,110%](img/layout-ii/watch3.png)] .right-column[ - What do you think this does? `app:layout_constraintBottom_toTopOf="@+id/linearLayout"` - And this? `app:layout_constraintEnd_toEndOf="parent"` - We also use `Start_tStartOf` and 'Top_toTopOf` to create this ```xml <TextView android:id="@+id/textView" android:layout_width="0dp" android:layout_height="0dp" android:text="@string/sample_text" app:layout_constraintBottom_toTopOf="@+id/linearLayout" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" android:layout_marginStart="8dp" android:layout_marginTop="8dp" android:layout_marginEnd="8dp" android:layout_marginBottom="8dp"/> ``` ] --- .left-column[ ## Constraints in Android ![:img picture of attributes window showing controls for constraint-based layout including five types of elements, 100%](img/layout-ii/constraints.png)] .right-column[ [Docs](https://developer.android.com/training/constraint-layout/): limited set of constraints - 1 Size ratio - 2 Delete constraint (not a constraint, just removes them) - 3 Height/width mode (3 main types): - Wrap constraint ![:img wrap symbol >>>, 5%](img/layout-ii/wrap.png) - Fixed size ![:img fixed symbol I--I, 5%](img/layout-ii/fixed.png) - Match Constraint ![:img match symbol IvvvI, 5%](img/layout-ii/match.png) - 4 Margins - 5 Constraint bias (essentially weights on competing constraints) Range of attachment options (e.g. button sides, corners) Worth getting to know additional abstractions (groups; guidelines; barriers; chains) ] ??? -bias lets us create something that is 2-3 of the way over rather than centered go back to android to demo again --- # Powerful option Can do everything we can do with springs, struts, and linear layouts Declare relationships (.red[what] should be true) System automatically maintains relationships under change (.red[how]) --- # Powerful option Can do everything we can do with springs, struts, and linear layouts Declare relationships (what should be true) - This should be centered in that - This should be 12 pixels to the right of that - Parent should be 5 pixels larger than child System automatically maintains relationships under change (how) --- # Powerful option Can do everything we can do with springs, struts, and linear layouts Declare relationships (what should be true) System automatically maintains relationships under change (how) Too good to be true? - Unsolvable for arbitrary things - Works really well for a limited set ??? a good set for ui programming xx need to make sure I know why it is hard for arbitrary things --- # Note that these are one-way constraints You can change the right side, and it will update the left side (not the reverse) Can be very inefficient .jax[$$O(2^n)$$] But highly efficient incremental update algorithms exist ??? Only have to update things that might change Hudson's work on this was seminal can have a Directed Acyclic Graph (DAG) but not a cycle (thus, a tree) hard to guard against cycles --- # Layout Assignment .left-column[ ![:img Part1: diagram of images evenly spaced stacked vertically, 100%](img/layout-ii/part1-diagram.png) ] .right-column[ Part 1 is about basic reactive layout using XML and constraints - We will use constraints for the left/right/top/bottom of each image - `scaleType`, `width` and `height` will be provided for you There are also things we specify without constraints: margins, for example. - Android best practice is to use a variable for this - How do we do that in XML? Note: the image on the left is what we are calling a __Layout Wireframe__ ] --- # Layout Assignment .left-column[ ![:img Part1: diagram of images evenly spaced stacked vertically, 100%](img/layout-ii/part1-diagram.png) ] .right-column[ Part 1 is about basic reactive layout using XML and constraints Part 2 asks you to reproduce this 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-column[ ![:img Part1: diagram of images evenly spaced stacked vertically, 100%](img/layout-ii/part1-diagram.png) ] .right-column[ Part 1 is about basic reactive layout using XML and constraints Part 2 asks you to reproduce this in code - Not all that different from creating views in Doodle - What are the key steps here? - instantiate (create an interactor) - add to the hierarchy - just now we will also add layout containers ] --- # Layout Assignment .left-column[ ![:img Part4: Spot the heron low fidelity prototype, 40%](img/layout-ii/spottheheron-prototype.png) ![:img Part4: Spot the heron layout wireframe, 50%](img/layout-ii/spottheheron-wireframe.png) ] .right-column[ Part 3 is about using both XML and programatic means to create a Pinterest style Layout 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 ] --- # Constraints: A General and Powerful Approach General mechanism for establishing and maintaining relationships between things - Layout is one use - Several other uses in UI - Connection of application to UI, e.g. deriving appearance from data - Multiple views of same data - Automated semantic feedback - Automatic arrangement of lines (Snapping in drawing programs) --- # Practice with the [Layout Lab](https://github.com/harshitha-akkaraju/layoutlab) - Clone [https://github.com/harshitha-akkaraju/layoutlab.git](https://github.com/harshitha-akkaraju/layoutlab.git) - Open it up in Android studio - Switch between the challenges based in the `AndroidManifest.xml` | Create this layout using XML | Create this layout programatically | | :-- | :-- | | ![:img Challenge for buttons in XML, 30%](https://github.com/harshitha-akkaraju/layoutlab/raw/master/img/xml-layout.png) | ![:img Challenge with buttons to be added programatically, 30%](https://github.com/harshitha-akkaraju/layoutlab/raw/master/img/programmatic-layout.png)|