MonoTouch UIScrollView not scrolling with dyanmic

2019-09-09 04:48发布

I have a UILabel (named contentLbl) that will change dynamically within a UIScrollView. Above it is another UILabel (named contentTitleLbl) that is a title and does not contain dynamic content. To successfully scroll I know that I must at least set the ContentSize of the UIScrollView to that of the content view's. I've also seen that the Frame should be set. I have tried both but it still does not scroll.

In my example code contentView contains both the contentLbl and contentTitleLbl. scrollView is the reference to the UIScrollView that I'm currently trying to use.

Here is my current code:

public override void ViewDidLoad ()
{
    base.ViewDidLoad ();
    //contentLbl is to have dynamic text, and currently stores a large lorem ipsum paragraph
    //contentTitleLbl is the title and is not dynamic
    this.contentLbl.SizeToFit();
    this.scrollView.ContentSize = new SizeF(this.contentView.Frame.Width, this.contentLbl.Frame.Size.Height + this.contentTitleLbl.Frame.Size.Height);
    this.scrollView.Frame = new RectangleF(this.scrollView.Frame.X, this.scrollView.Frame.Y, this.scrollView.ContentSize.Width, this.scrollView.ContentSize.Height);
    this.scrollView.AddSubview(this.contentView);
}

Any help would be greatly appreciated!

2条回答
够拽才男人
2楼-- · 2019-09-09 05:01

Just add this method extension. Call it when you done with adding subview. This method will calculate new content Height and assign to the scroll view.

public static void RecalculateContentSize (this UIScrollView scrollView)
        {
            float sizeOfContent = 0;
            float height = 0;
            for (int i = 0; i < scrollView.Subviews.Length; i++) {
                UIView view = scrollView.Subviews [i];
                height = view.Frame.Location.Y + view.Frame.Size.Height;
                if (height > sizeOfContent)
                    sizeOfContent = height;
            }

            // Set content size for scroll view
            scrollView.ContentSize = new System.Drawing.SizeF (scrollView.Frame.Size.Width, sizeOfContent);
        }
查看更多
Juvenile、少年°
3楼-- · 2019-09-09 05:24

Quick question: Are you intending for the title to scroll with your text? In this solution, I've done that, as this is my interpretation. I'll adjust it, if you'd like, for the title not to scroll. I recreated your sample by making this hierarchy in XCode

  • UIView (main view of the view controller)
    • UIView (contentView)
      • UILabel (contentTitleLbl)
        • Frame = (20,15,160,21)
      • UILabel (contentLbl)
        • Lines = 100
        • Frame = (20,43,160,190)
        • Text = "Lorem ipsum..." (long paragraph)
    • UIScrollView (scrollView)
      • Frame = (20,20,140,140)

I set the background colors of all the items to different values so that I could see the dimensions of all the components.

First, I needed to make sure all the auto-resizing of the labels was turned off. You can do this in XCode, or programmatically:

contentLbl.AutoresizingMask = UIViewAutoresizing.None;
contentTitleLbl.AutoresizingMask = UIViewAutoresizing.None;

I'd prefer to place the contentView inside the scrollView via XCode, but it looks like you had them as siblings under the main View. So we reparent the contentView to place it inside the scrollView

scrollView.AddSubview( contentView );

Then make the title the same width as the scrollView, positioning it at the origin and leaving the height as designed in XCode

var f = contentTitleLbl.Frame;
f.X = 0;
f.Y = 0;
f.Width = scrollView.Frame.Width;
contentTitleLbl.Frame = f;

Then the first major issue: resizing a UILabel to fit your contents dynamically. SizeToFit resizes the label to a single line of text (or at least, did for me). What you really want is NSString.sizeWithFont which appears in MonoTouch as UIView.StringSize. Be careful, as some of these return the size for a single line of text. Here I've constrained the width to the width of the scroll view, but left the height unbounded by using float.MaxValue.

SizeF sz = this.View.StringSize(
    contentLbl.Text,
    contentLbl.Font,
    new SizeF( scrollView.Frame.Width, float.MaxValue),
    UILineBreakMode.WordWrap );

Then resize and position the label just underneath the title:

f = contentLbl.Frame;
f.X = 0;
f.Y = contentTitleLbl.Frame.Bottom; // nudge the contentLbl right up against the title
f.Width = sz.Width;    // size matches the measured values from above
f.Height = sz.Height;
contentLbl.Frame = f;

Then adjust the size of the contentView to hold the title and the content. This view will be placed at the origin in the scroll view. The size is determined dynamically by the code above. I've added a small margin at the bottom so I can tell that the whole content has been rendered

f = contentView.Frame;
f.X = 0;
f.Y = 0;
f.Width = scrollView.Frame.Width;
f.Height = contentLbl.Frame.Bottom + 20;
contentView.Frame = f;

Then set the ContentSize of the scroll view to the size of the contentView. If the size is larger than the scroll view's size -- which should be the case with the Lorem Ipsum text -- you'll get your scrolling.

scrollView.ContentSize = contentView.Frame.Size;

Cheers.

[Edit: fixed typo for 'width' vs. 'height']

[Edit: simplest scroll view]

Here's the simplest scroll view I could come up with. Dragging up and down on the red area should show the scroll bar. When you get to the bottom, the green background of the scroll view should show.

var v =  new UIView( new RectangleF(0,0,200,1000));
v.BackgroundColor = UIColor.Red;

var sv = new UIScrollView( new RectangleF(20,20,200,300));
sv.BackgroundColor = UIColor.Green;
sv.ContentSize = v.Frame.Size;

View.AddSubview(sv);
sv.AddSubview(v);

[Edit: an even simpler scroll view] I created a scroll view in XCode and simply set the background color and the content size to be larger than the scroll view's size. When dragging on the blue scroll view, the scroll bars should appear.

designerScrollView.BackgroundColor = UIColor.Blue;
designerScrollView.ContentSize = new SizeF(1000,1000);
查看更多
登录 后发表回答