3.4. Text Views

The UITextView class is indirectly based on the UIView class, with its functionality extended to present and allow the editing of text, provide scrolling, and render various styling options, such as font and color. Text views are practical for text-based portions of an application, such as an electronic book, the notes section of a program, or an informational page to present unstructured information for editing. Structured information is best displayed in other UI Kit objects, which you'll learn about in this chapter and in Chapter 10. You've already used the UITextView class in some of the previous examples. In this section, you'll learn how to customize its behavior.

A UITextView object inherits from a class named UIScrollView, which is a general-purpose scrollable view class. The text view class inherits all of the scrolling functionality of UIScrollView, so the developer can focus on presenting content rather than programming scroll bars. The UIScrollView class inherits from the base UIView class, which, as discussed in the previous section, is the base for all view classes. The following is an illustration of the class hierarchy:

  • UITextView adds functionality and inherits the functionality of...

    • UIScrollView adds functionality and inherits the functionality of...

      • UIView is the base class for all view classes, inherits the functionality of...

        • UIResponder is the foundation class for all objects that respond.

3.4.1. Creating a Text View

Because UITextView is ultimately derived from UIView, it is created in the same fashion as other view objects were created in the previous section—using an initWithFrame method. If your text view were attached to a view controller's loadView method, you'd use the UIScreen class's applicationFrame method to determine the view's display region:

- (void) loadView {
    [ super loadView ];
    CGRect bounds = [ [ UIScreen mainScreen ] applicationFrame ];
    textView = [ [ UITextView alloc ] initWithFrame: bounds ];
    self.view = textView;
}

Alternatively, you can define a custom size for the text view if you are attaching it to an existing view object, such as the controller's default view. The following example creates a 320x200 text view with a vertical offset of 100 pixels down, and then attaches it to the view controller's default view:

- (void) loadView {
    [ super loadView ];
    CGRect viewRect = CGRectMake(0.0, 100.0, 320.0, 200.0);
    UITextView *textView = [ [ UITextView alloc ]
        initWithFrame: viewRect ];
    [ self.view addSubview: textView ];
}

Once you have created the text view, you can set a number of different properties.

3.4.1.1. Editing

By default, a text view is editable by the user. If the user taps within the text view, the iPhone will automatically pop up a keyboard and resize the text view to accommodate typing. For read-only text views, set the editable property to NO:

textView.editable = NO;

3.4.1.2. Alignment

By default, text is left-aligned in the window. You can change this using the text view's textAlignment property:

textView.textAlignment = UITextAlignmentLeft;

Use the following values to change text alignment:



UITextAlignmentLeft

Text will be left-aligned (default)



UITextAlignmentRight

Text will be right-aligned



UITextAlignmentCenter

Text will be centered

3.4.1.3. Font and size

The text font (typeface) and point size can be set by assigning a UIFont object to the text view's font property. To create a UIFont object, use a static method named fontWithName:

UIFont *myFont = [ UIFont fontWithName: @"Arial" size: 18.0 ];
textView.font = myFont;

Additionally, three other static methods exist for easily creating system fonts:

UIFont *mySystemFont = [ UIFont systemFontOfSize: 12.0 ];
UIFont *myBoldSystemFont = [ UIFont boldSystemFontOfSize: 12.0 ];
UIFont *myItalicSystemFont = [ UIFont italicSystemFontOfSize: 12.0 ];

The following fonts come preinstalled on the iPhone and can be referenced by name:

American Typewriter
Apple Gothic
Arial
Arial Rounded MT Bold
Courier
Courier New
Georgia
Helvetica
Helvetica Neue
Marker Felt
Times
Times New Roman
Trebuchet MS
Verdana
Zapfino

Font selection determines the display font for all text within the text view. A text view does not support rich text.

3.4.1.4. Text color

You can define text color using a UIColor object. The UIColor class provides many different methods for easily mixing any color. You can use static methods to create colors, which are released when no longer needed. Colors can be created as white levels, using hue, or as an RGB composite. To create a simple RGB color, specify a set of four floating-point values for red, green, blue, and alpha (opacity) with values between 0.0 and 1.0. These represent values ranging from 0% (0.0) to 100% (1.0):

UIColor *myWhiteTransparentColor = [ UIColor colorWithWhite: 1.0 alpha: 0.50 ];

UIColor *myColorHue = [ UIColor colorWithHue: 120.0 / 360.0
    saturation: 0.75
    brightness: 0.50
    alpha: 1.0
];

UIColor *myColorRGB = [ UIColor colorWithRed: 0.75
    green: 1.0
    blue: 0.75
    alpha: 1.0
];

                                          

If you plan on reusing many different UIColor objects, you may also create instances of them:

UIColor *myWhiteTransparentColor = [ [ UIColor alloc ]
    initWithWhite: 1.0 alpha: 0.50
];

