May 14, 2009

UIWebView and Native Footers

Posted in iPhone development tagged , , , , , , , , , , , at 7:18 pm by tetontech

At the request of a couple of QuickConnectiPhone users I have been playing around with a way to combine native footers and/or headers with the UIWebView and specifically the QuickConnectiPhone framework.

I am pleased to say that I have something that should make this easy.  As of the next release of QCiPhone you can create native, Objective-C based footers and buttons for the footers.  You can also hide and display them and the UIWebView containing your QCiPhone application will be resized so that the footer doesn’t cover any of your display.  When you hide the footer the UIWebView expands to fill the space made available by not displaying the footer.

Here is a snapshot of the QCiPhone example app without the footer displayed.

The native footer example application before the Show Footer button is pressed.

The native footer example application before the Show Footer button is pressed.

Here is the native footer being displayed.

The example application after the Show Footer button is pressed.

The example application after the Show Footer button is pressed.

The button is an HTML button in the UIWebView and JavaScript calls are made to show and hide the native footer.

Here is the code from the JavaScript onload event handler that creates the native footer and buttons and then assigns the buttons to the footer for display.  Notice that the last button created uses an image instead of text for it’s cue to the user.

footer = new QCNativeFooter(‘mainFooter’, ‘black’, false);

//examples of using full JavaScript function calls with staticly defined parameters

var lineButton = new QCNativeButton(‘line’, ‘Line’, ‘displayName(“Line”)’, false);

var pieButton = new QCNativeButton(‘pie’, ‘Pie’, ‘displayName(“Pie”)’, false);

var barButton = new QCNativeButton(‘bar’, ‘Bar’, ‘displayName()’, false);

var imageButton = new QCNativeButton(‘image’, ‘puzzleIcon.png’, ‘displayName(“Image Button”)’,true);

footer.setButtons([lineButton, barButton, pieButton, imageButton]);

The QCNativeFooter constructor is defined as in this following line of code.

function QCNativeFooter(uniqueId, color, translucentFlag)

It takes three parameters

  1. A unique identifier for the footer.  You can have as many footers as you wish.
  2. The color of the desired footer as a string.  The iPhone options are ‘black’ and ‘standard’.  Standard is blue.
  3. A boolean flag indicating if the footer should be semi-transparent.

The code to display the footer is seen here.

footer.show();

It is all that is needed to display the footer and automatically resize the display of your application.  To hide the footer simply call

footer.hide();

To change buttons being displayed all you need to do is call the QCNativeFooter object’s setButtons method and pass in an array of buttons that you want to replace the old ones.  The first code snippet in this posting has an example of this call.

These methods and objects are just facades for calls to Objective-C using the QCiPhone framework.  A complete description of all of the Objective-C executed for these calls would be to large for a blog posting.

This example application, as well as a couple of others, will be added to the next version of QCiPhone.  The framework’s template will also be modified to contain all of the Objective-C and JavaScript to allow you to make the calls described in this posting.

Advertisements

