开发者

Best way to create a view for notes

开发者 https://www.devze.com 2023-04-05 06:03 出处:网络
I\'m writing an iPhone/iPad application that will allow a user to fill in blanks for notes.The notes will be different each week.I see downloading the notes in an XML format from our webserver.What I\

I'm writing an iPhone/iPad application that will allow a user to fill in blanks for notes. The notes will be different each week. I see downloading the notes in an XML format from our webserver. What I'm struggling with is how to dynamically build a View that can align the text and input fields similar to the sample below.

sample image http://www.ccvonline.com/downloads/ios/example.png

I need to have the input controls inline with the text. Can this be done with Core Text? Any sample code? Right now I'm thinking about using an UIWebView and build it in HTML/CSS开发者_开发问答. But this feels a bit like cheating. Anyone have another idea?


Start with NSString's sizeWithFont: method for your current line. When the notes are downloaded, make sure each note is in two parts, the part before and the part after the text field.

CGSize textSize = [displayStringPart1 sizeWithFont:[UIFont systemFontOfSize:14.0]];

Create a label of that size and add it to the view hierarchy.

UILabel *textLabel = [[UILabel alloc] initWithFrame:CGRectMake(22.0, 22.0, textSize.width, textSize.height)];
textLabel.text = displayStringPart1;
// Configure label (shadow, etc.)
[self.view addSubview:textLabel];
[textLabel release];

With some simple arithmetic, you now know the location of the right end of the first label. You can then add in a text field. You may have to fiddle with the frame to make it line up properly—if you want a good UI, don't overlook this step!

// Put text field 5 pixels to the right of the end of the label
// How are you getting the width of the text field? I'm making it 50 here
// Default height for standard text field is 31 pixels
UITextField *answerField = [[UITextField alloc] initWithFrame:CGRectMake((22.0 + textSize.width + 5.0), 18.0, 50.0, 31.0)];
// Configure text field
[self.view addSubview:answerField];
[answerField release];

Then with a bit more math you can create a second label to display the second part. The code will be similar to the first block of code, except that to calculate the x-location you'll need to do 22.0 + textSize.width + 5.0 + 50.0 + 5.0 to account for all the existing elements.

Supporting line wrapping would be difficult. You may have to manually cut the string at a line break to make it fit. The above code only deals with one line, as the sizeWithFont: method can only return a single rectangle. If you have more than one line, it'll never return something less than the entire width of the text, making it somewhat less useful.


This is probably the easiest method to visualize. An alternative method which would make it more efficient especially while scrolling (by cutting out one of three labels) is to add a bunch of blank space in the string and have one label go across the whole screen. You'd probably want a method that calculates the number of blank spaces to make up a certain width for the text field, and then adjust your x-coordinates as necessary. I leave that up to you, if you'd like to try that.


If you have the beginning and ending texts you can try using the -sizeWithFont:constrainedToSize: or -sizeWithFont:constrainedToSize:lineBreakMode: of NSString. Also, you could add a parameter in your XML file that gives the required width of each element.


Sample code would be difficult considering no reqs beyond that screenshot, which doesn't appear to be arranged very well to begin with.

The easiest way may just be to get the text, break it into words and then arrange them in the space you have available. Be that a constraining view, or whatever. You'll also want to have note data to determine where the blank space will be. This could just be an index (i.e. if its word 4, 4).

Just subclass a view and use core graphics.

Rudimentary version:

- (void) awakeFromNib
{
    self.words = [NSArray arrayWithObjects:@"It ", @"has ", @"to ", @"be ", @"_", @"before ", @"it ", @"can ", @"multiply.", nil];
    blank = 4;

}

- (void) drawRect:(CGRect)theRect
{
    CGRect rect = self.textView.frame; // reference view

    CGContextRef context = UIGraphicsGetCurrentContext();
    if(context == nil)
        return;

    CGContextSelectFont(context, "Helvetica", 20, kCGEncodingMacRoman);
    CGContextSetTextMatrix(context, CGAffineTransformMakeScale(1.0, -1.0));
    CGContextSetRGBFillColor(context, 1, 1, 1, 1);
    CGContextSetRGBStrokeColor(context, 1, 1, 1, 1);

    float x = rect.origin.x;
    float y = rect.origin.y + 20;  // since text is flipped adjust our y (based on font size)
    float width = rect.size.width;
    CGContextSetTextPosition(context, x, y);

    int index = 0;
    for(NSString * word in self.words)
    {
        CGPoint startPos = CGContextGetTextPosition(context);
        if(index == blank)
        {
            CGRect box = self.textField.frame;
            box.origin = startPos;
            box.origin.y -= 22; // since text is flipped adjust our y (based on font size)
            self.textField.frame = box;
            CGContextSetTextPosition(context, x + box.size.width + 35, y); // + arbitrary space
            index++;
            continue;
        }

        CGContextSetTextDrawingMode(context, kCGTextInvisible);
        CGContextShowText(context, [word UTF8String], [word length]);
        CGPoint endPos = CGContextGetTextPosition(context);

        x = startPos.x;
        if(endPos.x > width)
        {
            // next line
            x = rect.origin.x;
            y += 22;
        }

        CGContextSetTextDrawingMode(context, kCGTextFillStroke);
        CGContextShowTextAtPoint(context, x, y, [word UTF8String], [word length]);

        index++;
    }

    CGContextRelease(context);
}

This produces this:

Best way to create a view for notes

The project is a simple view, I set up a UIView as the reference frame upon which the text is bound, and a UITextField that I move into place. You can duplicate for more than one such sentence on screen. The blank is just a filler to simplify the loop processing, the index is what determines where the box is shown.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号