Switching UIs - Embedded Systems Programming 2012-2013

tibburfrogtownMobile - sans fil

14 déc. 2013 (il y a 3 années et 6 mois)

76 vue(s)

EMBEDDED SYSTEMS
PROGRAMMING 2012-13
Application Tip: Switching UIs
THE PROBLEM
How to switch from one UI to another
Each UI is associated with a distinct class that
controls it
Solution shown: two UIs, hence two classes. A button
in each UI triggers the switch to the other UI
THE TIP: ANDROID
Two classes derived from
Activity
The UIs associated with the classes are defined
declaratively, hence there are two XML layout files
The two classes invoke each other via
intents
INTENTS (1/3)
Intent:
abstract request for an action to be
performed
Explicit
intent: requires an exact component (e.g., a
class) to perform the operation
Implicit
intent: does not specify a class, but includes
enough information for the system to determine
which of the available components is to be invoked
(
intent resolution
)
INTENTS (2/3)
The intent resolution process may find more than
one suitable component: in this case, the final choice
is up to the user
Action requested: dial a phone call
INTENTS (3/3)
Intents have a flexible (and complex) syntax;
http://developer.android.com/reference/android/
content/Intent.html
provides full details
To invoke a specific component (such as an activity),
it is enough to build an intent specifying
a
context
of the application package
implementing the component,
the
component class
ANDROID CODE (1/6)
Source files:
Activity1.java
,
Activity2.java
Layouts:
main.xml
(associated with Activity1),
main2.xml
(associated with Activity2)
ANDROID CODE (2/6)
main.xml

<?xml

version
=
"1.0"

encoding
=
"utf-8"
?
>
<
LinearLayout xmlns:android=
"http://schemas.android.com/apk/res/android"
android:orientation=
"vertical"
android:layout_width=
"fill_parent"
android:layout_height=
"fill_parent"
android:background=
"#ffffff"

>

<
TextView android:layout_width=
"fill_parent"
android:layout_height=
"wrap_content"
android:textColor=
"#000000"
android:text=
"This is Activity 1"

/>

<
Button android:text=
"Next"
android:id=
"@+id/Button01"
android:layout_width=
"200px"
android:textSize=
"18px"
android:layout_height=
"55px"
>

</
Button
>

</
LinearLayout
>
ANDROID CODE (3/6)
main2.xml

<?xml

version
=
"1.0"

encoding
=
"utf-8"
?
>
<
LinearLayout xmlns:android=
"http://schemas.android.com/apk/res/android"
android:orientation=
"vertical"
android:layout_width=
"fill_parent"
android:layout_height=
"fill_parent"
android:background=
"#ffffff"

>

<
TextView
android:layout_width=
"fill_parent"
android:layout_height=
"wrap_content"
android:textColor=
"#000000"
android:text=
"This is Activity 2"

/>

<
Button
android:id=
"@+id/Button02"
android:layout_width=
"200px"
android:layout_height=
"55px"
android:text=
"Previous"
android:textSize=
"18px"
>

</
Button
>


<
CheckBox
android:id=
"@+id/plain_cb"
android:layout_width=
"200px"
android:layout_height=
"wrap_content"
android:text=
"Check me"
android:textColor=
"#000000"

/>
</
LinearLayout
>
ANDROID CODE (4/6)
Activity1.java

package
it.unipd.dei.switchactivity;
import
android.app.Activity;
import
android.content.Intent;
import
android.os.Bundle;
import
android.view.View;
import
android.widget.Button;
public

class
Activity1
extends
Activity {

/** Called when the activity is first created. */
@Override

public

void
onCreate(Bundle savedInstanceState) {

super
.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button next = (Button) findViewById(R.id.Button01);
next.setOnClickListener(
new
View.OnClickListener() {

public

void
onClick(View view) {
Intent myIntent =
new
Intent(view.getContext(), Activity2.
class
);
startActivityForResult(myIntent,
0
);
}
});
}
}
ANDROID CODE (5/6)
Activity2.java

