user interface developmentweb.cse.ohio-state.edu/~champion.17/5236/07_uiandroid.pdf · ui support...

33
User Interface Development CSE 5236: Mobile Application Development Instructor: Adam C. Champion, Ph.D. Course Coordinator: Dr. Rajiv Ramnath Reading: Big Nerd Ranch Guide, Chapter 7 (Fragments) 1

Upload: others

Post on 16-Apr-2020

3 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: User Interface Developmentweb.cse.ohio-state.edu/~champion.17/5236/07_UIAndroid.pdf · UI Support in the Android SDK •“Inverted” paradigm –Each subclass constrains functionality

User Interface Development

CSE 5236: Mobile Application DevelopmentInstructor: Adam C. Champion, Ph.D.Course Coordinator: Dr. Rajiv RamnathReading: Big Nerd Ranch Guide, Chapter 7 (Fragments)

1

Page 2: User Interface Developmentweb.cse.ohio-state.edu/~champion.17/5236/07_UIAndroid.pdf · UI Support in the Android SDK •“Inverted” paradigm –Each subclass constrains functionality

Outline

• UI Support in Android• Fragments

2

Page 3: User Interface Developmentweb.cse.ohio-state.edu/~champion.17/5236/07_UIAndroid.pdf · UI Support in the Android SDK •“Inverted” paradigm –Each subclass constrains functionality

UI Support in the Android SDK

• “Inverted” paradigm– Each subclass constrains functionality (rather

than extend it)–Hundreds of methods are exposed: L

• Base classes:– ViewGroup base class for composite UI

elements– View base class for terminal UI components

3

Page 4: User Interface Developmentweb.cse.ohio-state.edu/~champion.17/5236/07_UIAndroid.pdf · UI Support in the Android SDK •“Inverted” paradigm –Each subclass constrains functionality

View Hierarchy

4

# = SDK Version number

Page 5: User Interface Developmentweb.cse.ohio-state.edu/~champion.17/5236/07_UIAndroid.pdf · UI Support in the Android SDK •“Inverted” paradigm –Each subclass constrains functionality

ViewGroup Hierarchy• Direct Subclasses:

– AbsoluteLayout– AdapterView<T extends Adapter>– FragmentBreadCrumbs– FrameLayout– GridLayout– LinearLayout– PagerTitleStrip– RelativeLayout– SlidingDrawer– ViewPager

• 19 indirect subclasses. See: – http://developer.android.com/reference/android/view/ViewGroup.html

5

Page 6: User Interface Developmentweb.cse.ohio-state.edu/~champion.17/5236/07_UIAndroid.pdf · UI Support in the Android SDK •“Inverted” paradigm –Each subclass constrains functionality

Sample Layout, Login Activity<?xml version="1.0" encoding="utf-8"?><ScrollView xmlns:android="http://schemas.android.com/apk/res/android”

android:background="@color/background"android:orientation="horizontal"android:layout_width="fill_parent"android:layout_height="fill_parent"android:padding="20dip">

<LinearLayout android:orientation="vertical...<TextView android:text="@string/login_title” ... /><TextView ... /><EditText android:id="@+id/username_text” ... /><TextView ... /><EditText ... /><Button ... /><Button ... /><Button ... />

</LinearLayout></ScrollView>

Page 7: User Interface Developmentweb.cse.ohio-state.edu/~champion.17/5236/07_UIAndroid.pdf · UI Support in the Android SDK •“Inverted” paradigm –Each subclass constrains functionality

Layout Configuration• ID: android:id="@+id/username_text” : used for widget handle• Parameters:

– layout_width, layout_height

– layout_marginTop / ...marginRight, layout_margin– orientation

• Can be combined: layout_gravity=“bottom|right”• Constants: match_parent, wrap_content• Width and height specs: dp, sp (display pixels, scaled pixels)• A wide range of LayoutParams• Resources (e.g. backgrounds):

android:background=“@drawable/backdrop”• Blank canvases using a (generic) View element in the layout 7

