使用UICollectionViewFlowLayout

时间:2016-08-10 10:53:33

标签: ipad keyboard xamarin.ios uicollectionviewlayout

如果其中的两个文本字段被iPad键盘的框架遮挡,我有一个移动CollectionView的方法:

    private void OnKeyboardNotification(NSNotification notification)
    {
        var activeTextField = FindFirstResponder(CollectionView);

        NSDictionary userInfo = notification.UserInfo;
        CGSize keyboardSize = ((NSValue)userInfo[UIKeyboard.FrameBeginUserInfoKey]).RectangleFValue.Size;

        var contentInset = new UIEdgeInsets(0, 0, keyboardSize.Height, 0);
        CollectionView.ContentInset = contentInset;
        CollectionView.ScrollIndicatorInsets = contentInset;

        CGRect oldRect = CollectionView.Frame;
        CGRect aRect = new CGRect(oldRect.X, oldRect.Y, oldRect.Width,
                                  oldRect.Height -= keyboardSize.Height);
        if (!aRect.Contains(activeTextField.Frame.Location))
        {
            CGPoint scrollPoint = new CGPoint(0, activeTextField.Frame.Location.Y - (keyboardSize.Height - 15));
            CollectionView.SetContentOffset(scrollPoint, true);
        }
    }

我不相信代码按预期工作。由于我在UICollectionViewFlowLayout的子类中定义了自定义布局,因此这很复杂。布局允许我让单元格垂直滚动,捕捉到焦点。

每次拨打OnKeyboardNotification时,都会在自定义布局中调用override UICollectionViewLayoutAttributes[]。我认为这可能会取消该方法的效果,但如果是这种情况,那么我怎样才能在调用UICollectionViewLayoutAttributes[]时进行更改?

    public override UICollectionViewLayoutAttributes[] LayoutAttributesForElementsInRect(CGRect rect)
    {
        var array = base.LayoutAttributesForElementsInRect(rect);
        var visibleRect = new CGRect(CollectionView.ContentOffset, CollectionView.Bounds.Size);

        foreach (var attributes in array)
        {
            if (attributes.Frame.IntersectsWith(rect))
            {
                float distance = (float)(visibleRect.GetMidX() - attributes.Center.X);
                float normalizedDistance = distance / ACTIVE_DISTANCE;
                if (Math.Abs(distance) < ACTIVE_DISTANCE)
                {
                    float zoom = 1 + ZOOM_FACTOR * (1 - Math.Abs(normalizedDistance));
                    attributes.Transform3D = CATransform3D.MakeScale(zoom, zoom, 1.0f);
                    attributes.ZIndex = 1;
                }
            }
        }
        return array;
    }

编辑:

以下是问题的一个示例。

我有两个字段

此处,当输入“编辑模式”时,键盘会隐藏年龄字段。

1 个答案:

答案 0 :(得分:0)

好像你使用了Xamarin样品中的样品。

每次更改UICollectionView的大小时都会调用UICollectionViewLayoutAttributes。

我建议您更改视图的位置,而不是在OnKeyboardNotification方法中更改大小:

    CGRect oldRect = CollectionView.Frame;
    CGRect aRect = new CGRect(oldRect.X, oldRect.Y  - keyboardSize.Height, oldRect.Width,oldRect.Height);

希望它可以解决你的问题,我现在是午夜,如果它无法工作,留下一些信息,明天早上我会检查后者。

编辑---------------------------------------------- -------------------

我更改了您使用的示例中的一些代码以产生效果。

首先,我在AppDelegate.cs中选择LineLayout,如下所示:

public override bool FinishedLaunching (UIApplication app, NSDictionary options)
    {
        //Don't change anything

//            simpleCollectionViewController = new SimpleCollectionViewController (flowLayout);
        simpleCollectionViewController = new SimpleCollectionViewController (lineLayout);
//            simpleCollectionViewController = new SimpleCollectionViewController (circleLayout);

        simpleCollectionViewController.CollectionView.ContentInset = new UIEdgeInsets (50, 0, 0, 0);

        window.RootViewController = simpleCollectionViewController;
        window.MakeKeyAndVisible ();

        return true;
    }

