[已解决]Swift中给UITableView和UIToolbar之间添加限制约束Constraint

[已解决]Swift中键盘显示后调整TableView的显示高度后工具栏变黑色了

期间,需要去:

给一个container的View:chatView中的tableview和toolbar之间,添加约束限制

使得:

tableview1的高度=chatView的高度-toolbar的高度

(或者最好再加上

tableview的最底端==toolbar的最顶端)

注:

之前在别的代码中,就试过一次加约束,但是没成功:

感觉添加约束,好像有点复杂,难搞懂的样子。。

搜:

swift 添加约束

Swift自适应布局(Adaptive Layout)教程(一) – 程序员说

自动布局autolayout使用总结(源码含swift版本) – 厚积薄发 – 博客频道 – CSDN.NET

iOS学习之Autolayout(代码添加约束)-Swift & Objective-C IOS-苦咖啡

其中讲到了:

对于约束条件,加到哪个view上的逻辑

Swift语言Auto Layout入门教程:上篇 – CocoaChina 苹果开发中文站 – 最热的iPhone开发社区 最热的苹果开发社区 最热的iPad开发社区

Swift语言Auto Layout入门教程:下篇 – CocoaChina_让移动开发更简单

iOS 8 Auto Layout界面自动布局系列3-使用代码添加布局约束 – 51iOS.net

swift add constraints programmatically

ios – SWIFT | Adding constraints programmatically – Stack Overflow

ios – add constraints programmatically swift – Stack Overflow

提到了:

对于iOS 8之后,把约束条件加到哪个view上,已经不需要我们操心了:

可以用active即可:

学习AutoLayout(NSLayoutConstraint) – 简书

NSLayoutConstraint Class Reference

还是官网解释的清楚:

NSLayoutConstraint有个active属性

设置active为true或false,内部会调用addConstraint或removeConstraint,添加或删除约束条件到哪呢?到两个view的最接近的一个共有的父视图上

-》也就是:

iOS学习之Autolayout(代码添加约束)-Swift & Objective-C IOS-苦咖啡

http://www.cokco.cn/thread-10684-1-1.html

画的那些图:

  1. 兄弟 view 的 Constraint 添加到他们的 superview

  2. 两个 view 的父 view 是兄弟关系的,Constraint 添加到父 view 的 superview 上

  3. 如果两个 view 是 parent-child 关系,Constraint 添加到 parent view上

-》不过,此处对于active属性的话,貌似系统内部调用addConstraint或removeConstraint时会自动判断的,无需自己操心

-》上述的active,是对于单个的NSLayoutConstraint来说的

想要一次性地,激活或取消多个约束条件的话,才会去调用对应的:

activateConstraints或deactivateConstraints

等价于对于每个约束条件都去调用active=yes

-》需要注意的是:上述的active,activateConstraints或deactivateConstraints,都只是在iOS 8.0之后才有

用代码:

        let heightConstraint:NSLayoutConstraint = NSLayoutConstraint(
            item:
messageTableView, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.LessThanOrEqual, toItem: inputMessageToolbar, attribute: NSLayoutAttribute.Top, multiplier: 1.0, constant: 0)
       
//<NSLayoutConstraint:0x7f8952785960 UITableView:0x7f8953863800.bottom <= UIToolbar:0x7f89525b8300.top>
        heightConstraint.active = true

没有效果:

好像是因为:

自己手动设置了frame了?

translatesAutoresizingMaskIntoConstraints

参考:

iOS: 让自定义控件适应Autolayout注意的问题 | Mgen

UIView Class Reference

去设置

结果,点击出现输入框,应该出现键盘时,变成:

学习iOS 6.0的NSAutoLayout – Kut@Padovo.com

学习AutoLayout(NSLayoutConstraint) – 简书

学习AutoLayout(VFL) – 简书

学习AutoLayout(UIScrollView) – 简书

学习AutoLayout(VFL中“-”的使用) – 简书

然后用代码:

        //add constraints for messageTableView
        self.messageTableView = UITableView()
       
messageTableView.translatesAutoresizingMaskIntoConstraints = false
       
let messageTopConstraint:NSLayoutConstraint = NSLayoutConstraint(
                item:
messageTableView,
                attribute:
NSLayoutAttribute.Top,
                relatedBy:
NSLayoutRelation.Equal,
                toItem:
chatView,
                attribute:
NSLayoutAttribute.Top,
                multiplier:
1.0,
                constant:
0)
       