Page 8: User Interface Developmentweb.cse.ohio-state.edu/~champion.17/5236/07_UIAndroid.pdf · UI Support in the Android SDK •“Inverted” paradigm –Each subclass constrains functionality

8

Page 9: User Interface Developmentweb.cse.ohio-state.edu/~champion.17/5236/07_UIAndroid.pdf · UI Support in the Android SDK •“Inverted” paradigm –Each subclass constrains functionality

Adding Resources

9

Resources can also be added by right-clicking on resdirectory, selecting New→AndroidResource File

Page 10: User Interface Developmentweb.cse.ohio-state.edu/~champion.17/5236/07_UIAndroid.pdf · UI Support in the Android SDK •“Inverted” paradigm –Each subclass constrains functionality

Other Layout Parameters, Techniques

• Inherit parameters from enclosing elements• layout_span spans multiple columns• Empty views to add blank canvases (filled later)• Shrink or stretch columns as needed

(shrinkColumns, stretchColumns)

• RelativeLayout lets window manager handle size• ConstraintLayout specifies widget constraints for

flexible widget rendering

10

Page 11: User Interface Developmentweb.cse.ohio-state.edu/~champion.17/5236/07_UIAndroid.pdf · UI Support in the Android SDK •“Inverted” paradigm –Each subclass constrains functionality

Linking a UI to a Fragment: Java// LoginActivity.java

public class LoginActivity extends SingleFragmentActivity {@Overrideprotected Fragment createFragment() { return new LoginFragment(); }

}

// LoginFragment.java

@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,

Bundle savedInstanceState) {View v = inflater.inflate(R.layout.fragment_login, container, false);

// Real code handles view rotationmUsernameEditText = (EditText) v.findViewById(R.id.username_text);mPasswordEditText = (EditText) v.findViewById(R.id.password_text);// Setup listener objects for buttonsreturn v;

}

11Also can set up listener objects in Activities with onCreate()

Page 12: User Interface Developmentweb.cse.ohio-state.edu/~champion.17/5236/07_UIAndroid.pdf · UI Support in the Android SDK •“Inverted” paradigm –Each subclass constrains functionality

Linking a UI to a Fragment: Kotlin// LoginActivity.kt

class LoginActivity : SingleFragmentActivity() {override fun createFragment(): Fragment { return LoginFragment() }

}// LoginFragment.kt

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {val v: View = inflater.inflate(R.layout.fragment_login, container, false)// Real code handles view rotationmUsernameEditText = v.findViewById<EditText>(R.id.username_text)mPasswordEditText = v.findViewById<EditText>(R.id.password_text)// Set up listener objects for Buttons

return v}

12

Page 13: User Interface Developmentweb.cse.ohio-state.edu/~champion.17/5236/07_UIAndroid.pdf · UI Support in the Android SDK •“Inverted” paradigm –Each subclass constrains functionality

Creating a Custom Widget: Layout<?xml version="1.0" encoding="utf-8"?><LinearLayout

xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:background="#676767"android:gravity="center_horizontal"android:padding="20dip">

<com.wiley.fordummies.androidsdk.tictactoe.Boardandroid:id="@+id/board"android:layout_width="match_parent"android:layout_height="280dip"/>

...</LinearLayout>

13

Page 14: User Interface Developmentweb.cse.ohio-state.edu/~champion.17/5236/07_UIAndroid.pdf · UI Support in the Android SDK •“Inverted” paradigm –Each subclass constrains functionality

Creating a Custom Widget: Java// Board.javapublic class Board extends View {

public Board(Context context, AttributeSet attributes) {super(context, attributes); // . . .setFocusable(true); setFocusableInTouchMode(true); // . . .

}// . . .protected void onSizeChanged(int w, int h, int oldw, int oldh) {

super.onSizeChanged(w, h, oldw, oldh); // . . .}@Overrideprotected void onDraw(Canvas canvas) {

super.onDraw(canvas); // . . .}

}

14

