Download presentation
Presentation is loading. Please wait.
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)
2
Outline UI Support in Android Fragments
3
UI Support in the Android SDK
“Inverted” paradigm Each subclass constrains functionality (rather than extend it) Hundreds of methods are exposed: Base classes: ViewGroup base class for composite UI elements View base class for terminal UI components
4
View Hierarchy # = SDK Version number
5
ViewGroup Hierarchy Direct Subclasses: 19 indirect subclasses. See:
AbsoluteLayout AdapterView<T extends Adapter> FragmentBreadCrumbs FrameLayout GridLayout LinearLayout PagerTitleStrip RelativeLayout SlidingDrawer ViewPager 19 indirect subclasses. See:
6
Sample Layout, Login Activity
<?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android=" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent" android:padding="20dip"> <LinearLayout android:orientation="vertical ... <TextView ... /> <TextView ... /> <EditText ... /> <EditText ... /> <Button ... /> </LinearLayout> </ScrollView>
7
Layout Configuration ID: : 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): Blank canvases using a (generic) View element in the layout See Android SDK book Chapter 5 for details
9
Adding Resources 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
11
Linking a UI to a Fragment: Java
// LoginActivity.java public class LoginActivity extends SingleFragmentActivity protected Fragment createFragment() { return new LoginFragment(); } } // 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; } 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 }
13
Creating a Custom Widget: Layout
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns: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:layout_height="280dip"/> ... </LinearLayout>
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); // protected void onDraw(Canvas canvas) { super.onDraw(canvas); // } } 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) // . . . 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
// 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); }
17
Styles and Themes (1) Use: Definition: Inheritance: <EditText
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 ... more parameters ... </style> </resources> Inheritance: <style name=“DarkPhone” <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 <activity Can even create version-specific layout files Ref: ui/themes.html
19
Outline UI Support in Android Fragments
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
21
Example – Login and Account
22
Portrait Layout: Login
<?xml version="1.0" encoding="utf-8"?> <ScrollView ...> <LinearLayout...> <TextView <TextView <EditText <TextView android:text="Enter Password".../> <EditText <Button <Button <Button </LinearLayout> </ScrollView>
23
Portrait Layout: Account
<?xml version="1.0" encoding="utf-8"?> <LinearLayout ...> <FrameLayout .../> ⟸ Placeholder for fragment <Button </LinearLayout> What happened to landscape layout of the Fragment?
24
Landscape Layout: Login
<?xml version="1.0" encoding="utf-8"?> <LinearLayout... android:orientation="horizontal” ...> ⟸ Note: horizontal layout <ScrollView ... > <LinearLayout .. > <TextView ... /> <! > </LinearLayout> </ScrollView> <fragment class="com.wiley.fordummies.androidsdk.tictactoe.AccountFragment" android:layout_height="match_parent” . . ./>
25
AccountFragment: Portrait Layout
<?xml version="1.0" encoding="utf-8"?> <LinearLayout ...> <LinearLayout...> <TextView android:text="New Account" .../> <TextView android:text="Username”.../> <EditText <TextView android:text="Password”.../> <EditText <TextView android:text="Confirm Password" .../> <EditText <Button "/> <Button </LinearLayout>
26
AccountFragment: Landscape Layout
<?xml version="1.0" encoding="utf-8"?> <LinearLayout...> <TextView android:text="New Account”.../> <TextView android:text="Username”.../> <EditText <TextView android:text="Password" .../> <EditText <TextView android:text="Confirm Password" .../> <EditText <LinearLayout ... > <Button <Button </LinearLayout>
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; }
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 }
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; }
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 }
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(); } } }
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() } }
33
Thank You Questions and comments?
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.