let messageBottomConstraint:NSLayoutConstraint = NSLayoutConstraint(
                item:
messageTableView,
                attribute:
NSLayoutAttribute.Bottom,
                relatedBy:
NSLayoutRelation.Equal,
                toItem:
chatView,
                attribute:
NSLayoutAttribute.Bottom,
                multiplier:
1.0,
                constant: (
0 – toolbarHeight))
       
let messageLeftConstraint:NSLayoutConstraint = NSLayoutConstraint(
                item:
messageTableView,
                attribute:
NSLayoutAttribute.Left,
                relatedBy:
NSLayoutRelation.Equal,
                toItem:
chatView,
                attribute:
NSLayoutAttribute.Left,
                multiplier:
1.0,
                constant:
0)
       
let messageRightConstraint:NSLayoutConstraint = NSLayoutConstraint(
                item:
messageTableView,
                attribute:
NSLayoutAttribute.Right,
                relatedBy:
NSLayoutRelation.Equal,
                toItem:
chatView,
                attribute:
NSLayoutAttribute.Right,
                multiplier:
1.0,
                constant:
0)
       
NSLayoutConstraint.activateConstraints([
                messageTopConstraint,
                messageBottomConstraint,
                messageLeftConstraint,
                messageRightConstraint])
        chatView.addSubview(self.messageTableView)
//        let inputToolbarView = UIView(frame: CGRectMake(
//            0,
//            0,
//            //TODO: adjust according to iPhone screen width
//            self.view.frame.width – 60, //iPhone5:260, iPhone:315
//            30))
//        print("inputToolbarView.frame=\(inputToolbarView.frame)")
        //for debug
        //inputToolbarView.backgroundColor = UIColor.greenColor()

       
//add constraints
        let inputToolbarView = UIView()
        inputToolbarView.
translatesAutoresizingMaskIntoConstraints = false
       
let inputToolbarTopConstraint:NSLayoutConstraint = NSLayoutConstraint(
                item: inputToolbarView,
                attribute:
NSLayoutAttribute.Top,
                relatedBy:
NSLayoutRelation.Equal,
                toItem:
chatView,
                attribute:
NSLayoutAttribute.Bottom,
                multiplier:
1.0,
                constant: (
0 – toolbarHeight))
       
let inputToolbarBottomConstraint:NSLayoutConstraint = NSLayoutConstraint(
                item: inputToolbarView,
                attribute:
NSLayoutAttribute.Bottom,
                relatedBy:
NSLayoutRelation.Equal,
                toItem:
chatView,
                attribute:
NSLayoutAttribute.Bottom,
                multiplier:
1.0,
                constant:
0)
       
let inputToolbarLeftConstraint:NSLayoutConstraint = NSLayoutConstraint(
                item: inputToolbarView,
                attribute:
NSLayoutAttribute.Left,
                relatedBy:
NSLayoutRelation.Equal,
                toItem:
chatView,
                attribute:
NSLayoutAttribute.Left,
                multiplier:
1.0,
                constant:
0)
       
let inputToolbarRightConstraint:NSLayoutConstraint = NSLayoutConstraint(
                item: inputToolbarView,
                attribute:
NSLayoutAttribute.Right,
                relatedBy:
NSLayoutRelation.Equal,
                toItem:
chatView,
                attribute:
NSLayoutAttribute.Right,
                multiplier:
1.0,
                constant:
0)
       
NSLayoutConstraint.activateConstraints([
                inputToolbarTopConstraint,
                inputToolbarBottomConstraint,
                inputToolbarLeftConstraint,
                inputToolbarRightConstraint])
        chatView.addSubview(inputMessageToolbar)

结果程序挂了:

