Posts Tagged: iPhone


13
Sep 12

iGrow – Corporate Growth at all Levels

iGROW is an iOS/Android application that was created by APP-SOLUT for Summerrain GmbH (Switzerland).

The application supports individual growth as well as personal performance improvement and aligns it with the achievement of strategic enterprise objectives. This is accomplished by simple exercises that require little time and are performed daily by the staff.

iGROW can be used in companies, associations or societies of any kind that want to realize the full potential of their employees. Continue reading →


31
Aug 12

Voting UPP – Direct Feedback

Voting Upp is a voting system that allows quick creation of surveys and direct feedback. It uses existing hardware, is platform-independent and does not need an installation.

Voting System for Teaching Activities

Voting Upp is a system for creating and conducting surveys at universities and colleges. It provides an immediate and direct feedback and it is easy to use. The necessary hardware devices are already available everywhere.

The creation of the questions is web-based with Internet-enabled devices such as PC, laptop, Mac, tablets. No installation is required.

Participants in the survey also use common Internet-enabled devices such as smartphone, laptop or tablet. For iOS and Android, apps can be loaded from the respective app stores; all other systems are browser-based web apps. Continue reading →


12
Mar 12

Augmented Reality-App by Auto-Bild

Augmented Reality may have great potential – however, the introduction of this new technique has been rather slow so far.

Now Auto-Bild has developed in collaboration with Metaio a new app for iOS/Android, that adds interactive content to its articles. The app responds to code symbols contained in the articles, and launches the associated content.

If you are a reader of Auto-Bild, don’t miss this (free) app.

Auto-Bild is one of the major German car magazines. More information is available at the Auto-Bild website.

For details about augmented reality, see this article.


14
Feb 12

sense4c …smart measurement

sense4c-TRF01 is an adapter for smartphones and tablets that is equipped with a high-precision, digital temperature and humidity sensor. It enables fast and mobile detection of climate conditions in buildings, garment components or intermediate layers.

The sensor is plugged into the headphone jack and requires no external power supply. The collected data are presented graphically on the display and recorded in the background. The smartphone provides additional information such as position data (GPS) and ensures that the data are synchronized in the cloud. The data transmission is encrypted so that sensitive information is secured. Authorized users can access the data from any location and may even intervene actively using the return channel. Continue reading →


4
Oct 11

Article in Tcworld

The october-issue (10/2011) of tcworld has recently been published. We have contributed an article: ‘Augmented Reality in Technical Communication’. Tcworld is one of the leading online magazines for technical communication and information management.

The article comprises the following topics:

  • What is augmented reality?
  • Which role plays augmented reality in technical communication?
    In the next years, there is a high probability that augmented reality will be used more and more as third way (in addition to paper and display) of transmitting technical information.
  • How does the application of augmented reality influence the writing of technical manuals?

You find the article at the tcworld website.


20
Jun 11

Industrial Applications for Tablets: Customer Service

Currently there are only few applications for smartphones/tablets, that play a role in industrial processes and are actually used in customer service or in production. With the new generations of smartphones/tablets and the advance of new forms of information distribution (e.g., augmented reality), a much wider range of use is possible in industry.

In the following article I use the example of an application for customer service to demonstrate how such a usage might look like. Continue reading →


13
May 11

Combining Interactive Video and WebView Control into a Powerful iOS App

By reviewing our two articles (interfacing a webview from within an iOS app and displaying scheduled box elements on top of HTML5 video), a combined application might come in your mind. Think of an iOS app which plays an HTML5 video you can stop, play and interact with. This is exactly what we’re going to build in this tutorial.

The HTML

Because only small changes are necessary, we will start by editing the HTML/JS code provided in this article. First, we attach a JavaScript onclick attribute to every elements’ surrounding <div>  via the setupItems() function:

var t = $("<div class=\"overlay_item\" id=\"item_"+i+"\" data-id=\""+items[i][0]+"\" onclick=\"Overlay.call('"+items[i][0]+"')\">"+items[i][3]+"</div>");

