【问题标题】:IOS, How to set Auto Layout in your UITableViewCell that contains different SubviewsIOS,如何在包含不同子视图的 UITableViewCell 中设置自动布局
【发布时间】:2014-11-05 21:33:37
【问题描述】:

我有一个布局问题,我有一个包含 UIImageView 和其他三个 UILabel 的 UIView。需要动态设置布局的部分是添加到单元格的主 UIView 和一个包含任意长度文本的 UILabel 让我们说这个例子。

我做了什么,我创建了一个自定义 UITableViewCell 并将 SubViews 添加到自定义 UITableViewCell,如下所示:

        -(void)setupView:(PostInfo*)postInfo{


            CGRect screenRect = [[UIScreen mainScreen] bounds];
            viewPostMessage = [[UIView alloc] initWithFrame:CGRectMake(10, 10, screenRect.size.width - 20, 100)];
            viewPostMessage.backgroundColor = [UIColor colorWithRed:193.0f/255 green:193.0f/255 blue:193.0f/255 alpha:1.0f];
            viewPostMessage.layer.borderColor = [UIColor blackColor].CGColor;
            viewPostMessage.layer.borderWidth = 0.5f;


            if(postInfo.userImage.length > 0){
            userImage = [[UIImageView alloc] initWithFrame:CGRectMake(10, 10, 30, 30)];
            UIImage *imageUser =  [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString: [NSString stringWithFormat:@"http://www.hugt.co.uk/userimage/%d/userImage.jpg", postInfo.userId]]]];
            userImage.image = imageUser;
            [viewPostMessage addSubview:userImage];
            }else{
            UIView *viewImage = [[UIView alloc] initWithFrame:CGRectMake(10, 10, 30, 30)];
            viewImage.backgroundColor = [UIColor colorWithRed:132.0f/255 green:132.0f/255 blue:132.0f/255 alpha:1.0f];
            [viewPostMessage addSubview:viewImage];

            userImage = [[UIImageView alloc] initWithFrame:CGRectMake(5, 5, 20, 20)];
            UIImage *imageUser = [UIImage imageNamed:@"defaultuser.jpg"];
            userImage.image = imageUser;
            [viewImage addSubview:userImage];
            }

            labelUserName = [[UILabel alloc] initWithFrame:CGRectMake(50, 8, 200, 16)];
            labelUserName.textColor = [UIColor colorWithRed:56.0f/255 green:56.0f/255 blue:57.0f/255 alpha:1.0f];
            labelUserName.text = [NSString stringWithFormat:@"%@ %@ posted...", postInfo.firstName,postInfo.lastName];
            //labelFirstName.textAlignment = NSTextAlignmentCenter;
            labelUserName.font = [UIFont fontWithName:@"Helvetica" size:12];
            labelUserName.userInteractionEnabled = YES;
            [viewPostMessage addSubview:labelUserName];

            labelCreated = [[UILabel alloc] initWithFrame:CGRectMake(50, 24, 200, 16)];
            labelCreated.textColor = [UIColor colorWithRed:86.0f/255 green:152.0f/255 blue:179.0f/255 alpha:1.0f];
            labelCreated.text = [NSDateFormatter localizedStringFromDate:postInfo.timeStampCreated dateStyle:NSDateFormatterMediumStyle timeStyle:NSDateFormatterMediumStyle];
            labelCreated.text = [labelCreated.text stringByReplacingOccurrencesOfString:@"AM" withString:@""];
            labelCreated.text = [labelCreated.text stringByReplacingOccurrencesOfString:@"PM" withString:@""];
            //labelFirstName.textAlignment = NSTextAlignmentCenter;
            labelCreated.font = [UIFont fontWithName:@"Helvetica" size:12];
            labelCreated.userInteractionEnabled = YES;
            [viewPostMessage addSubview:labelCreated];

            labelMessage = [[UILabel alloc] initWithFrame:CGRectMake(50, 43, 210, 50)];
            labelMessage.textColor = [UIColor colorWithRed:141.0f/255 green:142.0f/255 blue:142.0f/255 alpha:1.0f];
            labelMessage.text = postInfo.message;
            labelMessage.numberOfLines = 3;
            //labelFirstName.textAlignment = NSTextAlignmentCenter;
            labelMessage.font = [UIFont fontWithName:@"Helvetica" size:12];
            labelMessage.userInteractionEnabled = YES;
            [labelMessage sizeToFit];
            [viewPostMessage addSubview:labelMessage];

            [self.contentView addSubview:viewPostMessage];

        }

当我创建这个自定义 UITableViewCell 时,我传入一个对象,该对象设置 UILabel 上的文本,如下所示:

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
            static NSString *cellIdentifier = @"cell";


            if(tableViewThreads == tableView){
            UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

            if (cell == nil)
            {
                cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
            }
            ThreadInfo *threadInfo = (ThreadInfo*)[self.threadsArray objectAtIndex:indexPath.row];
            [cell.contentView addSubview:[self setupThreadItem:threadInfo]];
            cell.selectionStyle = UITableViewCellSelectionStyleNone;
            return cell;

            }
            if(tableViewPosts == tableView){
            PostTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

            if (cell == nil)
            {
                cell = [[PostTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
            }

            PostInfo *postInfo = (PostInfo*)[self.postsArray objectAtIndex:indexPath.row];
            [cell setupView:postInfo];



            //[cell addSubview:[self setupPostItem:postInfo]];
            cell.selectionStyle = UITableViewCellSelectionStyleNone;
            return cell;
            //[cell.contentView addSubview:[self setupThreadItem:threadInfo]];
            }

            return nil;
        }

我已经搜索了网络和这里以了解如何在单元格中自动布局子视图,但似乎无法理解下一步需要做什么。我读到你需要一个原型单元,所以我创建了一个自定义 UITableViewCell,这就是我已经走了多远。

任何帮助将不胜感激,谢谢。

【问题讨论】:

    标签: ios objective-c


    【解决方案1】:

    到目前为止,我已经让单元格使用自动布局调整大小,但我已经删除了位于单元格内的 UIView,所以现在我有三个 UILabel 和一个 UIImageView,它们是 UIImageView (userImage)、UILabel (labelUsername)、UILabel (labelCreated) 和 UILabel (labelMessage)。所以尺寸和坐标是一样的,只是 UIView 被移除了:

    首先我在自定义单元格中设置 NSLayoutContsraints,代码如下:

    设置 numberOFLines = 0 并删除 UILabel 上的 sizeToFit ,即自动布局。

    -(void)setupView:(PostInfo*)postInfo{
    
    
                CGRect screenRect = [[UIScreen mainScreen] bounds];
                viewPostMessage = [[UIView alloc] initWithFrame:CGRectMake(10, 10, screenRect.size.width - 20, 100)];
                viewPostMessage.backgroundColor = [UIColor colorWithRed:193.0f/255 green:193.0f/255 blue:193.0f/255 alpha:1.0f];
                viewPostMessage.layer.borderColor = [UIColor blackColor].CGColor;
                viewPostMessage.layer.borderWidth = 0.5f;
    
    
                if(postInfo.userImage.length > 0){
                userImage = [[UIImageView alloc] initWithFrame:CGRectMake(10, 10, 30, 30)];
                UIImage *imageUser =  [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString: [NSString stringWithFormat:@"http://www.hugt.co.uk/userimage/%d/userImage.jpg", postInfo.userId]]]];
                userImage.image = imageUser;
                [self.contentView addSubview:userImage];
                }else{
                UIView *viewImage = [[UIView alloc] initWithFrame:CGRectMake(10, 10, 30, 30)];
                viewImage.backgroundColor = [UIColor colorWithRed:132.0f/255 green:132.0f/255 blue:132.0f/255 alpha:1.0f];
                [self.contentView addSubview:viewImage];
    
                userImage = [[UIImageView alloc] initWithFrame:CGRectMake(5, 5, 20, 20)];
                UIImage *imageUser = [UIImage imageNamed:@"defaultuser.jpg"];
                userImage.image = imageUser;
                [viewImage addSubview:userImage];
                }
    
                labelUserName = [[UILabel alloc] initWithFrame:CGRectMake(50, 8, 200, 16)];
                labelUserName.textColor = [UIColor colorWithRed:56.0f/255 green:56.0f/255 blue:57.0f/255 alpha:1.0f];
                labelUserName.text = [NSString stringWithFormat:@"%@ %@ posted...", postInfo.firstName,postInfo.lastName];
                //labelFirstName.textAlignment = NSTextAlignmentCenter;
                labelUserName.font = [UIFont fontWithName:@"Helvetica" size:12];
                labelUserName.userInteractionEnabled = YES;
                [self.contentView addSubview:labelUserName];
    
                labelCreated = [[UILabel alloc] initWithFrame:CGRectMake(50, 24, 200, 16)];
                labelCreated.textColor = [UIColor colorWithRed:86.0f/255 green:152.0f/255 blue:179.0f/255 alpha:1.0f];
                labelCreated.text = [NSDateFormatter localizedStringFromDate:postInfo.timeStampCreated dateStyle:NSDateFormatterMediumStyle timeStyle:NSDateFormatterMediumStyle];
                labelCreated.text = [labelCreated.text stringByReplacingOccurrencesOfString:@"AM" withString:@""];
                labelCreated.text = [labelCreated.text stringByReplacingOccurrencesOfString:@"PM" withString:@""];
                //labelFirstName.textAlignment = NSTextAlignmentCenter;
                labelCreated.font = [UIFont fontWithName:@"Helvetica" size:12];
                labelCreated.userInteractionEnabled = YES;
                [self.contentView addSubview:labelCreated];
    
                labelMessage = [[UILabel alloc] initWithFrame:CGRectMake(50, 43, 210, 50)];
                labelMessage.textColor = [UIColor colorWithRed:141.0f/255 green:142.0f/255 blue:142.0f/255 alpha:1.0f];
                labelMessage.text = postInfo.message;
                labelMessage.numberOfLines = 0;
                //labelFirstName.textAlignment = NSTextAlignmentCenter;
                labelMessage.font = [UIFont fontWithName:@"Helvetica" size:12];
                labelMessage.userInteractionEnabled = YES;
                labelMessage.lineBreakMode = NSLineBreakByWordWrapping;
                //[labelMessage sizeToFit];
                [self.contentView addSubview:labelMessage];
    
                labelMessage.translatesAutoresizingMaskIntoConstraints = NO;
    
                [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-10-[bodyLabel]-19-|" options:0 metrics:nil views:@{ @"bodyLabel": labelMessage }]];
                [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-43-[bodyLabel]-6-|" options:0 metrics:nil views:@{ @"bodyLabel": labelMessage }]];
    
                //[self.contentView addSubview:viewPostMessage];
    
            }
    

    然后在包含 UITableVIew 的 ViewController 中,我修改了这段代码:

    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
                static NSString *cellIdentifier = @"cell";
                if(tableViewThreads == tableView){
    
                return 122;
    
                }
                if(tableViewPosts == tableView){
                PostTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    
                if (cell == nil)
                {
                    cell = [[PostTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
                }
    
                PostInfo *postInfo = (PostInfo*)[self.postsArray objectAtIndex:indexPath.row];
                [cell setupView:postInfo];
    
                [cell setNeedsLayout];
                [cell layoutIfNeeded];
    
                CGFloat h = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
    
                return h + 1;
    
    
                }
                return 0;
            }
    

    Cells 现在会调整大小,UILabel 现在会自动调整大小,但我的另一个问题是 UITableView 滚动不平滑,所以我必须解决这个问题,当我在 UITableView 中滚动时,来自 UILabel 的 Cell 数据( labelMessage) 似乎在其他单元格中自行打印,不知道这是为什么

    但是单元格调整大小和其他问题在这里提出另一个问题。

    抱歉忘记添加 PostTableViewCell 中的这段代码:

            - (void)layoutSubviews
            {
                [super layoutSubviews];
    
                // Make sure the contentView does a layout pass here so that its subviews have their frames set, which we
                // need to use to set the preferredMaxLayoutWidth below.
                [self.contentView setNeedsLayout];
                [self.contentView layoutIfNeeded];
    
                // Set the preferredMaxLayoutWidth of the mutli-line bodyLabel based on the evaluated width of the label's frame,
                // as this will allow the text to wrap correctly, and as a result allow the label to take on the correct height.
                labelMessage.preferredMaxLayoutWidth = CGRectGetWidth(labelMessage.frame);
            }
    

    【讨论】:

    • 我看到的一个大问题是使用NSData dataWithContentsOfURL:。除非您知道这些图像已缓存,否则这是对网络的阻塞(同步)调用,不应该在主线程上执行(我假设您的 -setupView: 正在运行。)
    • 所以我必须使用调度队列
    • 是的,这将是加载图像的一种方式。但随后您需要切换回主队列以在 UIImageView 上实际设置 UIImage。您也可以使用AFNetworking。它在 UIImageView 上有一个甜蜜的类别,用于异步加载/设置图像。
    • 谢谢老哥我试试
    猜你喜欢
    • 2013-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多