Xamarin iOS Autolayout: Resize width and vertical scroll automatically for various devices while keeping the horizontal scroll disabled

前端 未结 4 960
慢半拍i
慢半拍i 2020-12-22 00:21

I want to create a page which has a vertical but no horizontal scroll. It must adjust width of the content and vertical scroll automatically as per screen size.

Som

相关标签:
4条回答
  • 2020-12-22 00:59

    In a custom renderer for Xamarin.Forms i've written my UITableViewController like this:

    _controller = new InfoFieldItemsTableViewController();
    _controller.TableView.SeparatorStyle = UITableViewCellSeparatorStyle.None;
    _controller.TableView.SeparatorColor = UIColor.Clear;
    _controller.TableView.AllowsSelection = false;
    // http://useyourloaf.com/blog/self-sizing-table-view-cells/
    _controller.TableView.RowHeight = UITableView.AutomaticDimension;
    

    In my controller i am doing this to register all potential cell candidates:

        private void RegisterCells()
        {
            foreach (var tuple in InfoFieldCellMapping.Map)
            {
                this.TableView.RegisterNibForCellReuse(tuple.Value.Item1, tuple.Value.Item2);
            }
        }
    
        public override void ViewDidLoad()
        {
    
            RegisterCells();
    
            base.ViewDidLoad();
        }
    

    I am doing this in my controller so cells resize themselves depending on how much height they need:

        public override nfloat EstimatedHeight(UITableView tableView, NSIndexPath indexPath)
        {
            return 100;
        }
    

    Now all you need to do is create cell files from within your IDE which should be .xib files and design them in the editor using autolayout (so they can adapt to orientation changes automatically).

    Within your TableViews datasource all that's left to do is mapping between your data item and it's corresponding cell similar to:

    public override UICollectionViewCell GetCell(UICollectionView collectionView, NSIndexPath indexPath) 
    {
        var dataItem = Items[indexPath.Row];
        var key = ""; // use info from data item to figure out which key identifies your table cell to dequeue the correct kind of cell
        var cell = collectionView.DequeueReusableCell(key, indexPath) as UICollectionViewCell;
    }
    

    That's all you need really. In my scenario i am mapping fields which may contain different controls for date entries, number entries, long texts, short texts etc etc.

    I hope that helps

    0 讨论(0)
  • 2020-12-22 01:14

    As I mentioned here .

    Refer to Step 1 and Step 2 ,set constraints on Scrollview and containerView.

    I remove the margin between Scrollview and View , and I add some controls on the containerView , so it looks like as below:

    Notice

    1. Since we set the containerView's width equal to scrollview's width, the width is fixed, so we can scroll vertically not horizontally.

    2. Height of controls and spaces between them should be set clearly, because the contentSize is auto calculated by adding them. (If contentSize is greater than the height of screen ,the scrollview can be scrolled)

    I saw you set those constrains on controls , but you can't scroll down to see the controls out of screen, I think you are missing to set bottom margin on the last control(the downmost one).

    Let us do a test.

    1. We set the margin (between button and textfield ) to 1000 and don't set bottom margin between the textfield and containerView.

    Result : can't scroll down to see the textfield out of screen.

    2. Set the margin 1000 and add a bottom margin(10) between textfiled and containerView.

    Result: can scroll

    Demo Link

    0 讨论(0)
  • 2020-12-22 01:16

    The previous answer was quite right, but not right at all. Indeed I tried to solve this problem using the method described before, but to make it work, I made some adjustments.

    Your view's hierarchy has to be as follow :

    UIScrollview :

    • View1
    • View2
    • View3

    You don't need a container inside the UIScrollview, because apart the fact that it will be an extraview that you don't need, there is the problem that if you use this container-view you will get problem getting touch events in the views added.

    So, let's make a step-by-step process:

    1. Add scrollview to your viewController

    The first step is to add the scrollview to your viewController, and we can simply do this programmatically in the following way:

    UIScrollView scrollView = new UIScrollView();
    scrollView.TranslatesAutoresizingMaskIntoConstraints = false;
    View.AddSubview(scrollView);
    

    View is the main-view of the viewController you are working in (aka Self.View). Put attention to set TranslateAutoResizionMaskIntoConstrains property of the scrollview to false, otherwise autoresizing will mess your constraints.

    1. Add constraint (autolayout) to your scrollView

    You need to ensure that you layout will adjust for every different iPhone-screen, so simply use auotlayout to pin your scrollView to the viewController main-view (is the View used in the next code sample):

    scrollView.TopAnchor.ConstraintEqualTo(View.TopAnchor, 0).Active = true;
    scrollView.BottomAnchor.ConstraintEqualTo(View.BottomAnchor, 0).Active = true;
    scrollView.LeadingAnchor.ConstraintEqualTo(View.LeadingAnchor, 0).Active = true;
    scrollView.TrailingAnchor.ConstraintEqualTo(View.TrailingAnchor, 0).Active = true;
    

    In this way your scrollView is pinned to the bound of the main-view.

    1. Create the view to be added

    You need to create the view that you will add to the scrollView:

    UIView viewToBeAdded = new UIView();
    viewToBeAdded.TranslatesAutoresizingMaskIntoConstraints = false;
    viewToBeAdded.Frame = new CGRect(0, 0, UIScreen.MainScreen.Bounds.Width, 200);
    

    We have created a new UIView that setting its frame large as the screen (UIScreen.MainScreen.Bounds.Width) so it won't scroll horizontally, and with an arbitrary height (200 in the sample).

    NOTE : even in this case you have to set TranslateAutoResizingMaskProperty to false, otherwise you will get a mess.

    1. Add the view to the scrollView

    Next step is to add our new view to the scrollView as follow:

    scrollView.AddSubview(view);
    

    Nothing more.

    1. Set constraint for the view added in relation to the scrollView

    Once you have added your view you have to said which will her behavior related to the scrollView. We assume that we will add several view to the scrollView, so we have to made a distinction, to the behavior of the FIRST view, the IN-BETWEEN views, and the LAST view.

    So to be clear we assume that we are adding only 3 views, so we will have the three different cases.

    FIRST VIEW

    The important thing is that the first view has to be pinned to the top of the scrollView, we do this as follow :

    firstView.TopAnchor.ConstraintEqualTo(scrollView.TopAnchor, 0).Active = true;
    

    and then we set the others constraints:

    firstView.WidthAnchor.ConstraintEqualTo(firstView.Bounds.Width).Active = true;
    firstView.HeightAnchor.ConstraintEqualTo(firstView.Bounds.Height).Active = true;
    

    IN-BETWEEN VIEW

    The in between views (in our sample the secondView) need to be pinned to the previous view added (in our case the first view). So we do as follow:

    secondView.TopAnchor.ConstraintEqualTo(firstView.BottomAnchor).Active = true;
    

    So the top of the secondView is pinned to the bottom of the firstView. And then we add the others constraints:

    secondView.WidthAnchor.ConstraintEqualTo(secondView.Bounds.Width).Active = true;
    secondView.HeightAnchor.ConstraintEqualTo(secondView.Bounds.Height).Active = true;
    

    LAST VIEW

    The last view (in our case the third view) instead needs to be pinned to the bottom of the previousView (in our case the secondView) and to the bottom of the scrollView.

    thirdView.TopAnchor.ConstraintEqualTo(secondView.BottomAnchor).Active = true;
    thirdView.BottomAnchor.ConstraintEqualTo(scrollView.BottomAnchor).Active = true;
    

    And the usual other constraints for width and eight:

    thirdView.WidthAnchor.ConstraintEqualTo(thirdView.Bounds.Width).Active = true;
    thirdView.HeightAnchor.ConstraintEqualTo(thirdView.Bounds.Height).Active = true;
    

    In this way the eight of the scrollView will adapt to the eight of the views added, due to the fact that the views inside are pinned to the top and the bottom of the scrollView.

    CONCLUSIONS

    If you follow these simple instruction you will get everything work. Remember to disable autoResizingMask, as this is on of the common mistake.

    Hope it was helpful. Cheers

    0 讨论(0)
  • 2020-12-22 01:18

    1.Add Leading,Trailing,Top,Bottom Constraints on scrollView to it'superview.

    2.Add UIView as containerView of scrollview and add 6 Constraints from containerView to scrollview as below.

    a)Leading b)trailing c)top d)bottom e)Center Horizontally.

    3.Make sure top elements in container view must bind to top by adding top constraints and also bind bottom most element to bottom of container view by adding bottom constraints.And also all the items between topmost and bottommost in the container view must be vertically connected to each other so it will define the content size of container view.

    it will define the actual content height for scrollview. and finally define content size for scrollview in code.

    0 讨论(0)
提交回复
热议问题