14 Comments »

  1. Sam said,

    TetonTech-
    Great addition! Thanks a lot.

    Any news of the rendering of the index.html before the default png goes away?
    Or the disabling of text selection (for copy, paste, etc.), especially in games that use this framework?

    Thanks again.

    • tetontech said,

      Sam,

      In all of the exploration that I have done I have not been able to find a way to turn off copy-paste for Apple’s UIElements. I am continuing to look. The splash screen is under the control of the Operating system and so I can’t make it stay around longer. The only potential work around for the display delay that I have been able to find is to break your application up into multiple html files and load them one at a time. This should reduce the load and render time.

      I can’t put another view over the top of the UIWebView and wait for the UIWebView to load and render since the UIWebView does not render until it is viewable. I will continue to see if I can ‘fool’ the UIWebView into thinking it is the viewable element.

      Lee

      • Sam said,

        Thanks for the response. If I find anything successful I’ll be sure to post it

      • tetontech said,

        Sam,

        I have had a crazy idea that might work for this. The idea is, 1 – make the UIWebView have a transparent background. 2. Add another view UNDER it that uses the same image as the splash screen so that it shows through the loading UIWebView. 3. When load completes change the background of the UIWebView to opaque.

        I haven’t tried this yet, but it just might work.

        Lee

      • tetontech said,

        It works. I’ll put it in the next release. Hopefully tomorrow.

        Lee

  2. Matt Braun said,

    A note on disabling the copy/paste interaction – this is done using CSS. Add the following line to your CSS, probably on the “body” declaration:

    -webkit-user-select: none;

    Thanks for the other info!

    • tetontech said,

      Matt,

      Thanks for the info. I assume this would turn off all selection such as would be used to do text highlighting, etc. It does not interfere with QuickConnect’s drag-and-drop functionality.

      Lee

  3. Sam said,

    Sounds like it should work, I’ll give it a try (unfortunately I know close to zero ObjC but I’ll see what I can do and post back)

    • tetontech said,

      I have it working now. I’m putting together 1.5 beta 8 tomorrow that will include this behavior by default. It will include changes to QuickConnectViewController.m

      Here are the changes.

      1. Change webViewDidFinishLoad as seen here.

      – (void)webViewDidFinishLoad:(UIWebView *)aWebView{
      MESSAGE(@”finished loading”);
      /* set the delegate for the accelerometer to be the QuickConnectViewController
      * do this after the page has loaded so that no javascript calls will be made
      * to push the values to the page before the page is loaded.
      *
      * kAccelerometerFrequency is defined in the header file.
      */
      //uncomment these lines of code if you want to use acceleration in your application

      [[UIAccelerometer sharedAccelerometer] setUpdateInterval:(1.0 / kAccelerometerFrequency)];
      [[UIAccelerometer sharedAccelerometer] setDelegate:self];
      [aWebView stringByEvaluatingJavaScriptFromString:@”okToSend()”];

      self.webView.opaque = YES;
      self.webView.backgroundColor = [UIColor whiteColor];

      }

      2. Change lines 89 and those that follow as seen here.

      DeviceWebView *aWebView = [[DeviceWebView alloc] initWithFrame:webFrame];
      self.webView = aWebView;

      NSString *imageFilePathString = [[NSBundle mainBundle] pathForResource:@”Default” ofType:@”png”];
      if(imageFilePathString != nil){
      CGRect splashFrame = [[UIScreen mainScreen] applicationFrame];
      UIImage *splashImage = [[UIImage alloc] initWithContentsOfFile: imageFilePathString];
      UIImageView *splashView = [[UIImageView alloc] initWithImage:splashImage];
      [contentView addSubview:splashView];

      self.webView.opaque = NO;
      self.webView.backgroundColor = [UIColor clearColor];
      }

      /*
      * Uncomment the following line if you want the HTML to scale to fit.
      * This also allows the pinch zoom in and out functionallity to work.
      */
      //aWebView.scalesPageToFit = YES;
      aWebView.autoresizesSubviews = YES;

  4. Sam said,

    Lee! You’re the greatest!!

  5. hkabir said,

    First of all, thanks for developing the excellent framework. I already purchased your book, and now trying to develope an application. I’m really happy to see that we can use native footer in hybrid application. However, I found a lack of explanation as to how the nativeFooter can be effectively utilized in the application. For example:

    var lineButton = new QCNativeButton(‘line’, ‘Line’, ‘displayName(”Line”)’, false);

    Here, the third argument – ‘displayName(”Line”)’ – is not necessary to display the footer. In the main javascript file I found that it’s reserve for ‘callback function’. Does it mean that I can call any javascript function there? What I’m really interested in is to link a local html file to one of the native footer button. How can do that? Is there any resources that you can suggest me in this case?

    • tetontech said,

      Hkabir,

      The third parameter of teh QCNativeButton constructor is the JavaScript function you want called when the button is clicked. This native footer functionality was added to the framework after the book was completed and so isn’t in the scope of the book.

      I’m not sure what you mean by ‘link a local html file’. Does this mean that you want to replace the entire contents of the display with other content? If so, this is usually done using DHTML concepts. There are several examples of how to do this included in the download.

      Maybe some further explanation of what you are trying to do would help me.

      Lee

      • hkabir said,

        Thanks for the quick reply. I found how the third parameter really works by using a javascripts function like “goToView3(event)” that I have already in my main.js file.

        Yes, you’re right – linking another local html file will replace the entire content. It’s better not to do it.

        I’ve some concern – I heard that there’s some ‘5 second rule’ to follow for loading javascript files on such native iphone applications. If that is true then wouldn’t that be a problem since in your framework you’ve so many javascript files along with other javascript files created in Dashcodes and later imported in the xcode?

      • tetontech said,

        By the ‘five second rule’ I assume you mean that it takes 5 seconds to load a JavaScript file. That is not true at all.

        Lee


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: