SlideShare a Scribd company logo
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
Outline
• UI Support in Android
• Fragments
2
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
View Hierarchy
4
# = SDK Version number
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
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>
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
8
Adding Resources
9
Resources can also
be added by right-
clicking on res
directory, selecting
New→Android
Resource File
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
Linking a UI to a Fragment: Java
// LoginActivity.java
public class LoginActivity extends SingleFragmentActivity {
@Override
protected Fragment createFragment() { return new LoginFragment(); }
}
// LoginFragment.java
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_login, container, false);
// Real code handles view rotation
mUsernameEditText = (EditText) v.findViewById(R.id.username_text);
mPasswordEditText = (EditText) v.findViewById(R.id.password_text);
// Setup listener objects for buttons
return v;
}
11
Also can set up listener objects in Activities with onCreate()
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 rotation
mUsernameEditText = v.findViewById<EditText>(R.id.username_text)
mPasswordEditText = v.findViewById<EditText>(R.id.password_text)
// Set up listener objects for Buttons
return v
}
12
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.Board
android:id="@+id/board"
android:layout_width="match_parent"
android:layout_height="280dip"/>
...
</LinearLayout>
13
Creating a Custom Widget: Java
// Board.java
public 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); // . . .
}
@Override
protected 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);
Creating a Custom Widget: Kotlin
// Board.kt
class Board(context: Context, attributes: AttributeSet) : View(context, attributes) {
init {
isFocusable = true
isFocusableInTouchMode = 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)
Creating a Layout via Code
// DohActivity.java
@Override
public 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
Styles and Themes (1)
Use:
<EditText
style=”@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>
Styles and Themes (2)
• Stored in res/values/ directory with .xml
extension (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.html
18
Outline
• UI Support in Android
• Fragments
19
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 experience
20
Example – Login and Account
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>
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
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
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
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
LoginFragment: Java
@Override
public 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 buttons
return v;
}
27
LoginFragment: Kotlin
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
val v: View
val rotation = activity.windowManager.defaultDisplay.rotation
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 = v.findViewById<EditText>(R.id.username_text)
mPasswordEditText = v.findViewById<EditText>(R.id.password_text)
// Set up onClickListeners for buttons
return v
}
28
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
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
AccountFragment: onClick():
Java
@Override
public 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
AccountFragment: onClick():
Kotlin
override 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
Thank You
Questions and comments?
33

More Related Content

Similar to 07_UIAndroid.pdf

行動App開發管理實務 unit2
行動App開發管理實務 unit2行動App開發管理實務 unit2
行動App開發管理實務 unit2
Xavier Yin
 
Answer1)Responsive design is the idea where all the developed pag.pdf
Answer1)Responsive design is the idea where all the developed pag.pdfAnswer1)Responsive design is the idea where all the developed pag.pdf
Answer1)Responsive design is the idea where all the developed pag.pdf
ankitcomputer11
 
Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점
Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점
Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점
Jeado Ko
 
Zyncro zyncro apps & ui customization feb 2013
Zyncro zyncro apps & ui customization feb 2013Zyncro zyncro apps & ui customization feb 2013
Zyncro zyncro apps & ui customization feb 2013
Zyncro
 

Similar to 07_UIAndroid.pdf (20)

08ui.pptx
08ui.pptx08ui.pptx
08ui.pptx
 
Android development for iOS developers
Android development for iOS developersAndroid development for iOS developers
Android development for iOS developers
 
Android Tutorial
Android TutorialAndroid Tutorial
Android Tutorial
 
Native Android Development Practices
Native Android Development PracticesNative Android Development Practices
Native Android Development Practices
 
Android Workshop
Android WorkshopAndroid Workshop
Android Workshop
 
Android por onde começar? Mini Curso Erbase 2015
Android por onde começar? Mini Curso Erbase 2015 Android por onde começar? Mini Curso Erbase 2015
Android por onde começar? Mini Curso Erbase 2015
 
Lec005 android start_program
Lec005 android start_programLec005 android start_program
Lec005 android start_program
 
Android programming basics
Android programming basicsAndroid programming basics
Android programming basics
 
Design Patterns for Tablets and Smartphones
Design Patterns for Tablets and SmartphonesDesign Patterns for Tablets and Smartphones
Design Patterns for Tablets and Smartphones
 
行動App開發管理實務 unit2
行動App開發管理實務 unit2行動App開發管理實務 unit2
行動App開發管理實務 unit2
 
Hello Android
Hello AndroidHello Android
Hello Android
 
Android 3
Android 3Android 3
Android 3
 
