More Effective Layouts

Similar documents
Adapting to Data. Before we get to the fun stuff... Initial setup

ListView Containers. Resources. Creating a ListView

Fragments were added to the Android API in Honeycomb, API 11. The primary classes related to fragments are: android.app.fragment

Managing Data. However, we'll be looking at two other forms of persistence today: (shared) preferences, and databases.

UI Fragment.

Eventually, you'll be returned to the AVD Manager. From there, you'll see your new device.

CS371m - Mobile Computing. More UI Navigation, Fragments, and App / Action Bars

Fragments. Lecture 11

Creating a Custom ListView

CS371m - Mobile Computing. More UI Action Bar, Navigation, and Fragments

User Interface Development. CSE 5236: Mobile Application Development Instructor: Adam C. Champion Course Coordinator: Dr.

Android Dialogs. Dialogs are simple visual objects that pop up and display a message or prompt for some user input.

CS 4330/5390: Mobile Application Development Exam 1

MVC Apps Basic Widget Lifecycle Logging Debugging Dialogs

Mobile Development Lecture 10: Fragments

Layout and Containers

Agenda. Overview of Xamarin and Xamarin.Android Xamarin.Android fundamentals Creating a detail screen

Tablets have larger displays than phones do They can support multiple UI panes / user behaviors at the same time

MITOCW ocw f99-lec07_300k

Formal Methods of Software Design, Eric Hehner, segment 24 page 1 out of 5

Mobile Computing Fragments

Azon Master Class. By Ryan Stevenson Guidebook #5 WordPress Usage

The Stack, Free Store, and Global Namespace

ANDROID USER INTERFACE

Mobile Programming Lecture 3. Resources, Selection, Activities, Intents

Produced by. Mobile Application Development. David Drohan Department of Computing & Mathematics Waterford Institute of Technology

Mobile Programming Lecture 7. Dialogs, Menus, and SharedPreferences

Developing Android Applications Introduction to Software Engineering Fall Updated 1st November 2015

Android Specifics. Jonathan Diehl (Informatik 10) Hendrik Thüs (Informatik 9)

CMSC436: Fall 2013 Week 3 Lab

10.1 Introduction. Higher Level Processing. Word Recogniton Model. Text Output. Voice Signals. Spoken Words. Syntax, Semantics, Pragmatics

Q.1 Explain the dialog and also explain the Demonstrate working dialog in android.

Android CardView Tutorial

Android User Interfaces. Hsiao-Lung Chan, Ph.D. Dept Electrical Engineering Chang Gung University, Taiwan

Multiple devices. Use wrap_content and match_parent Use RelativeLayout/ConstraintLayout Use configuration qualifiers

Creating a User Interface

Building User Interface for Android Mobile Applications II

Post Experiment Interview Questions

Mobile Programming Lecture 2. Layouts, Widgets, Toasts, and Event Handling

Fragments. Lecture 10

Solving an Android Threading Problem

CS 4518 Mobile and Ubiquitous Computing Lecture 5: Rotating Device, Saving Data, Intents and Fragments Emmanuel Agu

EMBEDDED SYSTEMS PROGRAMMING Application Tip: Managing Screen Orientation

Instructor: Craig Duckett. Lecture 04: Thursday, April 5, Relationships

Getting Started. Dr. Miguel A. Labrador Department of Computer Science & Engineering

CS 528 Mobile and Ubiquitous Computing Lecture 3b: Android Activity Lifecycle and Intents Emmanuel Agu

Android Application Model I

CSE 660 Lab 3 Khoi Pham Thanh Ho April 19 th, 2015

Resources and Media and Dealies

Mobile Programming Lecture 5. Composite Views, Activities, Intents and Filters

Vienos veiklos būsena. Theory

Accelerating Information Technology Innovation

Understand applications and their components. activity service broadcast receiver content provider intent AndroidManifest.xml

Activities and Fragments

Skill 1: Multiplying Polynomials