Instantiating the view:// LoginFragment.java: onCreateView() and setupBoard()// onCreateView()v = inflater.inflate(R.layout.fragment_game_session, . . .);// setupBoard()mBoard = (Board) v.findViewById(R.id.board);

Page 15: User Interface Developmentweb.cse.ohio-state.edu/~champion.17/5236/07_UIAndroid.pdf · UI Support in the Android SDK •“Inverted” paradigm –Each subclass constrains functionality

Creating a Custom Widget: Kotlin// Board.kt

class Board(context: Context, attributes: AttributeSet) : View(context, attributes) {init {

isFocusable = trueisFocusableInTouchMode = true // . . .

}

override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {super.onSizeChanged(w, h, oldw, oldh) // . . .

}

override fun onDraw(canvas: Canvas) {super.onDraw(canvas) // . . .

}

}

15

Instantiating the view:// LoginFragment.kt, onCreateView() and setupBoard()// onCreateView()v = inflater.inflate(R.layout.fragment_game_session, container, false) // setupBoard()mBoard = (Board) v.findViewById(R.id.board)

Page 16: User Interface Developmentweb.cse.ohio-state.edu/~champion.17/5236/07_UIAndroid.pdf · UI Support in the Android SDK •“Inverted” paradigm –Each subclass constrains functionality

Creating a Layout via Code// DohActivity.java@Overridepublic void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);LinearLayout layout = new LinearLayout(this);Button dohButton = new Button(this);dohButton.setText(“In case of meltdown, Push Me!”);layout.addView(dohButton);setContentView(layout);

}

16

Page 17: User Interface Developmentweb.cse.ohio-state.edu/~champion.17/5236/07_UIAndroid.pdf · UI Support in the Android SDK •“Inverted” paradigm –Each subclass constrains functionality

Styles and Themes (1)Use:

<EditTextstyle=”@style/DarkBold”android:text=”Hello” />

Definition:<?xml version=”1.0” encoding=”utf-8”?><resources>

<style name=“DarkBold”><item name=”android:layout_width”>

match_parent</item><item name=“android:layout_height”>

wrap_content</item>

... more parameters ...</style>

</resources> 17

Inheritance:<style name=“DarkPhone” parent=”@style/DarkBold”>

<item name=”android:phoneNumber”>true</item></style>

Page 18: User Interface Developmentweb.cse.ohio-state.edu/~champion.17/5236/07_UIAndroid.pdf · UI Support in the Android SDK •“Inverted” paradigm –Each subclass constrains functionality

Styles and Themes (2)

• Stored in res/values/ directory with .xmlextension (name not relevant)

• Can set application-wide and activity-specific styles (aka themes):– Set themes in AndroidManifest.xml on <application>

tag or <Activity> tag<application android:theme="@style/CustomTheme"><activity android:theme="@android:style/Theme.Translucent">

• Can even create version-specific layout files• Ref: http://developer.android.com/guide/topics/

ui/themes.html18

Page 19: User Interface Developmentweb.cse.ohio-state.edu/~champion.17/5236/07_UIAndroid.pdf · UI Support in the Android SDK •“Inverted” paradigm –Each subclass constrains functionality

Outline

• UI Support in Android• Fragments

19

Page 20: User Interface Developmentweb.cse.ohio-state.edu/~champion.17/5236/07_UIAndroid.pdf · UI Support in the Android SDK •“Inverted” paradigm –Each subclass constrains functionality

Fragments and Their Rationale

• Fragment: Composite UI component that handles its own UI

• One, multiple Fragments in an Activity• Separate class hierarchy: Fragment, DialogFragment, ListFragment, PreferenceFragment, etc.

• Goals: – Separate UI design from Activity design– UI should have its own lifecycle and flow– Dynamically add/remove UI components in running activity

• Drivers: heterogeneous devices, user experience20

Page 21: User Interface Developmentweb.cse.ohio-state.edu/~champion.17/5236/07_UIAndroid.pdf · UI Support in the Android SDK •“Inverted” paradigm –Each subclass constrains functionality

Example – Login and Account