UIColor *myColorHue = [ [ UIColor alloc ]
    initWithHue: 120.0 / 360.0
    saturation: 0.75
    brightness: 0.50
    alpha: 1.0
];

UIColor *myColorRGB = [ [ UIColor alloc ] initWithRed: 0.75
    green: 1.0
    blue: 0.75
    alpha: 1.0
];

The UIColor class also supports many static methods to create system colors, which are calibrated by the iPhone as closely as possible. These methods include the following, from UIColor.h:

+ (UIColor *)blackColor;      // 0.0 white
+ (UIColor *)darkGrayColor;   // 0.333 white
+ (UIColor *)lightGrayColor;  // 0.667 white
+ (UIColor *)whiteColor;      // 1.0 white
+ (UIColor *)grayColor;       // 0.5 white
+ (UIColor *)redColor;        // 1.0, 0.0, 0.0 RGB
+ (UIColor *)greenColor;      // 0.0, 1.0, 0.0 RGB
+ (UIColor *)blueColor;       // 0.0, 0.0, 1.0 RGB
+ (UIColor *)cyanColor;       // 0.0, 1.0, 1.0 RGB
+ (UIColor *)yellowColor;     // 1.0, 1.0, 0.0 RGB
+ (UIColor *)magentaColor;    // 1.0, 0.0, 1.0 RGB
+ (UIColor *)orangeColor;     // 1.0, 0.5, 0.0 RGB
+ (UIColor *)purpleColor;     // 0.5, 0.0, 0.5 RGB
+ (UIColor *)brownColor;      // 0.6, 0.4, 0.2 RGB
+ (UIColor *)clearColor;      // 0.0 white, 0.0 alpha

Once you have created a UIColor object, assign it to the text view's color property:

textView.textColor = myColorHue;

Because a text view doesn't directly support rich text, the color selection affects all of the text within the view.

3.4.1.5. Colors from Core Graphics

The Core Graphics framework is used widely on the Mac OS X desktop for two-dimensional rendering and transformations. We'll cover some of its pieces in this book, but Core Graphics programming is a topic for an entirely dedicated book in itself. If you're already using the Core Graphics framework for graphics programming, you can apply much of your knowledge to the iPhone.

The Core Graphics equivalent of a UIColor object is CGColor. You can convert a CGColorRef (Core Graphics color reference) to a UIColor object using the colorWithCGColor method:

CGColorSpaceRef colorSpace =
    CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
float opaqueRed[4] = { 1.0, 0.0, 0.0, 1.0 };
CGColorRef red = CGColorCreate(colorSpace, opaqueRed);
UIColor *myRed = [ UIColor colorWithCGColor: red ];
textView.textColor = myRed;

3.4.2. Assigning Content

The text of the view can be set with a property named text. This property accepts an NSString argument. An easy way to set static text follows:

textView.text = @"Hello, world!";

You can also use the NSString class's many string creation methods to create custom string objects:

int nBottles = 100;
NSString *myFormattedString = [ [ NSString alloc ]
    initWithFormat: @"%d bottles of beer on the wall", nBottles
];

textView.text = myFormattedString;

You can also create NSString objects from C-style character arrays:

char myBottles[] = "100 bottles of beer on the wall";
NSString *myCString = [ NSString stringWithCString: myBottles ];
textView.text = myCString;

To access a file in your home directory, use the NSHomeDirectory function to obtain the unique path to your application's sandbox. This is the path to the directory hierarchy you learned about in Chapter 1:

NSString *myFile = [ NSHomeDirectory()
    stringByAppendingPathComponent: @"Documents/file.txt"
];

NSString *myFileString = [ NSString stringWithContentsOfFile: myFile ];
textView.text = myFileString;

The same also exist as instance methods using the initWith prefix instead of stringWith:

NSString *myFile = [ [ NSString alloc ] initWithFormat: @"%@/Documents/file.txt",
    NSHomeDirectory()
];

NSString *myFileString = [ [ NSString alloc ] initWithContentsOfFile: myFile ];
textView.text = myFileString;

                                          

3.4.3. Displaying HTML

An undocumented API exists to display HTML content inside a text view. Because it's undocumented, Apple likely wants you to use the UIWebView class instead, which you'll learn about in Chapter 10. For fun, we'll show you the private method call to do this below, which can be useful for debugging:

[ textView setContentToHTMLString:
    @"<HTML><BODY><B>Hello, World!</B></BODY></HTML>" ];

This undocumented API is subject to change at any time. Your application could also potentially be rejected from listing in the iTunes store if you use undocumented APIs.


3.4.4. SourceReader: Web Page Source Code Reader

If you've ever tried to learn HTML, chances are you've used your browser's View Source feature at least a few times. This example uses the foundation library's NSURL and NSString objects to load the front page from http://www.oreilly.com and display it in a text window using a UITextView. You'll also see UIColor and UIFont objects in action, and other text view properties used. This example will build on top of the previous view controller example, adding functionality to the controller's loadView method. Because the functionality of performing HTTP requests has been incorporated into the NSString class, you won't see any code for loading web page content. The web page content will be automatically loaded after invoking the NSString class's stringWithCon⁠tentsOfURL method. See Figure 3-1.