然后,我向LineLayout.cs添加一个静态属性,如下所示:

public class LineLayout : UICollectionViewFlowLayout
{
    private static bool flagForLayout = true;
    public static bool FlagForLayout {
        get {
            return flagForLayout;
        }
        set {
            flagForLayout = value;
        }
    }

    public const float ITEM_SIZE = 200.0f;
    public const int ACTIVE_DISTANCE = 200;
    public const float ZOOM_FACTOR = 0.3f;

    public LineLayout ()
    {
        //Don't change anything
    }

    public override bool ShouldInvalidateLayoutForBoundsChange (CGRect newBounds)
    {
        return flagForLayout;
    }

    public override UICollectionViewLayoutAttributes[] LayoutAttributesForElementsInRect (CGRect rect)
    {
        //Don't change anything
    }

    public override CGPoint TargetContentOffset (CGPoint proposedContentOffset, CGPoint scrollingVelocity)
    {
        //Don't change anything
    }

}

然后在SimpleCollectionViewController.cs中,我为每个单元格添加一个UITextField,如下所示:

public override UICollectionViewCell GetCell (UICollectionView collectionView, NSIndexPath indexPath)
    {
        var animalCell = (AnimalCell)collectionView.DequeueReusableCell (animalCellId, indexPath);

        var animal = animals [indexPath.Row];

        animalCell.Image = animal.Image;

        animalCell.AddSubview (new UITextField (new CGRect (0, 0, 100, 30)){ BackgroundColor = UIColor.Red });

        return animalCell;
    }

仍然在SimpleCollectionViewController.cs中,我在ViewDidload方法中添加了一些代码并添加了两个方法来处理键盘显示事件,如下所示:

public override void ViewDidLoad ()
    {
        base.ViewDidLoad ();

        CollectionView.RegisterClassForCell (typeof(AnimalCell), animalCellId);
        CollectionView.RegisterClassForSupplementaryView (typeof(Header), UICollectionElementKindSection.Header, headerId);

        UIMenuController.SharedMenuController.MenuItems = new UIMenuItem[] {
            new UIMenuItem ("Custom", new Selector ("custom"))
        };

        this.View.AddGestureRecognizer(new UITapGestureRecognizer(()=>{
            this.View.EndEditing(true);
        }));

        NSNotificationCenter.DefaultCenter.AddObserver(this,new ObjCRuntime.Selector("onKeyboardWillShowNotification:"),UIKeyboard.WillShowNotification,null);
        NSNotificationCenter.DefaultCenter.AddObserver(this,new ObjCRuntime.Selector("onKeyboardWillHideNotification:"),UIKeyboard.WillHideNotification,null);

    }

    [Export("onKeyboardWillShowNotification:")]
    private void OnKeyboardWillShowNotification(NSNotification notification)
    {
        LineLayout.FlagForLayout = false;
        NSDictionary userInfo = notification.UserInfo;
        CGSize keyboardSize = ((NSValue)userInfo[UIKeyboard.FrameBeginUserInfoKey]).RectangleFValue.Size;

        CGRect oldRect = CollectionView.Frame;
        CGRect aRect = new CGRect(oldRect.X, oldRect.Y - keyboardSize.Height, oldRect.Width,
            oldRect.Height);
        this.CollectionView.Frame = aRect;
    }

    [Export("onKeyboardWillHideNotification:")]
    private void OnKeyboardWillHideNotification(NSNotification notification)
    {
        LineLayout.FlagForLayout = true;
        this.CollectionView.Frame = UIScreen.MainScreen.Bounds;
    }

现在在键盘显示时会调用LayoutAttributesForElementsInRect,希望它可以解决你的问题。