Android Application Model I. CSE 5236: Mobile Application Development Instructor: Adam C. Champion, Ph.D. Course Coordinator: Dr.

EMBEDDED SYSTEMS PROGRAMMING UI and Android

Practical 1.ListView example

Smart formatting for better compatibility between OpenOffice.org and Microsoft Office

Chapter 1 Getting Started

Naming Things in Adafruit IO

MITOCW watch?v=0jljzrnhwoi

In our first lecture on sets and set theory, we introduced a bunch of new symbols and terminology.

CS 4518 Mobile and Ubiquitous Computing Lecture 4: Data-Driven Views, Android Components & Android Activity Lifecycle Emmanuel Agu

South Africa Version Control.

MITOCW ocw f99-lec12_300k

External Services. CSE 5236: Mobile Application Development Course Coordinator: Dr. Rajiv Ramnath Instructor: Adam C. Champion

Action Bar. (c) 2010 Haim Michael. All Rights Reserv ed.

EECS 4443 Mobile User Interfaces. More About Layouts. Scott MacKenzie. York University. Overview (Review)

CHAPTER 4. Fragments ActionBar Menus

INTRODUCTION COS MOBILE DEVELOPMENT WHAT IS ANDROID CORE OS. 6-Android Basics.key - February 21, Linux-based.

Linked Lists. What is a Linked List?

Formal Methods of Software Design, Eric Hehner, segment 1 page 1 out of 5

CSE143 Notes for Monday, 4/25/11

Lab 1 - Setting up the User s Profile UI

Mobile Computing Professor Pushpedra Singh Indraprasth Institute of Information Technology Delhi Andriod Development Lecture 09

Lesson 3 Transcript: Part 1 of 2 - Tools & Scripting

Hi everyone. Starting this week I'm going to make a couple tweaks to how section is run. The first thing is that I'm going to go over all the slides

EMBEDDED SYSTEMS PROGRAMMING Application Basics

Intents. Your first app assignment

Most of the class will focus on if/else statements and the logical statements ("conditionals") that are used to build them. Then I'll go over a few

Mobile Computing Practice # 2c Android Applications - Interface

EECS 4443 Mobile User Interfaces. More About Layouts. Scott MacKenzie. York University

Android Programming: More User Interface. CS 3: Computer Programming in Java

MITOCW watch?v=flgjisf3l78

MITOCW watch?v=yarwp7tntl4

Create new Android project in Android Studio Add Button and TextView to layout Learn how to use buttons to call methods. Modify strings.

Our First Android Application

Introduction. Using Styles. Word 2010 Styles and Themes. To Select a Style: Page 1

Upon completion of the second part of the lab the students will have:

05. SINGLETON PATTERN. One of a Kind Objects

ACTIVITY, FRAGMENT, NAVIGATION. Roberto Beraldi

MITOCW MIT6_172_F10_lec18_300k-mp4

Programming with Android: Android for Tablets. Dipartimento di Scienze dell Informazione Università di Bologna

Android Basics. Android UI Architecture. Android UI 1

Android Data Binding: This is the DSL you're looking for

Adaptation of materials: dr Tomasz Xięski. Based on presentations made available by Victor Matos, Cleveland State University.

The following content is provided under a Creative Commons license. Your support

Mobile Application Development MyRent Settings

1 Getting used to Python

Transcription:

More Effective Layouts In past weeks, we've looked at ways to make more effective use of the presented display (e.g. elastic layouts, and separate layouts for portrait and landscape), as well as autogenerating custom widgets for selections. Problems Both of these are slightly lacking. So far, creating a separate landscape layout has required repeating the entire user interface (with potential pitfalls for major errors). This would be even worse if we wanted to take the same approach to the phone vs tablet problem (likely including significantly different code as well). Additionally, our generated widgets have been fine for list-oriented entries, but still ignores a basic design question: what if we want to present a popup, just to get some input (or inputs) from the user? We wouldn't necessarily want to combine such questions with the larger interface, right? (For example, suppose you want to send a message to someone. It isn't unheard of for an application to present you with a contact list that then entirely disappears) Solutions Basically, the two topics we want to discuss are fragments and dialogs; albeit in the opposite order. If we have time, we'll also get our first taste of minimal (organized) persistence. Dialogs We'll be using dialogs in cases where we theoretically could have just made a new Activity, but where that would be overkill (or where we don't really want to completely leave the current context). Though we can create our own custom dialogs, Android also provides several handy base types. Let's start off simple. AlertDialogs Make a new project, and let's get the skeleton of a basic layout down: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" tools:context="ca.brocku.efoxwell.a2017_fifthstage.mainactivity" android:orientation="vertical" > <Button android:text="simple" android:id="@+id/lerta" android:onclick="pushy"

