User Interface Development - Ohio State University

Transcription

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

Outline UI Support in Android Fragments2

UI Support in the Android SDK “Inverted” paradigm– Each subclass constrains functionality (ratherthan extend it)– Hundreds of methods are exposed: L Base classes:– ViewGroup base class for composite UIelements– View base class for terminal UI components3

View Hierarchy# SDK Version number4

ViewGroup Hierarchy Direct View T extends Adapter DrawerViewPager 19 indirect subclasses. See:– w/ViewGroup.html5

Sample Layout, Login Activity ?xml version "1.0" encoding "utf-8"? ScrollView xmlns:android oid: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 layout7

8

Adding ResourcesResources can alsobe added by rightclicking on resdirectory, selectingNew AndroidResource File9

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 forflexible widget rendering10

Linking a UI to a Fragment: Java// LoginActivity.javapublic 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()

Linking a UI to a Fragment: Kotlin// LoginActivity.ktclass 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 Buttonsreturn v}12

Creating a Custom Widget: Layout ?xml version "1.0" encoding "utf-8"? LinearLayoutxmlns:android d:layout width "match parent"android:layout height "match parent"android:orientation "vertical"android:background "#676767"android:gravity "center horizontal"android:padding "20dip" roid:id "@ id/board"android:layout width "match parent"android:layout height "280dip"/ . /LinearLayout 13

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); // . . .}}Instantiating the view:// LoginFragment.java: onCreateView() and setupBoard()// onCreateView()v inflater.inflate(R.layout.fragment game session, . . .);// setupBoard()14mBoard (Board) v.findViewById(R.id.board);

Creating a Custom Widget: Kotlin// Board.ktclass 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) // . . .}}Instantiating the view:// LoginFragment.kt, onCreateView() and setupBoard()// onCreateView()v inflater.inflate(R.layout.fragment game session, container, false)// setupBoard()15mBoard (Board) v.findViewById(R.id.board)

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 ayout);}16

Styles and Themes (1)Use: EditTextstyle ”@style/DarkBold”android:text ”Hello” / Inheritance: style name “DarkPhone” parent ”@style/DarkBold” item name ”android:phoneNumber” true /item /style 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

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: s.html18

Outline UI Support in Android Fragments19

Fragments and Their Rationale Fragment: Composite UI component that handles itsown 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

Example – Login and Account

Portrait Layout: Login ?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 22

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” . ScrollView . LinearLayout . Note: horizontal layout TextView . / TextView . / !-- . . . -- /LinearLayout /ScrollView fragment class Fragment"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: LandscapeLayout ?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@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {View v;int rotation ().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

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

AccountFragment:onCreateView(): Javapublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {// Inflate the layout for this fragmentView v inflater.inflate(R.layout.accountfragment, container, false);Activity activity getActivity();if (activity ! null) {int rotation tRotation();mEtUsername v.findViewById(R.id.username);mEtPassword v.findViewById(R.id.password);mEtConfirm v.findViewById(R.id.password confirm);// OnClickListeners for Add, Cancel buttonsButton 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(): Kotlinoverride 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 buttonsval 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@Overridepublic void onClick(View view) {switch (view.getId()) {case R.id.done button:createAccount();break;case R.id.cancel button:mEtUsername.setText(""); ak;case R.id.exit button:FragmentActivity activity getActivity();if (activity ! null) ();}}}31

AccountFragment: onClick():Kotlinoverride fun onClick(view: View) {when (view.id) {R.id.done button - createAccount()R.id.cancel button - Confirm.setText("")}R.id.exit button - 32

Thank YouQuestions and comments?33

User Interface Development. 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.