Page 22: User Interface Developmentweb.cse.ohio-state.edu/~champion.17/5236/07_UIAndroid.pdf · UI Support in the Android SDK •“Inverted” paradigm –Each subclass constrains functionality

Portrait Layout: Login

22

<?xml version="1.0" encoding="utf-8"?><ScrollView ...>

<LinearLayout...><TextView android:text="@string/login_title".../><TextView android:text="@string/enter_username”.../><EditText android:id="@+id/username_text”.../><TextView android:text="Enter Password".../><EditText android:id="@+id/password_text".../><Button android:id="@+id/login_button".../><Button android:id="@+id/cancel_button”.../><Button android:id="@+id/new_user_button”.../>

</LinearLayout></ScrollView>

Page 23: User Interface Developmentweb.cse.ohio-state.edu/~champion.17/5236/07_UIAndroid.pdf · UI Support in the Android SDK •“Inverted” paradigm –Each subclass constrains functionality

Portrait Layout: Account

<?xml version="1.0" encoding="utf-8"?><LinearLayout ...>

<FrameLayout .../> ⟸⟸ Placeholder for fragment<Button android:id="@+id/exit_button”.../>

</LinearLayout>

What happened to landscape layout of the Fragment?

23

Page 24: User Interface Developmentweb.cse.ohio-state.edu/~champion.17/5236/07_UIAndroid.pdf · UI Support in the Android SDK •“Inverted” paradigm –Each subclass constrains functionality

Landscape Layout: Login<?xml version="1.0" encoding="utf-8"?>

<LinearLayout...

android:orientation="horizontal” ...> ⟸⟸ Note: horizontal layout<ScrollView ... >

<LinearLayout .. >

<TextView ... />

<TextView ... />

<!-- . . . -->

</LinearLayout>

</ScrollView><fragment class="com.wiley.fordummies.androidsdk.tictactoe.AccountFragment"

android:id="@+id/titles"

android:layout_height="match_parent” . . ./>

</LinearLayout>24

Page 25: User Interface Developmentweb.cse.ohio-state.edu/~champion.17/5236/07_UIAndroid.pdf · UI Support in the Android SDK •“Inverted” paradigm –Each subclass constrains functionality

AccountFragment: Portrait Layout<?xml version="1.0" encoding="utf-8"?><LinearLayout ...>

<LinearLayout...><TextView android:text="New Account" .../><TextView android:text="Username”.../><EditText android:id="@+id/username”.../><TextView android:text="Password”.../><EditText android:id="@+id/password”.../><TextView android:text="Confirm Password" .../><EditText android:id="@+id/password_confirm”.../><Button android:id="@+id/cancel_button” "/><Button android:id="@+id/done_button”.../></LinearLayout>

</LinearLayout>25

Page 26: User Interface Developmentweb.cse.ohio-state.edu/~champion.17/5236/07_UIAndroid.pdf · UI Support in the Android SDK •“Inverted” paradigm –Each subclass constrains functionality

AccountFragment: Landscape Layout<?xml version="1.0" encoding="utf-8"?><LinearLayout...>

<LinearLayout...><TextView android:text="New Account”.../><TextView android:text="Username”.../><EditText android:id="@+id/username”...”/><TextView android:text="Password" .../><EditText android:id="@+id/password”.../><TextView android:text="Confirm Password" .../><EditText android:id="@+id/password_confirm”.../><LinearLayout ... >

<Button android:id="@+id/cancel_button”.../><Button android:id="@+id/done_button”.../>

</LinearLayout></LinearLayout>

</LinearLayout>

26

Page 27: User Interface Developmentweb.cse.ohio-state.edu/~champion.17/5236/07_UIAndroid.pdf · UI Support in the Android SDK •“Inverted” paradigm –Each subclass constrains functionality

LoginFragment: Java@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,

Bundle savedInstanceState) {View v;int rotation = getActivity().getWindowManager().getDefaultDisplay()

.getRotation();if (rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) {

v = inflater.inflate(R.layout.fragment_login_land, container, false);} else {

v = inflater.inflate(R.layout.fragment_login, container, false);}mUsernameEditText = (EditText) v.findViewById(R.id.username_text);mPasswordEditText = (EditText) v.findViewById(R.id.password_text);// Set up OnClickListeners for buttonsreturn v;

}

