ANA
ANA

Reputation: 280

iOS: The proper way to display Images and long texts with scroll functionality

I'm developing an app for a news website, i'm displaying the news articles using UITableView where each cell is an article title, when a user clicks on a cell (i.e an article), another view opens (using segue), now in this view i want to put the following:

  1. The article's Image at the top.
  2. The article's date under the image.
  3. The article's description under the date. (Which could be very long)
  4. The ability for the user to scroll the entire view. (not only the description)

NOTE: I have tried so many ways, i can't seem to know the proper way to implement this structure.

Upvotes: 2

Views: 484

Answers (3)

Catalina T.
Catalina T.

Reputation: 3494

I have created a pod to programmatically add constraints. There is a special category for scrollViews, because they are so complicated to use with auto layout.

Here is the link to the project

There is an example app you can take a look at, but the things you would have to do would be

  • initialize your views (the image, date label and description label).
  • add the scrollView
  • add the subviews of the scrollView
UIScrollView *scrollView = [[UIScrollView alloc] init];
[self.view addSubview:scrollView];
[scrollView addConstraintsToFillHorizontal];
[scrollView addConstraintsToFillVertical];

[scrollView addConstraintsToAlignVerticalAllViews:@[image, dateLabel, descriptionLabel]];

This should be pretty simple to implement, but if you need more help, just let me know and I could provide you with some more sample code.

Good luck with your project!

Upvotes: 1

Rufel
Rufel

Reputation: 2660

Another way would be to display each article as a HTML string in a UIWebView.

NSURL *url = [NSURL URLWithString:self.articleController.url];
NSString *html = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:NULL];
[self.articleView.webView loadHTMLString:html baseURL:baseURL];

Upvotes: 0

Tommy
Tommy

Reputation: 100622

The modern solution is actually relatively simple: compose the whole thing as an attributed string and put it into a UITextView. The text view will automatically deal with the fact that the description may be very long, that all content should scroll together, etc.

E.g.

NSAttributedString *imageString = [NSAttributedString attributedStringWithAttachment:
                [[NSTextAttachment new] setImage:[UIImage imageNamed:@"whatever.png"]]];

... and use the natural means for composition of attributed strings and for setting things like font and colour on your other bits of text. Then just textView.attributedString = compoundString;.


Elaborated example:

- (void)setStory:(Story *)story
{
    NSAttributedString *image = [story imageString];
    NSAttributedString *date = [story dateString];
    NSAttributedString *body = [story bodyString];

    NSMutableAttributedString *wholeStory = [NSMutableAttributedString new];

    // TODO: can you be sure image, date and body are all non-nil?
    NSArray *allComponents = @[image, date, body];
    for(NSAttributedString *component in allComponents)
    {
        [wholeStory appendAttributedString:component];
        if(component != [allComponents lastObject])
            [[wholeStory mutableString] appendString:@"\n\n"];
    }

    self.textView.attributedString = wholeStory;
}

... elsewhere, in the Story object ...

- (UIImage *)image
{
    // ...something...
}

- (NSString *)dateText
{
    // ...something, probably using NSDateFormatter unless it's returned
    // from a server or wherever already formatted...
}

- (NSString *)bodyText
{
    // ... something ...
}

- (NSAttributedString *)imageString
{
    return [NSAttributedString attributedStringWithAttachment:
            [[NSTextAttachment new] setImage:[self image]]];
}

- (NSAttributedString *)dateString
{
    return [[NSAttributedString alloc]
             initWithString:[self dateText]
             attributes:
             @{
                 NSFontAttributeName: [UIFont preferredFontForTextStyle: UIFontTextStyleSubheadline],
                 ... etc ...
             }];
}

- (NSAttributedString *)bodyString
{
    return [[NSAttributedString alloc]
             initWithString:[self bodyText]
             attributes:
             @{
                 NSFontAttributeName: [UIFont preferredFontForTextStyle: UIFontTextStyleBody],
                 ... etc ...
             }];
}

Check out the NSAttributedString UIKit Additions documentation for lists of the various attributes you can set other than NSFontAttributeName. Note that I've gone with the iOS 7+ way of asking for fonts by purpose rather than a specific size or font. That means that users who have turned up their default font size will get larger text in your app.

Upvotes: 6

Related Questions