Figure 3-1. SourceReader example


You can compile this application, shown in Examples Example 3-12 through Example 3-16, with the SDK by creating a view-based application project named SourceReader. Be sure to pull out the Interface Builder code if you'd like to see how these objects are created from scratch.

Example 3-12. SourceReader application delegate prototypes (SourceReaderAppDelegate.h)
#import <UIKit/UIKit.h>

@class SourceReaderViewController;

@interface SourceReaderAppDelegate : NSObject <UIApplicationDelegate> {
    UIWindow *window;
    SourceReaderViewController *viewController;
}

@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet SourceReaderViewController *viewController;

@end

                                          

Example 3-13. SourceReader application delegate (SourceReaderAppDelegate.m)
#import "SourceReaderAppDelegate.h"
#impo rt "SourceReaderViewController.h"

@implementation SourceReaderAppDelegate

@synthesize window;
@synthesize viewController;

- (void)applicationDidFinishLaunching:(UIApplication *)application {
    CGRect screenBounds = [ [ UIScreen mainScreen ] bounds ];

    self.window = [ [ [ UIWindow alloc ] initWithFrame: screenBounds ]
        autorelease
    ];

    viewController = [ [ SourceReaderViewController alloc ] init ];

    [ window addSubview: viewController.view ];
    [ window makeKeyAndVisible ];
}


- (void)dealloc {
    [viewController release];
    [window release];
    [super dealloc];
}

@end

Example 3-14. SourceReader view controller prototype (SourceReaderViewController.h)
#import <UIKit/UIKit.h>

@interface SourceReaderViewController : UIViewController {
    UITextView *textView;
}

@end

Example 3-15. SourceReader view controller (SourceReaderViewController.m)
#import <UIKit/UIColor.h>
#import <UIKit/UIFont.h>
#import "SourceReaderViewController.h"

@implementation SourceReaderViewController

- (id)init {
    self = [ super init ];
    if (self != nil) {
        /* Additional initialization code */
    }
    return self;
}

- (void)loadView {
    CGRect bounds = [ [ UIScreen mainScreen ] applicationFrame ];

    [ super loadView ];

    textView = [ [ UITextView alloc ] initWithFrame: bounds ];

    UIColor *myBlue = [ UIColor colorWithRed: 0.0
        green: 0.0 blue: 1.0 alpha: 1.0 ];
    textView.textColor = myBlue;

    UIFont *myFixed = [ UIFont fontWithName: @"Courier New" size: 10.0 ];
    textView.font = myFixed;

    textView.editable = NO;

    NSURL *url = [ NSURL URLWithString: @"http://www.oreilly.com" ];
    NSString *pageData = [ NSString stringWithContentsOfURL: url ];
    textView.text = pageData;

    self.view = textView;
}

-(BOOL)shouldAutorotateToInterfaceOrientation:
(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation == UIDeviceOrientationPortrait);
}

- (void)viewDidLoad {
    [ super viewDidLoad ];
}


- (void)dealloc {
    [ textView dealloc ];
    [ super dealloc ];
}

@end

                                          

Example 3-16. SourceReader main (main.m)
#import <UIKit/UIKit.h>

int main(int argc, char *argv[]) {

    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    int retVal = UIApplicationMain(argc, argv, nil, @"SourceReaderAppDelegate");
    [pool release];
    return retVal;
}

                                          

3.4.5. What's Going On

The SourceReader example contains the core of everything you've seen so far and adds a functional text view containing the contents of the O'Reilly website:

  1. The application begins within its main function, which invokes the SourceReaderAppDelegate class's applicationDidFinishLaunching method.

  2. A window is created using the entire bounds of the screen. A view controller is then created and its init method is invoked. The runtime then calls the controller's loadView method, which creates the UITextView object and assigns it the application's viewable region using UIScreen's applicationFrame method.

  3. After the text view is created, an NSURL object is created using the URL http://www.oreilly.com. This is used to create an NSString object containing the contents of the web page, which the NSString class loads automatically. The contents of the page are then assigned to the text view and the view controller's active view is replaced by means of setting self.view.

  4. The view controller's active view is added as a subview of the window and the window is instructed to display. This in turn displays the text view.

3.4.6. Further Study

Play around with the text view for a little while before proceeding:

  • Using the undocumented API, modify this project so that the actual HTML is displayed rather than the source text. What kind of compiler warnings do you receive and why?

  • Check out the following prototypes in your SDK's header files: UITextView.h, UIColor.h, and UIFont.h. You'll find these under /Developer/Platforms/iPho⁠neOS.platform, inside the UI Kit framework's Headers directory.