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

07_UIAndroid.pdf

  • 1.
    User Interface Development CSE5236: 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 Supportin Android • Fragments 2
  • 3.
    UI Support inthe 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 • DirectSubclasses: – 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, LoginActivity <?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.
  • 9.
    Adding Resources 9 Resources canalso 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 UIto 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 UIto 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 CustomWidget: 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 CustomWidget: 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 CustomWidget: 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 Layoutvia 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 Supportin Android • Fragments 19
  • 20.
    Fragments and TheirRationale • 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 – Loginand Account
  • 22.
    Portrait Layout: Login 22 <?xmlversion="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 <?xmlversion="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 <?xmlversion="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 <?xmlversion="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 ViewonCreateView(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 funonCreateView(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 ViewonCreateView(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 funonCreateView(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 voidonClick(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 funonClick(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.