package
it.unipd.dei.switchactivity;
import
android.app.Activity;
import
android.content.Intent;
import
android.os.Bundle;
import
android.view.View;
import
android.widget.Button;
public

class
Activity2
extends
Activity
{

/** Called when the activity is first created. */

public

void
onCreate(Bundle savedInstanceState)
{

super
.onCreate(savedInstanceState);
setContentView(R.layout.main2);
Button next = (Button) findViewById(R.id.Button02);
next.setOnClickListener(
new
View.OnClickListener()
{

public

void
onClick(View view)
{
Intent intent =
new
Intent();
setResult(RESULT_OK, intent);
finish();
}
});
}

}
ANDROID CODE (6/6)
Both activities should be declared in the
AndroidManifest.xml
file
<?
xml

version
=
"1.0"

encoding
=
"utf-8"
?>
<
manifest

xmlns:android
=
"http://schemas.android.com/apk/res/android"

package
=
"it.unipd.dei.switchactivity"

android:versionCode
=
"1"

android:versionName
=
"1.0"
>

<
uses-sdk

android:minSdkVersion
=
"8"

/>

<
application

android:icon
=
"@drawable/icon"

android:label
=
"@string/app_name"
>

<
activity

android:name
=
".Activity1"

android:label
=
"@string/app_name"
>

<
intent-filter
>

<
action

android:name
=
"android.intent.action.MAIN"

/>

<
category

android:name
=
"android.intent.category.LAUNCHER"

/>

</
intent-filter
>

</
activity
>

<
activity

android:name
=
".Activity2"
></
activity
>

</
application
>
</
manifest
>
THE TIP: IOS
Works in iOS 2.0 and above
Two classes derived from
UIViewController
The UIs associated with the classes are defined
declaratively in two XIB files
The two classes communicate by invoking an ad-hoc
method implemented in the delegate (this is just to
avoid having one more class hanging around)
IOS CODE (1/7)
Source files:
main.m
(default implementation: will not be shown),
SwitchViewAppDelegate.m
(and
.h
),
SwitchViewVC1.m
(and
.h
)
,
SwitchViewVC2.m
(and
.h
)
Other resources:
MainWindow.xib
,
SwitchViewVC1.xib
(associated with SwitchViewVC1),
SwitchViewVC2.xib
(associated with SwitchViewVC2)
IOS CODE (2/7)
SwitchViewVC1.xib

IOS CODE (3/7)
SwitchViewVC2.xib

IOS CODE (4/7)
SwitchViewAppDelegate.h
#import
<UIKit/UIKit.h>
@class
SwitchViewVC1;
@class
SwitchViewVC2;
@interface
SwitchViewAppDelegate : NSObject <UIApplicationDelegate>
{
UIWindow *window;
SwitchViewVC1 *viewController1;
SwitchViewVC2 *viewController2;
}
@property
(
nonatomic
,
retain
)
IBOutlet
UIWindow *window;
@property
(
nonatomic
,
retain
)
IBOutlet
SwitchViewVC1 *viewController1;
@property
(
nonatomic
,
retain
)
IBOutlet
SwitchViewVC2 *viewController2;
// Method that switches between the two views
- (
void
) switchView;
@end
IOS CODE (5/7)
SwitchViewAppDelegate.m
(fragment)
- (
BOOL
)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{

// At this point, the main nib file is loaded.

// View controller #1 is automatically allocated through the main nib,

// while view controller #2 must be instantiated by hand.
viewController2 = [[SwitchViewVC2 alloc] initWithNibName:
@"SwitchViewVC2"
bundle:
nil
];

// Set view controller #1 as the window's root view controller and display.

self
.window.rootViewController =
self
.viewController1;
[
self
.window makeKeyAndVisible];

return

YES
;
}
- (
void
)switchView
{

static

unsigned

int
numberOfSwitches =
0
;

// The transition between the two views is not animated, but it can be
++numberOfSwitches;

if
((numberOfSwitches%
2
) ==
1
)

self
.window.rootViewController =
self
.viewController2;

else

self
.window.rootViewController =
self
.viewController1;
}
IOS CODE (6/7)
SwitchViewVC1.h
#import
<UIKit/UIKit.h>
@interface
SwitchViewVC1 : UIViewController
{
}
- (
IBAction
)button1Pressed:(
id
)sender;
@end
SwitchViewVC2.h
is very similar and is not shown
IOS CODE (7/7)
SwitchViewVC1.m
(fragment)
SwitchViewVC2.m
is very similar and is not shown
#import
"SwitchViewVC1.h"
#import
"SwitchViewAppDelegate.h"
@implementation
SwitchViewVC1
- (
IBAction
)button1Pressed:(
id
)sender
{

// Perform what has to be done by invoking the switchView method.

// To keep the number of classes to a minimum, the method is

// implemented in the application delegate
SwitchViewAppDelegate *appDelegate = [[UIApplication sharedApplication]
delegate];
[appDelegate performSelector:
@selector
(switchView)];
}
...
THE TIP: IOS 5 (1/2)
Works in iOS 5.0 and above
Two classes derived from
UIViewController
The transitions between the two UIs are defined
via
Segues
using the
Storyboard
The UIs associated with the classes are defined
declaratively in the Storyboard file
THE TIP: IOS 5 (2/2)
In this second implementation of the tip, we will also
use Automatic Reference Counting (ARC)
to simplify memory management,
preserve the state of the switch
THE STORYBOARD (1/3)
Storyboard
: representation of the user interface
which describes the views and the relations among
them
Scene
: a view (or a set of views) and its content.
Each scene is associated with a view controller
Segue
: a transition between two views
Xcode provides a visual editor for storyboards
THE STORYBOARD (2/3)
Scene
Segue
View controller’s name
IOS CODE (1/10)
Source files:
main.m
(default implementation: will not be shown),
AppDelegate.m
(and
.h
) (default: not shown),
ViewController.m
(and
.h
) (default: not shown)
,
ViewController2.m
(and
.h
)
Other resources:
MainStoryboard.storyboard
IOS CODE (2/10)
Create a new Single View Application
Flag the “Use Storyboard” and “Use ARC” options
IOS CODE (3/10)
Create a new Objective-C class
bearing the name
ViewController2
IOS CODE (4/10)
Storyboard: design the first View Controller Scene
IOS CODE (5/10)
Storyboard: add the second View Controller.
Remember to link it to
ViewController2
IOS CODE (6/10)
Create a Segue from the “Next” button to the
second Scene. Select the “Modal” style
IOS CODE (7/10)
Create a second Segue connecting the “Previous”
button to the first Scene
IOS CODE (8/10)
ViewController2.h

#import
<UIKit/UIKit.h>

@interface
ViewController2 :
UIViewController
{


UISwitch
*sw;

}
@property
(
nonatomic
,
retain
)
IBOutlet

UISwitch
*sw;
@end
IOS CODE (9/10)
ViewController2.m
(fragment)

...

@implementation
ViewController2
@synthesize
sw;

static

BOOL
swstate;
// Contains the state of the switch
...
- (
void
)viewDidLoad
{
[
super

viewDidLoad
];

// Do any additional setup after loading the view.

NSLog
(
@"View2 loaded"
);


// Restore the state of the switch
[
sw

setOn
:
swstate
];

}
- (
void
) viewWillDisappear: (
BOOL
)animated
{


NSLog
(
@"View2 to disappear"
);



// Save the current state of the switch

swstate
=
sw
.
on
;

}
...
@end
IOS: CODE (10/10)
Remember to connect the switch to the
sw
outlet
CTRLClick from the second View Controller
to the switch, then select the “sw” outlet
HOMEWORKS
Android: what happens if the screen is rotated? Why?
iOS: arrange the UIs in a stack
(hint: use a Navigation Controller)
LAST MODIFIED: APRIL 30, 2013
COPYRIGHT HOLDER: CARLO FANTOZZI (
FANTOZZIDEI.UNIPD.IT
)
LICENSE:
CREATIVE COMMONS ATTRIBUTION SHARE-ALIKE 3.0