Answer1)Responsive design is the idea where all the developed pag.pdf
Answer1)Responsive design is the idea where all the developed pag.pdfAnswer1)Responsive design is the idea where all the developed pag.pdf
Answer1)Responsive design is the idea where all the developed pag.pdf
 
Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점
Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점
Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점
 
Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점
Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점 Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점
Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점
 
Angular server side rendering - Strategies & Technics
Angular server side rendering - Strategies & Technics Angular server side rendering - Strategies & Technics
Angular server side rendering - Strategies & Technics
 
Writing HTML5 Web Apps using Backbone.js and GAE
Writing HTML5 Web Apps using Backbone.js and GAEWriting HTML5 Web Apps using Backbone.js and GAE
Writing HTML5 Web Apps using Backbone.js and GAE
 
Android Development Made Easy - With Sample Project
Android Development Made Easy - With Sample ProjectAndroid Development Made Easy - With Sample Project
Android Development Made Easy - With Sample Project
 
Zyncro zyncro apps & ui customization feb 2013
Zyncro zyncro apps & ui customization feb 2013Zyncro zyncro apps & ui customization feb 2013
Zyncro zyncro apps & ui customization feb 2013
 
What's New in Android
What's New in AndroidWhat's New in Android
What's New in Android
 

Recently uploaded

Industrial Training Report- AKTU Industrial Training Report
Industrial Training Report- AKTU Industrial Training ReportIndustrial Training Report- AKTU Industrial Training Report
Industrial Training Report- AKTU Industrial Training Report
Avinash Rai
 

Recently uploaded (20)

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 
Mattingly "AI & Prompt Design: Limitations and Solutions with LLMs"
Mattingly "AI & Prompt Design: Limitations and Solutions with LLMs"Mattingly "AI & Prompt Design: Limitations and Solutions with LLMs"
Mattingly "AI & Prompt Design: Limitations and Solutions with LLMs"
 
INU_CAPSTONEDESIGN_비밀번호486_업로드용 발표자료.pdf
INU_CAPSTONEDESIGN_비밀번호486_업로드용 발표자료.pdfINU_CAPSTONEDESIGN_비밀번호486_업로드용 발표자료.pdf
INU_CAPSTONEDESIGN_비밀번호486_업로드용 발표자료.pdf
 
The Art Pastor's Guide to Sabbath | Steve Thomason
The Art Pastor's Guide to Sabbath | Steve ThomasonThe Art Pastor's Guide to Sabbath | Steve Thomason
The Art Pastor's Guide to Sabbath | Steve Thomason
 
NCERT Solutions Power Sharing Class 10 Notes pdf
NCERT Solutions Power Sharing Class 10 Notes pdfNCERT Solutions Power Sharing Class 10 Notes pdf
NCERT Solutions Power Sharing Class 10 Notes pdf
 
Solid waste management & Types of Basic civil Engineering notes by DJ Sir.pptx
Solid waste management & Types of Basic civil Engineering notes by DJ Sir.pptxSolid waste management & Types of Basic civil Engineering notes by DJ Sir.pptx
Solid waste management & Types of Basic civil Engineering notes by DJ Sir.pptx
 
Industrial Training Report- AKTU Industrial Training Report
Industrial Training Report- AKTU Industrial Training ReportIndustrial Training Report- AKTU Industrial Training Report
Industrial Training Report- AKTU Industrial Training Report
 
Jose-Rizal-and-Philippine-Nationalism-National-Symbol-2.pptx
Jose-Rizal-and-Philippine-Nationalism-National-Symbol-2.pptxJose-Rizal-and-Philippine-Nationalism-National-Symbol-2.pptx
Jose-Rizal-and-Philippine-Nationalism-National-Symbol-2.pptx
 
Fish and Chips - have they had their chips
Fish and Chips - have they had their chipsFish and Chips - have they had their chips
Fish and Chips - have they had their chips
 
Ethnobotany and Ethnopharmacology ......
Ethnobotany and Ethnopharmacology ......Ethnobotany and Ethnopharmacology ......
Ethnobotany and Ethnopharmacology ......
 
Synthetic Fiber Construction in lab .pptx
Synthetic Fiber Construction in lab .pptxSynthetic Fiber Construction in lab .pptx
Synthetic Fiber Construction in lab .pptx
 
Application of Matrices in real life. Presentation on application of matrices
Application of Matrices in real life. Presentation on application of matricesApplication of Matrices in real life. Presentation on application of matrices
Application of Matrices in real life. Presentation on application of matrices
 
Advances in production technology of Grapes.pdf
Advances in production technology of Grapes.pdfAdvances in production technology of Grapes.pdf
Advances in production technology of Grapes.pdf
 