(Note that the encoding is necessary because the above string is given as function parameter).

As you can see, Overlay.call() is called with the appropriate item id when clicking on a box. Call() works similar to the way we used windows.location to submit data to the iOS parent app in a previous article – it takes the id and forwards the page to something like ?cmd=call&param=2. This string  can be read later by the iOS app.

That’s it! Now fire up Xcode and create a new view based application. Call it App Solut InteractiveVideoInterface and open your ViewController header file. Put this code in:

@interface App_Solut_InteractiveVideoInterfaceViewController : UIViewController {

IBOutlet UIWebView *webView;
IBOutlet UILabel *label;
}
@property(retain, nonatomic) UIWebView *webView;
@property(retain, nonatomic) UILabel *label;

@end

Save the file, switch to interface builder and edit your ViewControllers’ xib file. Drag both a webView and a label to the screen and connect the just created outlets. To do so, control-drag from your webview object to the files’ owner and select delegate. Then do the same vice-versa: Control-drag (or right click-drag if you own a standard mouse) from files’ owner to both the webview and the label and select the appropriate entries from the list. You have now created the connection between your code and your interface.

In your implementation file synthesize both the label and the webview:

@synthesize webView;
@synthesize label;

Similar to the webview interface code we add the following function to catch all webpage requests.

- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType {
NSString *url = [[request URL] absoluteString];
NSArray *urlArray = [url componentsSeparatedByString:@"?"];
NSString *cmd = @"";
NSMutableArray *paramsToPass = nil;
if([urlArray count] > 1) {
NSString *paramsString = [urlArray objectAtIndex:1];
NSArray *urlParamsArray = [paramsString componentsSeparatedByString:@"&"];
cmd = [[[urlParamsArray objectAtIndex:0] componentsSeparatedByString:@"="] objectAtIndex:1];
int numCommands = [urlParamsArray count];
paramsToPass = [[NSMutableArray alloc] initWithCapacity:numCommands-1];
for(int i = 1; i < numCommands; i++){
NSString *aParam = [[[urlParamsArray objectAtIndex:i] componentsSeparatedByString:@"="] objectAtIndex:1];
[paramsToPass addObject:aParam];
}
}
if([cmd compare:@"call"] == NSOrderedSame) {
NSString *message = [[paramsToPass objectAtIndex:0]stringByReplacingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
[label setText:[NSString stringWithFormat:@"You just clicked button #%@", message]];
}
/* Only load the page if it is not an appcall */
NSRange aSubStringRange = [url rangeOfString:@"appcall"];
if(aSubStringRange.length != 0){
NSLog(@"App call found: request cancelled");
return NO;
} else {
return YES;
}
}

You can see that the value given in the parameter param is attached to a string which is then set as the label text. In this scenario, every video overlay will have it’s own ID send to the app when clicked on. From this point your imagination is set free. You can at this point react to the users click and do whatever you want.

Download sample project

Again, you can find a sample project at GitHub: InteractiveVideoInterface-Example


2
May 11

iOS: Interfacing WebView Content via JavaScript

A WebView element is a smart and easy way to integrate both platform-independent and dynamic content into an ordinary iOS app. While using it to display webpages might be simple things become more complicated when some kind of interaction between the parent app and the webpage is needed. At the moment there is no common way for a page to send any messages to its WebView controller. This article shows basic principles of a two-way communication, providing a work-around for the function missing.
At the end you’ll find a download link to a full iOS sample project.

Calling JavaScript code from your App

This part is easy: Assuming you have a WebView set up in your project displaying just any page. There is a method called stringByEvaluatingJavaScriptFromString which does the job. Example:

[myWebView stringByEvaluatingJavaScriptFromString:@"alert('Hello World!');"];

Will display – you guessed it – an alert message sent by your webpage. That way you can call any JavaScript function available to your webpage from outside, making it a snap to alter pages on the fly.

Calling functions in your App from inside a WebView

As I mentioned earlier, the other way around is far more complicated. First, we have to think about a way a webpage can communicate to an app. Fortunately, the WebView element provides some interesting attributes and events.
First of all an event called shouldStartLoadWithRequest is fired when a page is requested. Here is an example implementation:

-(BOOL)myWebView:(UIWebView*)myWebView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNaviagtionType)navigationType {
   [...]
}