27

Page 28: User Interface Developmentweb.cse.ohio-state.edu/~champion.17/5236/07_UIAndroid.pdf · UI Support in the Android SDK •“Inverted” paradigm –Each subclass constrains functionality

LoginFragment: Kotlinoverride fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,

savedInstanceState: Bundle?): View? {val v: Viewval rotation = activity.windowManager.defaultDisplay.rotationif (rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) {

v = inflater.inflate(R.layout.fragment_login_land, container, false)} else {

v = inflater.inflate(R.layout.fragment_login, container, false)}mUsernameEditText = v.findViewById<EditText>(R.id.username_text)mPasswordEditText = v.findViewById<EditText>(R.id.password_text)// Set up onClickListeners for buttonsreturn v

}

28

Page 29: User Interface Developmentweb.cse.ohio-state.edu/~champion.17/5236/07_UIAndroid.pdf · UI Support in the Android SDK •“Inverted” paradigm –Each subclass constrains functionality

AccountFragment: onCreateView(): Java

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {// Inflate the layout for this fragment

View v = inflater.inflate(R.layout.accountfragment, container, false);

Activity activity = getActivity();if (activity != null) {int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();mEtUsername = v.findViewById(R.id.username);mEtPassword = v.findViewById(R.id.password);mEtConfirm = v.findViewById(R.id.password_confirm);// OnClickListeners for Add, Cancel buttons

Button btnExit = v.findViewById(R.id.exit_button);if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) {

btnExit.setOnClickListener(this);} else { btnExit.setVisibility(View.GONE); }

return v;

}29

Page 30: User Interface Developmentweb.cse.ohio-state.edu/~champion.17/5236/07_UIAndroid.pdf · UI Support in the Android SDK •“Inverted” paradigm –Each subclass constrains functionality

AccountFragment: onCreateView(): Kotlin

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {val v = inflater.inflate(R.layout.fragment_account, container, false)

mEtUsername = v.findViewById(R.id.username)mEtPassword = v.findViewById(R.id.password)mEtConfirm = v.findViewById(R.id.password_confirm)// Set up OnClickListeners for Add, Cancel buttons

val btnExit = v.findViewById(R.id.exit_button)

if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) {btnExit.setOnClickListener(this)

} else {

btnExit.setVisibility(View.GONE)

}return v

}

30

Page 31: User Interface Developmentweb.cse.ohio-state.edu/~champion.17/5236/07_UIAndroid.pdf · UI Support in the Android SDK •“Inverted” paradigm –Each subclass constrains functionality

AccountFragment: onClick(): Java

@Overridepublic void onClick(View view) {

switch (view.getId()) {case R.id.done_button:

createAccount();break;

case R.id.cancel_button:mEtUsername.setText(""); mEtPassword.setText(""); mEtConfirm.setText("");break;

case R.id.exit_button:FragmentActivity activity = getActivity();if (activity != null) {

activity.getSupportFragmentManager().popBackStack();}

}} 31

Page 32: User Interface Developmentweb.cse.ohio-state.edu/~champion.17/5236/07_UIAndroid.pdf · UI Support in the Android SDK •“Inverted” paradigm –Each subclass constrains functionality

AccountFragment: onClick(): Kotlinoverride fun onClick(view: View) {

when (view.id) {R.id.done_button -> createAccount()R.id.cancel_button -> {

mEtUsername.setText("")mEtPassword.setText("")mEtConfirm.setText("")

}

R.id.exit_button -> activity?.supportFragmentManager?.popBackStack()

}}

32

Page 33: User Interface Developmentweb.cse.ohio-state.edu/~champion.17/5236/07_UIAndroid.pdf · UI Support in the Android SDK •“Inverted” paradigm –Each subclass constrains functionality

Thank You

Questions and comments?

33