50 ĐỀ LUYỆN THI IOE LỚP 9 - NĂM HỌC 2022-2023 (CÓ LINK HÌNH, FILE AUDIO VÀ ĐÁ...
50 ĐỀ LUYỆN THI IOE LỚP 9 - NĂM HỌC 2022-2023 (CÓ LINK HÌNH, FILE AUDIO VÀ ĐÁ...50 ĐỀ LUYỆN THI IOE LỚP 9 - NĂM HỌC 2022-2023 (CÓ LINK HÌNH, FILE AUDIO VÀ ĐÁ...
50 ĐỀ LUYỆN THI IOE LỚP 9 - NĂM HỌC 2022-2023 (CÓ LINK HÌNH, FILE AUDIO VÀ ĐÁ...
 
MARUTI SUZUKI- A Successful Joint Venture in India.pptx
MARUTI SUZUKI- A Successful Joint Venture in India.pptxMARUTI SUZUKI- A Successful Joint Venture in India.pptx
MARUTI SUZUKI- A Successful Joint Venture in India.pptx
 
Instructions for Submissions thorugh G- Classroom.pptx
Instructions for Submissions thorugh G- Classroom.pptxInstructions for Submissions thorugh G- Classroom.pptx
Instructions for Submissions thorugh G- Classroom.pptx
 
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 
Salient features of Environment protection Act 1986.pptx
Salient features of Environment protection Act 1986.pptxSalient features of Environment protection Act 1986.pptx
Salient features of Environment protection Act 1986.pptx
 
Basic phrases for greeting and assisting costumers
Basic phrases for greeting and assisting costumersBasic phrases for greeting and assisting costumers
Basic phrases for greeting and assisting costumers
 
Basic Civil Engg Notes_Chapter-6_Environment Pollution & Engineering
Basic Civil Engg Notes_Chapter-6_Environment Pollution & EngineeringBasic Civil Engg Notes_Chapter-6_Environment Pollution & Engineering
Basic Civil Engg Notes_Chapter-6_Environment Pollution & Engineering
 

07_UIAndroid.pdf

  • 1. 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
  • 2. Outline • UI Support in Android • Fragments 2
  • 3. 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
  • 4. View Hierarchy 4 # = SDK Version number
  • 5. 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
  • 6. 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>
  • 7. 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
  • 8. 8
  • 9. Adding Resources 9 Resources can also be added by right- clicking on res directory, selecting New→Android Resource File
  • 10. 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
  • 11. Linking a UI to a Fragment: Java // LoginActivity.java public class LoginActivity extends SingleFragmentActivity { @Override protected Fragment createFragment() { return new LoginFragment(); } } // LoginFragment.java @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.fragment_login, container, false); // Real code handles view rotation mUsernameEditText = (EditText) v.findViewById(R.id.username_text); mPasswordEditText = (EditText) v.findViewById(R.id.password_text); // Setup listener objects for buttons return v; } 11 Also can set up listener objects in Activities with onCreate()
  • 12. 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 rotation mUsernameEditText = v.findViewById<EditText>(R.id.username_text) mPasswordEditText = v.findViewById<EditText>(R.id.password_text) // Set up listener objects for Buttons return v } 12
  • 13. 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.Board android:id="@+id/board" android:layout_width="match_parent" android:layout_height="280dip"/> ... </LinearLayout> 13
  • 14. Creating a Custom Widget: Java // Board.java public 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); // . . . } @Override protected 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);
  • 15. Creating a Custom Widget: Kotlin // Board.kt class Board(context: Context, attributes: AttributeSet) : View(context, attributes) { init { isFocusable = true isFocusableInTouchMode = 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)
  • 16. Creating a Layout via Code // DohActivity.java @Override public 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
  • 17. Styles and Themes (1) Use: <EditText style=”@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>
  • 18. Styles and Themes (2) • Stored in res/values/ directory with .xml extension (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.html 18
  • 19. Outline • UI Support in Android • Fragments 19
  • 20. 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 experience 20
  • 21. Example – Login and Account
  • 22. 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>
  • 23. 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
  • 24. 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
  • 25. 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
  • 26. 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
  • 27. LoginFragment: Java @Override public 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 buttons return v; } 27
  • 28. LoginFragment: Kotlin override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { val v: View val rotation = activity.windowManager.defaultDisplay.rotation 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 = v.findViewById<EditText>(R.id.username_text) mPasswordEditText = v.findViewById<EditText>(R.id.password_text) // Set up onClickListeners for buttons return v } 28
  • 29. 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
  • 30. 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
  • 31. AccountFragment: onClick(): Java @Override public 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
  • 32. AccountFragment: onClick(): Kotlin override 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
  • 33. Thank You Questions and comments? 33