The great thing about this function is that it is called before the page actually gets loaded and that it expects a boolean as a return. Returning YES makes the WebView start loading the desired page while returning NO stops it from doing so.
Now the plan is as follows: A JavaScript function loads a fictional page including some GET parameters via window.location. Because of the special URL keyword the app is able to figure out whether a real page should be loaded or an in-app function is called (namely an app-call). At that point the function can stop the request and execute the action or just let it load.
So the above function needs to get two things done:

  • check whether a normal link or an app call is requested and returning the proper boolean
  • extract given parameters and check if they fit into predefined actions

Based on a sample by tetontech this is the code we are going to talk about:

- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType {
 NSString *url = [[request URL] absoluteString];
 NSLog(@"Requesting: %@",url);
 NSArray *urlArray = [url componentsSeparatedByString:@"?"];
 NSString *cmd = @"";
 NSMutableArray *paramsToPass = nil;
 // isolate command and parameters
 if([urlArray count] < 1){
 NSString *paramsString = [urlArray objectAtIndex:1];
 NSArray *urlParamsArray = [paramsString componentsSeparatedByString:@"&"];
 cmd = [[[urlParamsArray objectAtIndex:0] componentsSeparatedByString:@"="] objectAtIndex:1];
 int numCommands = [urlParamsArray count];
 paramsToPass = [[NSMutableArray alloc] initWithCapacity:numCommands-1];
 for(int i = 1; i &lt; numCommands; i++){
 NSString *aParam = [[[urlParamsArray objectAtIndex:i] componentsSeparatedByString:@"="] objectAtIndex:1];
 [paramsToPass addObject:aParam];
 }
 }
 if([cmd compare:@"toggleWorking"] == NSOrderedSame){
 NSLog(@"Turning working indicator...");
 if([UIApplication sharedApplication].networkActivityIndicatorVisible == NO) {
 [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
 NSLog(@"...on");
 } else {
 [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
 NSLog(@"...off");
 }
 } else if([cmd compare:@"logMessage"] == NSOrderedSame) {
 NSString *message = [[paramsToPass objectAtIndex:0] stringByReplacingOccurrencesOfString:@"%20" withString:@" "];
 NSString *message = [[paramsToPass objectAtIndex:0] stringByReplacingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
 NSLog(@"Received JS message: %@",message);
 }
 // only load the page if it is the initial index.html file
 NSRange aSubStringRange = [url rangeOfString:@"index.html"];
 if(aSubStringRange.length != 0){
 return YES;
 } else {
 NSLog(@"App call found: request cancelled");
 return NO;
 }
}

As stated before this function extracts and isolates every parameter and command given and runs through a couple of if-statements to check whether a command is recognized. If that’s the case additional arguments might be used to execute an action.

In this example there are just two possible actions to call: By requesting ?cmd=toggleWorking a spinning wheel in iPads’ tab bar is turned on or off depending on it’s current state. Second action logMessage might be called like this: ?cmd=logMessage&param=Hello%20World. It will forward any given message to the debug console as a log.

NSRange aSubStringRange = [url rangeOfString:@"index.html"];
if(aSubStringRange.length != 0){

The last check is really important! Assuming your mainpage is named index.html this makes sure the page gets loaded once at start. Other requests are blocked right now but you can most likely think of different approaches to make sure app calls don’t get loaded.

Download sample project

Header over to GitHub and download the WebViewInterface-Example
Source:


14
Apr 11

Custom UITableViewCells with round corners

In order to implement your own style ideas or a given layout it might be necessary to create custom UITableViewCells with round corners. In the App the UITableView might look like this:

Custom UITableViewCell with round corners

With your custom UITableViewCell class and some core graphics it’s quite easy to solve this problem.

Open your project in XCode. At first we have to add a new file of type UITableViewCell. I call it “RoundedTableViewCell”.

We have to import the QuartzCore framework which includes all core graphics.

#import <QuartzCore/QuartzCore/>

Don’t forget to add it also to the “frameworks” folder of your project:

add QuartzCore FRamework to your project add QuartzCore framework

In the RoundedTableViewCell.h-file we define a CALayer for every corner of the cell. These small square layers will later on “cover” the round corners where desired.

CALayer* topleft;
CALayer* topright;
CALayer* bottomleft;
CALayer* bottomright;
CALayer* bglayer;
...
@property (nonatomic, retain) CALayer* topleft;
@property (nonatomic, retain) CALayer* topright;
@property (nonatomic, retain) CALayer* bottomleft;
@property (nonatomic, retain) CALayer* bottomright;
@property (nonatomic, retain) CALayer* bglayer;

We also need two BOOLs:

BOOL roundTop;
BOOL roundBottom;
...
@property (nonatomic) BOOL roundTop;
@property (nonatomic) BOOL roundBottom;

.. and two methods to tell the single cell to have round corners at the top and/or the bottom:

-(void) drawRoundTop;
-(void) drawRoundBottom;

That’s it for the .h-file. In the RoundedTableViewCell.m we have now to implement the rounded corners. At first we define a corner radius and a background color for the cell (between #import and @implemetation):

#define rad 15  // radius
#define normalColor [UIColor colorWithRed:0.39 green:0.15 blue:0.24 alpha:1.0]  // cell background color, dark red

Whithin the implementation we have to synthesize our defined CALayers and BOOLs:

@synthesize topleft;
@synthesize topright;
@synthesize bottomleft;
@synthesize bottomright;
@synthesize bglayer;
@synthesize roundTop;
@synthesize roundBottom;

In the initWithStyle-Method we define an UILabel with some style attributes:

// add label
 label = [[UILabel alloc] initWithFrame:self.contentView.frame];
 label.textAlignment = UITextAlignmentLeft;
 label.backgroundColor = [UIColor clearColor];
 label.textColor = [UIColor whiteColor];
 label.font = [UIFont fontWithName:@"Zapfino" size:16];
 [self.contentView addSubview:label];

// initial values
 roundTop = NO;
 roundBottom = NO;
// set layer background color (= cell background color)
 self.layer.backgroundColor = normalColor.CGColor;

Still within the initWithStyle-method, we set the initial cell style without round top or bottom corners and set the cell’s background color:

roundTop = NO;
roundBottom = NO;
self.layer.backgroundColor = normalColor.CGColor;

Our custom drawRect method will draw our round corners, depending on the defined corner radius. Then the round corners are “covered” by drawing a CALayer for every corner:

- (void) drawRect:(CGRect)rect{
	CGRect fr = rect;

	fr.size.width = fr.size.width-2*rad;
	fr.size.height = fr.size.height-1;
	fr.origin.x = rad;

	// draw round corners layer
	bglayer = [CALayer layer];
    bglayer.backgroundColor = normalColor.CGColor;
	bglayer.cornerRadius = rad;
	bglayer.frame = fr;
	bglayer.zPosition = -5;	// important, otherwise delete button does not fire / is covered
	[self.layer addSublayer:bglayer];

	// set label size (adjust to heightForRowAtIndexPath..)
	label.frame = CGRectMake(rad, 5, fr.size.width, fr.size.height);

	// corner layer top left
	topleft = [CALayer layer];
    topleft.backgroundColor = normalColor.CGColor;
	CGRect tl = CGRectMake(rad, 0, rad, rad);
	topleft.frame = tl;
	topleft.zPosition = -4;
	if(roundTop){
		topleft.hidden = YES;
	}else {
		topleft.hidden = NO;
	}
    [self.layer addSublayer:topleft];

	// corner layer top right
	topright = [CALayer layer];
    topright.backgroundColor = normalColor.CGColor;
	topright.frame = CGRectMake(fr.size.width, 0, rad, rad);
	topright.zPosition = -3;
	if(roundTop){
		topright.hidden = YES;
	}
	else {
		topright.hidden = NO;
	}
    [self.layer addSublayer:topright];

	// corner layer bottom left
	bottomleft = [CALayer layer];
    bottomleft.backgroundColor = normalColor.CGColor;
	bottomleft.frame = CGRectMake(rad, fr.size.height-rad, rad, rad);
	bottomleft.zPosition = -2;
	if(roundBottom){
		bottomleft.hidden = YES;
	}else {
		bottomleft.hidden = NO;
	}
    [self.layer addSublayer:bottomleft];

	// corner layer bottom right
	bottomright = [CALayer layer];
	bottomright.backgroundColor = normalColor.CGColor;
	bottomright.frame = CGRectMake(fr.size.width, fr.size.height-rad, rad, rad);
	bottomright.zPosition = -1;
	if(roundBottom){
		bottomright.hidden = YES;
	}else {
		bottomright.hidden = NO;
	}
    [self.layer addSublayer:bottomright];

	[super drawRect:rect];

}

Now we implement both methods to show round corners on top or bottom of the cell by hiding the appropriate CALayers:

-(void) drawRoundTop{
roundTop = YES;
topleft.hidden = YES;
topright.hidden = YES;
}

For the cell bottom:

-(void) drawRoundBottom{
roundBottom = YES;
bottomleft.hidden = YES;
bottomright.hidden = YES;
}

Ok, our custom UITableViewCell class is ready for use. Therefore we open our UITableViewController file (.m). In the viewDidLoad method we have to implement at least the first line of the following code (if not, the standard table background view will hide our new cells).

// important! without this line it does not work!
[self.tableView setBackgroundView:[[[UIView alloc] init] autorelease]];
// set plain background color
 [self.tableView setBackgroundColor:[UIColor colorWithRed:0.69 green:0.81 blue:0.79 alpha:1.0]];
// remove seperator color
 self.tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
 [self.tableView setSeparatorColor:[UIColor clearColor]];

In my case I have defined two sections, one with normal cells and one with rounded cells, like a separate block. The cell type is defined in the cellForRowAtIndexPath method like this:

if (indexPath.section == SECTION_NORMAL) {

 static NSString *CellIdentifier = @"Cell";

 NormalTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
 if (cell == nil) {
 cell = [[[NormalTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
 }
 cell.label.text = @"normal cell";
 return cell;

 } else if (indexPath.section == SECTION_ROUNDED) {
// define round cell
 static NSString *CellRoundedIdentifier = @"RoundedTableViewCell";
 RoundedTableViewCell *cell = (RoundedTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellRoundedIdentifier];
 if (cell == nil) {
 cell = [[[RoundedTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellRoundedIdentifier] autorelease];
 }

 // Configure the cell.
 [cell.label setText:[NSString stringWithFormat:@"my round cell No.%d",(indexPath.row+1)]];
 cell.selectionStyle = UITableViewCellSelectionStyleNone;
 // draw round top corners in first row
 if(indexPath.row == 0){
 [cell drawRoundTop];
 }
// draw round corners in last row
if (indexPath.row == [self.tableView  numberOfRowsInSection:indexPath.section]-1) {
 [cell drawRoundBottom];
 }

 return cell;
 }

In order to set a margin between both sections, use the heightForHeaderInSection and the viewForHeaderInSection methods:

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {

 UIView* header = nil;
 if(section == SECTION_ROUNDED){
 CGRect rect = CGRectMake(0, 0, self.tableView.frame.size.width, [self tableView:(tableView) heightForHeaderInSection:section]);
 header = [[UIView alloc] initWithFrame:rect];

 }
 return header;
}

- (CGFloat) tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
 CGFloat h = 0;
 if(section == SECTION_ROUNDED){
 h = 15;
 }
 return h;
}

You can download the zipped XCode example project from github.