<Button android:text="interesting" android:id="@+id/lertb" android:onclick="pushy" <Button android:text="feedback" android:id="@+id/lertc" android:onclick="pushy" <TextView android:id="@+id/feedback" <Button android:text="next!" android:id="@+id/enoughlerts" android:onclick="pushy" I figured I'd probably want four buttons, but we can change that. Also, yours doesn't need to look like mine. The AlertDialog is used to either present a notification, or to get minimal feedback. In all cases, it acts as a sort of a popup, as an alternative to the current Activity/mode (for this reason, you might want to use them sparingly. More often than not, you don't want your application to interrupt itself). Of course, we'll be using a switch statement to handle the button presses, so I'll focus on what's inside. Let's start simple. To simplify the creation of a new Dialog, we'll use a builder: AlertDialog.Builder firstdialog=new AlertDialog.Builder(this); firstdialog.settitle("attention!"); firstdialog.seticon(r.mipmap.ic_launcher); firstdialog.setmessage("note: this is a dialog. That is all."); firstdialog.show(); Well, that's... boring. Also, note that you have to press the 'back' button or click somewhere else to get out of it. You wouldn't commonly want an AlertDialog this simplistic. At the very least, you'd want some sort of acknowledgement button on it, and possibly a negative/cancel (e.g. if asking to proceed). We have up to three buttons available to us (positive, neutral, and negative), so let's use them all:

AlertDialog.Builder seconddialog=new AlertDialog.Builder(this); seconddialog.settitle("attention!"); //I no longer care about the icon seconddialog.setmessage("i'm Mr. Dialog! Look at me!"); seconddialog.setpositivebutton("ok", new DialogInterface.OnClickListener() { public void onclick(dialoginterface dialog, int buttonid) { Toast.makeText(MainActivity.this,"Caaan dooo!",toast.length_short).show(); ); seconddialog.setnegativebutton("cancel", new DialogInterface.OnClickListener() { public void onclick(dialoginterface dialog, int buttonid) { Toast.makeText(MainActivity.this, "Well, which is it? Square my shoulders or keep my head down?", Toast.LENGTH_SHORT).show(); ); seconddialog.setneutralbutton("(other)", new DialogInterface.OnClickListener() { public void onclick(dialoginterface dialog, int buttonid) { Toast.makeText(MainActivity.this, "We talked about this! It's both!", Toast.LENGTH_SHORT).show(); ); seconddialog.show(); Of course, your text would presumably be different. Or not. Up to you. Note that it'd probably be more appropriate to use a single listener for all three (the buttonid will tell you which was pressed). Okay, so now we can show, for example, a disclaimer, or a permission/confirmation form. What else? Well, the dialog is already designed to contain a View. If we wanted anything more complicated than a single data entry, then we'd probably be best off just creating an entire custom dialog. Let's just programmatically create a single EditText to put into it, and retrieve the data (only) upon pressing OK. AlertDialog.Builder thirddialog=new AlertDialog.Builder(this); thirddialog.settitle("attention!"); thirddialog.seticon(r.mipmap.ic_launcher); thirddialog.setmessage("what's your favourite number?"); final EditText query=new EditText(this); query.sethint("like... 42?"); query.setinputtype(inputtype.type_class_number); thirddialog.setview(query); thirddialog.setpositivebutton("ok", new DialogInterface.OnClickListener() { public void onclick(dialoginterface dialog, int buttonid) { ((TextView)findViewById(R.id.feedback)).setText("Yep. "+ query.gettext()+" is neat."); ); thirddialog.setnegativebutton("cancel",

new DialogInterface.OnClickListener() { public void onclick(dialoginterface dialog, int buttonid) { return; ); thirddialog.show(); break; So now, we can easily get a bit of information back from the user whenever we want. Other premade dialogs There are plenty of other dialogs already built into Android. Some of the more esoteric ones include CharacterPickerDialog and ProgressDialog. But let's look at a pair of dialogs you might actually semi-commonly need. Time for another Activity. Just give its layout two buttons (one for this demonstration, and one to move on). I'm assuming the demo button is called chronology. Heck, I'll use the same for the Activity, itself. public class Chronology extends AppCompatActivity implements DatePickerDialog.OnDateSetListener, TimePickerDialog.OnTimeSetListener{ @Override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_chronology); public void chronology(view v) { java.util.calendar today=java.util.calendar.getinstance(); new DatePickerDialog(Chronology.this, //context this, //listener today.get(java.util.calendar.year), today.get(java.util.calendar.month), today.get(java.util.calendar.day_of_month)).show(); public void ondateset(datepicker view, int year, int monthofyear, int dayofmonth) { java.util.calendar today=java.util.calendar.getinstance(); new TimePickerDialog(this, this, today.get(calendar.hour_of_day), today.get(calendar.minute), true //24-hour display? ).show(); public void ontimeset(timepicker view, int hour, int minute) { android.widget.toast.maketext(this,"neat.", Toast.LENGTH_SHORT).show(); public void nextactivity(view v) { //startactivity

Yeah, it doesn't actually do anything. But we can still see roughly how it works. Note that this isn't the same thing as having the user's list of contacts pop up for selecting. Contacts rely on a content provider, and we aren't there just yet. Fragments Okey dokey. No real segue here; just a flat introduction of the problem: as mentioned earlier, if I want to have different layouts according to different screen geometries, my choices (with the tools we've covered thus far) have been pretty limited. Basically, I need to recreate everything from scratch for each different type of view. How much of that is really necessary? Certainly, if we wanted the application to look different between its portrait and landscape orientations, we'd definitely need different XML layouts. But do we need complete copies of the layouts? For example, there is likely to be a great deal of overlap between them. Just for the sake of clarification, let's look at an example (which we won't actually be creating today). Thought experiment Let's say we wanted to make a graphing calculator. In a portrait view, we'd probably have the graphing area at the top, and the buttons at the bottom. In landscape, that would look squished, and borderline useless. Instead, we might prefer the buttons on the right, and the graphing area on the left (or vice versa). However, the graphing area itself is the same, irrespective of where it is, and the same goes for the buttons. So then, what's a Fragment? Well, this is one of those it makes more sense when you see it cases, but, in short, a Fragment is a selfcontained, pseudo-activity, that keeps its own interface to itself. The application can then have one or more Fragments simultaneously, and either display them together, or let you switch between them, or selectively only show some when there's enough room. Fragments have their own separate life cycles, not directly tied to those of the Activities. The Android developer page has a good perspective: You can combine multiple fragments in a single activity to build a multi-pane UI and reuse a fragment in multiple activities. You can think of a fragment as a modular section of an activity, which has its own lifecycle, receives its own input events, and which you can add or remove while the activity is running (sort of like a "sub activity" that you can reuse in different activities). Read more here: https://developer.android.com/guide/components/fragments.html

Life cycles A Fragment has its own life cycle, but that life cycle is still closely connected to its Activity's. For example, if you pause an Activity, it would be odd if the pieces within that Activity didn't also pause, right? For the sake of visualizing the connection between the two, consider the following image, stolen shamelessly from the Android developer page: The two major methods to override are oncreate() and oncreateview(). oncreate() should be self-explanatory by now, but oncreateview() might not be. Basically, because Fragments handle UIs a little differently from Activities (when they even have UIs at all), we'll have to build them slightly differently as well. In this case, we'll need to explicitly construct the UI, and then return that 'View' for incorporation into the Activity. If a Fragment doesn't need a UI, just return null. First example Let's start small for our first example, okay? In fact, let's start so small that it's effectively pointless. Let's make a single Fragment to fit within a single Activity, just to confirm that we can, k? You know the drill by now. Let's create a new Activity (I'm calling mine FraggyOne), and load it up from that second button we created for our last layout. For this example, I'm still going to create a layout for the Activity, but it will be pretty trivial, as its sole job will be to hold a Fragment. While I'm at it, I'll also create the new Fragment, FraggyOneFrag, and have Android studio create a layout for that for me. I won't have it create the other extras, though.

Our first Fragment: layout <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" tools:context="ca.brocku.efoxwell.a2017_fifthstage.fraggyonefrag" android:orientation="vertical"> <TextView android:text="things!" <TextView android:text="stuff!" <Button android:text="button!" android:onclick="thatsit" Our first Fragment: code public class FraggyOneFrag extends Fragment { @Override public View oncreateview(layoutinflater inflater, ViewGroup container, Bundle savedinstancestate) { // Inflate the layout for this fragment return inflater.inflate(r.layout.fragment_fraggy_one, container, false); Corresponding Activity: layout <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" > <fragment android:name="ca.brocku.efoxwell.a2017_fifthstage.fraggyonefrag" android:id="@+id/fragonefrag" tools:layout="@layout/fragment_fraggy_one" Corresponding Activity: code public class FraggyOne extends AppCompatActivity { @Override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_fraggyone); public void thatsit(view v) { startactivity(new Intent(this,MainActivity.class));

Of course, we'll be wanting to change that MainActivity.class to our actual next Activity later. In this case, we just had the Activity handle the button click because it was easier. But we can always get our Activity's application context, if necessary. Also note that, in the layout file for the Activity, there's an entry explicitly stating which layout to use. That doesn't really mean much, functionality-wise. Rather, it's a hint to Android Studio, so it knows how to preview the final appearance of the total Activity. That example was boring This is true. Let's move on to using two Fragments in the same Activity, but still displaying them both. Let's say we'll want them to be stacked if in portrait, and side-by-side in landscape. Second example For this one, create the new Activity, EfficientLayout, and let the button start it. We'll get to filling it out in a moment. First, some boilerplate. I'll create Fragments of EfficientFruitFrag and EfficientViewFrag, and let Android Studio provide the layout files for them. Let's start by putting both Fragments into the Activity's layout. Activity layout: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:name="ca.brocku.efoxwell.a2017_fifthstage.efficientfruitfrag" tools:context="ca.brocku.efoxwell.a2017_fifthstage.efficientlayout" android:orientation="vertical"> <fragment android:layout_height="0dip" android:layout_weight="4" android:id="@+id/effragfruit" tools:layout="@layout/fragment_efficient_fruit" <fragment android:layout_height="0dip" android:layout_weight="2" android:id="@+id/effragview" android:name="ca.brocku.efoxwell.a2017_fifthstage.efficientviewfrag" tools:layout="@layout/fragment_efficient_view" <Button android:layout_height="0dip" android:layout_weight="1" android:onclick="nexteroonie"

Activity layout, landscape version: For this one, we just need to create the new version, change the vertical to horizontal, and tweak the width/height properties a bit. Activity code: public class EfficientLayout extends AppCompatActivity { @Override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_efficient_layout); public void nexteroonie(view v) { //start the next activity Fruit list fragment, layout: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" tools:context=".efficientfruitfrag" android:orientation="vertical"> <ListView android:id="@+id/fruits_list" android:drawselectorontop="false" Fruit view fragment, layout: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" tools:context=".efficientviewfrag" android:orientation="vertical"> <TextView android:text="what kind of fruit do you like?" android:id="@+id/selectedopt" So far, so good, right? Next, we'll want to populate the list, and have it change the TextView to indicate the selection. But, wait, that's in another Fragment, isn't it? Doesn't that make it difficult? Nope.

Fruit view fragment, code: public class EfficientFruitFrag extends Fragment { @Override public View oncreateview(layoutinflater inflater, ViewGroup container, Bundle savedinstancestate) { //First, let's get access to the Activity enclosing this Fragment Context c=getactivity().getapplicationcontext(); //Next, we need to build up the layout View vw=inflater.inflate(r.layout.fragment_efficient_fruit,container,false); final String[] fruits={"apple","pear","applepear","pear of Apples","Purple"; ListView flist=(listview)vw.findviewbyid(r.id.fruits_list); ArrayAdapter<String> adapter=new ArrayAdapter<>( c,android.r.layout.simple_list_item_1,fruits ); flist.setadapter(adapter); flist.setonitemclicklistener(new AdapterView.OnItemClickListener(){ public void onitemclick( AdapterView<?> parent, View v, int position, long id ) { TextView selected=(textview)getactivity().findviewbyid(r.id.selectedopt); selected.settext("i also like "+((TextView)v).getText().toString()); ); return vw; Give it a try, and you'll see that it works perfectly!... wait a minute... mostly perfectly? Can you spot the issue? If not, we can just fix it together. I don't like the portrait version Nah, me neither. As mentioned earlier, a big part of the reason to use Fragments is so we can not only reorganize them, but also separate them. Let's try tweaking just the portrait version of the Activity's layout: New Activity layout, portrait version: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" tools:context="ca.brocku.efoxwell.a2017_fifthstage.efficientlayout" android:orientation="vertical"> <fragment android:layout_height="0dip" android:layout_weight="4"

android:id="@+id/effragfruit" android:name="ca.brocku.efoxwell.a2017_fifthstage.efficientfruitfrag" tools:layout="@layout/fragment_efficient_fruit" <Button android:layout_height="0dip" android:layout_weight="1" android:onclick="nexteroonie" Note: All we did was to remove the second fragment. Fruit list fragment, code change: All we need to do is to change the onitemclick method as follows: public void onitemclick(adapterview<?> parent, View v, int position, long id) { if (getresources().getconfiguration().orientation== Configuration.ORIENTATION_LANDSCAPE) { TextView selected=(textview)getactivity().findviewbyid(r.id.selectedopt); selected.settext("i also like "+((TextView)v).getText().toString()); else { Intent intent=new Intent(getActivity().getApplicationContext(), EfficientItemActivity.class); intent.putextra("item",((textview)v).gettext().tostring()); startactivity(intent); Basically, if we're in a landscape orientation (meaning the other fragment is already there), do the exact same thing as before. However, if we're in portrait, we'll need to start a new Activity. Wait, what new Activity? Guess we'd better make one! However, we do not need to make a new layout for this one! Fruit view activity, code: public class EfficientItemActivity extends AppCompatActivity { @Override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); if (getresources().getconfiguration().orientation== Configuration.ORIENTATION_LANDSCAPE) { finish(); return; setcontentview(r.layout.fragment_efficient_view); Bundle extras=getintent().getextras(); if (extras!=null) { String selected=extras.getstring("item"); TextView tv=(textview)findviewbyid(r.id.selectedopt); tv.settext("i, too, like "+selected);

It's worth noting that this topic is actually far larger than this example (big surprise, eh?). For example, we can create Fragments programmatically, pass information between them (e.g. via Bundles or articles), and even save them on a stack (similar to how Activities are pushed onto the Activity stack), so you can retain a fragment's state if you need to switch away for a moment. There's a very good read here: https://developer.android.com/training/basics/fragments/index.html However, what we've seen so far is a decent first endeavour. It's also worth mentioning some of the other types of Fragment provided by Android. For example, there's a DialogFragment, to let you do largely the same thing as dialogs. There's also a PreferenceFragment, which can attach to the Shared Preferences. We'll probably be talking a bit about those in a week or so.