2015-11-29 15:11:06.616 JianDao[50721:2654673] *** Terminating app due to uncaught exception ‘NSGenericException’, reason: ‘Unable to activate constraint with items <UITableView: 0x7fc7d209b600; frame = (0 0; 0 0); clipsToBounds = YES; gestureRecognizers = <NSArray: 0x7fc7d413ca10>; layer = <CALayer: 0x7fc7d1cf6760>; contentOffset: {0, 0}; contentSize: {0, 0}> and <UIView: 0x7fc7d413c2e0; frame = (0 0; 375 603); layer = <CALayer: 0x7fc7d413b910>> because they have no common ancestor.  Does the constraint reference items in different view hierarchies?  That’s illegal.’
*** First throw call stack:
(
0   CoreFoundation                      0x000000010a002f45 __exceptionPreprocess + 165
1   libobjc.A.dylib                     0x000000010929bdeb objc_exception_throw + 48
2   CoreFoundation                      0x000000010a002e7d +[NSException raise:format:] + 205
3   Foundation                          0x000000010901908e +[NSLayoutConstraint _addOrRemoveConstraints:activate:] + 383
4   JianDao                             0x000000010897e23f _TFC7JianDao26MessageTableViewController11viewDidLoadfS0_FT_T_ + 5823
5   JianDao                             0x00000001089804d2 _TToFC7JianDao26MessageTableViewController11viewDidLoadfS0_FT_T_ + 34
6   UIKit                               0x000000010aca4cc4 -[UIViewController loadViewIfRequired] + 1198
7   UIKit                               0x000000010acaac7b -[UIViewController __viewWillAppear:] + 120
8   UIKit                               0x000000010acdaa37 -[UINavigationController _startCustomTransition:] + 1203
9   UIKit                               0x000000010aceacdb -[UINavigationController _startDeferredTransitionIfNeeded:] + 712
10  UIKit                               0x000000010acebcea -[UINavigationController __viewWillLayoutSubviews] + 57
11  UIKit                               0x000000010ae91c85 -[UILayoutContainerView layoutSubviews] + 248
12  UIKit                               0x000000010abc6e40 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 710
13  QuartzCore                          0x000000010a89259a -[CALayer layoutSublayers] + 146
14  QuartzCore                          0x000000010a886e70 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 366
15  QuartzCore                          0x000000010a886cee _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 24
16  QuartzCore                          0x000000010a87b475 _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 277
17  QuartzCore                          0x000000010a8a8c0a _ZN2CA11Transaction6commitEv + 486
18  UIKit                               0x000000010ab3d216 _afterCACommitHandler + 174
19  CoreFoundation                      0x0000000109f2e947 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
20  CoreFoundation                      0x0000000109f2e8b7 __CFRunLoopDoObservers + 391
21  CoreFoundation                      0x0000000109f2450b __CFRunLoopRun + 1147
22  CoreFoundation                      0x0000000109f23e08 CFRunLoopRunSpecific + 488
23  GraphicsServices                    0x000000010e6a3ad2 GSEventRunModal + 161
24  UIKit                               0x000000010ab1230d UIApplicationMain + 171
25  JianDao                             0x000000010890d2bd main + 109
26  libdyld.dylib                       0x000000010c9ce92d start + 1
27  ???                                 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException

难道是顺序错了?

那么把那些约束条件,放到最后:

         chatView.addSubview(self.messageTableView) 

         chatView.addSubview(inputMessageToolbar)

        //add constraints for messageTableView
        messageTableView.translatesAutoresizingMaskIntoConstraints = false
       
let messageTopConstraint:NSLayoutConstraint = NSLayoutConstraint(
            item:
messageTableView,
            attribute:
NSLayoutAttribute.Top,
            relatedBy:
NSLayoutRelation.Equal,
            toItem:
chatView,
            attribute:
NSLayoutAttribute.Top,
            multiplier:
1.0,
            constant:
statusBarFrame.height + HeightNaviBar)
       
let messageBottomConstraint:NSLayoutConstraint = NSLayoutConstraint(
            item:
messageTableView,
            attribute:
NSLayoutAttribute.Bottom,
            relatedBy:
NSLayoutRelation.Equal,
            toItem:
chatView,
            attribute:
NSLayoutAttribute.Bottom,
            multiplier:
1.0,
            constant: (
0 – toolbarHeight))
       
let messageLeftConstraint:NSLayoutConstraint = NSLayoutConstraint(
            item:
messageTableView,
            attribute:
NSLayoutAttribute.Left,
            relatedBy:
NSLayoutRelation.Equal,
            toItem:
chatView,
            attribute:
NSLayoutAttribute.Left,
            multiplier:
1.0,
            constant:
0)
       
let messageRightConstraint:NSLayoutConstraint = NSLayoutConstraint(
            item:
messageTableView,
            attribute:
NSLayoutAttribute.Right,
            relatedBy:
NSLayoutRelation.Equal,
            toItem:
chatView,
            attribute:
NSLayoutAttribute.Right,
            multiplier:
1.0,
            constant:
0)
       
NSLayoutConstraint.activateConstraints([
            messageTopConstraint,
            messageBottomConstraint,
            messageLeftConstraint,
            messageRightConstraint])

       
       
        //add constraints
        inputToolbarView.translatesAutoresizingMaskIntoConstraints = false
       
let inputToolbarTopConstraint:NSLayoutConstraint = NSLayoutConstraint(
            item: inputToolbarView,
            attribute:
NSLayoutAttribute.Top,
            relatedBy:
NSLayoutRelation.Equal,
            toItem:
chatView,
            attribute:
NSLayoutAttribute.Bottom,
            multiplier:
1.0,
            constant: (
0 – toolbarHeight))
       
let inputToolbarBottomConstraint:NSLayoutConstraint = NSLayoutConstraint(
            item: inputToolbarView,
            attribute:
NSLayoutAttribute.Bottom,
            relatedBy:
NSLayoutRelation.Equal,
            toItem:
chatView,
            attribute:
NSLayoutAttribute.Bottom,
            multiplier:
1.0,
            constant:
0)
       
let inputToolbarLeftConstraint:NSLayoutConstraint = NSLayoutConstraint(
            item: inputToolbarView,
            attribute:
NSLayoutAttribute.Left,
            relatedBy:
NSLayoutRelation.Equal,
            toItem:
chatView,
            attribute:
NSLayoutAttribute.Left,
            multiplier:
1.0,
            constant:
0)
       
let inputToolbarRightConstraint:NSLayoutConstraint = NSLayoutConstraint(
            item: inputToolbarView,
            attribute:
NSLayoutAttribute.Right,
            relatedBy:
NSLayoutRelation.Equal,
            toItem:
chatView,
            attribute:
NSLayoutAttribute.Right,
            multiplier:
1.0,
            constant:
0)
       
NSLayoutConstraint.activateConstraints([
            inputToolbarTopConstraint,
            inputToolbarBottomConstraint,
            inputToolbarLeftConstraint,

            inputToolbarRightConstraint])

虽然可以运行了,但是还是效果不对:

AutoLayout的三种设置方式之——NSLayoutConstraint代码篇 – 愤怒大熊猫 – 博客园

好像是:

父的view,此处的chatView,难道也是不能设置frame???

ios – AutoLayout acts strangely when translatesAutoresizingMaskIntoConstraints set to false – Stack Overflow

调试改为:

        messageTableView.translatesAutoresizingMaskIntoConstraints = false
//        inputMessageToolbar.translatesAutoresizingMaskIntoConstraints = false
//        chatView.translatesAutoresizingMaskIntoConstraints = false

出错:

2015-11-29 15:51:54.147 JianDao[51551:2697148] Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don’t want.
Try this:
(1) look at each constraint and try to figure out which you don’t expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(Note: If you’re seeing NSAutoresizingMaskLayoutConstraints that you don’t understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints)
(
    "<NSAutoresizingMaskLayoutConstraint:0x7f9c8b0a9900 h=–& v=–& UIToolbar:0x7f9c88ee2700.midY ==>",
    "<NSAutoresizingMaskLayoutConstraint:0x7f9c8b0a9970 h=–& v=–& V:[UIToolbar:0x7f9c88ee2700(0)]>",
    "<NSAutoresizingMaskLayoutConstraint:0x7f9c88fe0c10 h=–& v=–& V:[UIView:0x7f9c88eee3c0(603)]>",
    "<NSLayoutConstraint:0x7f9c88efa3f0 UIToolbar:0x7f9c88ee2700.bottom == UIView:0x7f9c88eee3c0.bottom>"
)

Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x7f9c88efa3f0 UIToolbar:0x7f9c88ee2700.bottom == UIView:0x7f9c88eee3c0.bottom>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.

The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.

改为:

        messageTableView.translatesAutoresizingMaskIntoConstraints = false
       
inputMessageToolbar.translatesAutoresizingMaskIntoConstraints = false
        chatView.translatesAutoresizingMaskIntoConstraints = false

没有警告了,但是效果还是不对:

参考:

代码添加constraint,设置translatesAutoresizingMaskIntoConstraints为NO的原因 – 1993奇葩 – 博客频道 – CSDN.NET

搜:

Layout is performed in three primary ways

找到:

1. Views – Programming iOS 8

Programmatically create a constraint – Swift | Ryan Wright

swift UIViewAutoresizing FlexibleTopMargin example

swift UIViewAutoresizing example

swift UIViewAutoresizing demo

最后的最后,还是没有搞定,如何通过添加约束条件的方式,实现在:

键盘显示的时候,调整chatView内的toolbar的位置以便得以显示出来toolbar

最后是通过autoresizingMask解决的:

详见:

[已解决]Swift中键盘显示后调整TableView的显示高度后工具栏变黑色了

抽空再去看看:

1. Views – Programming iOS 8



发表评论

电子邮件地址不会被公开。 必填项已用*标注

无觅相关文章插件,快速提升流量