【问题标题】:Swift - How to create this form bubble effectSwift - 如何创建这种形式的气泡效果
【发布时间】:2020-01-20 08:12:06
【问题描述】:

所以我正在尝试使用 xcode swift 创建以下效果。

我正在尝试使用以下样式重新创建包含文本字段和文本字段本身的表单气泡。

到目前为止我所做的尝试:

创建一个带有弯曲边框的 UI 视图,然后使用透明文本字段和 UILabel 来指示字段内容。

我假设它必须是一个 UItableview 给定缩进线,但我不确定如何以相同的方式设置 tableview 的样式。我以为我可以像对 UIView 一样使用 layer.cornerRadius ,但这似乎不起作用。

整个视图控制器也是UItableview控制器还是UICollectionView?

任何有关如何创建如下表单的帮助将不胜感激。

【问题讨论】:

    标签: swift xcode storyboard swift4 swift5


    【解决方案1】:

    在 iOS 13 中,您只需将 Style 设置为 Inset Grouped,UITableView 看起来就像那样 - 无需额外更改。

    【讨论】:

    • 我试过了,但我觉得没有达到同样的效果,你有图片吗?
    【解决方案2】:

    对整个 tableview 使用 layer.cornerRadius 将不起作用。您应该使用 UITableviewController 或包含 tableView 的普通 UIViewController 然后将您的 tableview 分为 3 个部分

    • 第一部分应该是配置文件:这部分毫无疑问,你的单元格边框与设计相同

    • 第二部分应该是个人信息。 3 个单元格,每个单元格包含文本字段。您可以通过相应位置为单元格计算并创建边框(顶部单元格将在左上和右上加边框,底部单元格将在左下角和右下角加边框,否则没有边框)

    • 第三部分:这个不用怀疑,只要一个单元格(切换账号)

    【讨论】:

    • 感谢您的建议,但是您如何删除单元格的插图。它们仍然出现在上方和下方。另外你会如何填充这个?你在填充内部容器视图吗?
    • 有几种方法可以做到这一点。您可以使用此self.contentView.frame = self.contentView.frame.inset(by: yourInset) 使用超级视图或在 TableviewCell 内插入表视图的前导和尾随约束
    【解决方案3】:

    SWIFT 解决方案

    感谢保罗·席尔瓦

    第 1 步: 您可以简单地创建一个名为“CUIView”(或您自己的愿望)的快速文件,并在其中使用以下 IBDesignable 代码并保存。

    //
    //  CUIView.swift
    //  CustomUIView
    //
    //  Created by Paulo Silva on 23/08/2019.
    //  Copyright © 2019 example. All rights reserved.
    //
    
    import UIKit
    import UIKit
    import CoreGraphics
    
    @IBDesignable class CUIView: UIView {
    
        // MARK: - Private Variables -
    
        private let containerView = UIView()
        private var containerImageView = UIImageView()
    
        // MARK: - Public Attributes -
    
        @IBInspectable public var backgroundImage: UIImage? {
            get {
                return self.containerImageView.image
            }
            set {
    //            addShadowColorFromBackgroundImage()
                self.containerImageView.image = newValue
            }
        }
    
        override open var backgroundColor: UIColor? {
            didSet(new) {
                if let color = new {
                    containerView.backgroundColor = color
                }
                if backgroundColor != UIColor.clear { backgroundColor = UIColor.clear }
            }
        }
    
        @IBInspectable var borderColor: UIColor {
            get {
                return UIColor(cgColor: self.containerView.layer.borderColor!)
            }
            set {
                self.layer.borderColor = newValue.cgColor
                self.containerView.layer.borderColor = newValue.cgColor
            }
        }
    
        @IBInspectable var borderWidth: CGFloat {
            get {
                return self.containerView.layer.borderWidth
            }
            set {
                self.layer.borderWidth = newValue
                self.containerView.layer.borderWidth = newValue
            }
        }
    
        @IBInspectable var cornerRadius: CGFloat {
            get {
                return self.containerView.layer.cornerRadius
            }
            set {
                self.layer.cornerRadius = newValue
                self.containerView.layer.cornerRadius = newValue
            }
        }
    
        @IBInspectable var shadowOpacity: Float {
            get {
                return self.layer.shadowOpacity
            }
            set {
                self.layer.shadowOpacity = newValue
            }
        }
    
        @IBInspectable var shadowRadius: CGFloat {
            get {
                return self.layer.shadowRadius
            }
            set {
                self.layer.shadowRadius = newValue
            }
        }
    
        @IBInspectable var shadowOffset: CGSize {
            get {
                return self.layer.shadowOffset
            }
            set {
                self.layer.shadowOffset = newValue
            }
        }
    
        @IBInspectable var shadowColor: UIColor {
            get {
                return UIColor(cgColor: self.layer.shadowColor!)
            }
            set {
                self.layer.shadowColor = newValue.cgColor
            }
        }
    
    //    @IBInspectable var shadowColorFormImage: Bool = false {
    //        didSet {
    //            addShadowColorFromBackgroundImage()
    //        }
    //    }
    
        // MARK: - Life Cycle -
    
        override init(frame: CGRect) {
            super.init(frame: frame)
            addViewLayoutSubViews()
            refreshViewLayout()
        }
    
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
            addViewLayoutSubViews()
            refreshViewLayout()
        }
    
        override open func draw(_ rect: CGRect) {
            super.draw(rect)
            refreshViewLayout()
    //        addShadowColorFromBackgroundImage()
        }
    
        override func layoutSubviews() {
            super.layoutSubviews()
            refreshViewLayout()
    //        addShadowColorFromBackgroundImage()
        }
    
        // MARK: - Private Methods -
    
        private func refreshViewLayout() {
            // View
            self.clipsToBounds = true
            self.layer.masksToBounds = false
            self.layer.cornerRadius = cornerRadius
    
            // Shadow
            self.layer.shadowOpacity = shadowOpacity
            self.layer.shadowColor = shadowColor.cgColor
            self.layer.shadowOffset = shadowOffset
            self.layer.shadowRadius = shadowRadius
    
            // Container View
            self.containerView.layer.masksToBounds = true
            self.containerView.layer.cornerRadius = cornerRadius
    
            // Image View
            self.containerImageView.backgroundColor = UIColor.clear
            self.containerImageView.image = backgroundImage
            self.containerImageView.layer.cornerRadius = cornerRadius
            self.containerImageView.layer.masksToBounds = true
            self.containerImageView.clipsToBounds = true
            self.containerImageView.contentMode = .redraw
        }
    
        private func addViewLayoutSubViews() {
            // add subViews
            self.addSubview(self.containerView)
            self.containerView.addSubview(self.containerImageView)
    
            // add image constraints
            self.containerImageView.translatesAutoresizingMaskIntoConstraints = false
            self.containerImageView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
            self.containerImageView.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
            self.containerImageView.topAnchor.constraint(equalTo: topAnchor).isActive = true
            self.containerImageView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
    
            // add view constraints
            self.containerView.translatesAutoresizingMaskIntoConstraints = false
            self.containerView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
            self.containerView.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
            self.containerView.topAnchor.constraint(equalTo: topAnchor).isActive = true
            self.containerView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
        }
    
    //    private func addShadowColorFromBackgroundImage() {
    //        // Get the averageColor from the image for set the Shadow Color
    //        if shadowColorFormImage {
    //            let week = self
    //            DispatchQueue.main.async {
    //                week.shadowColor = (week.containerImageView.image?.averageColor)!
    //            }
    //        }
    //    }
    }
    
    extension UIImage {
    
        static func imageWithColor(tintColor: UIColor) -> UIImage {
            let rect = CGRect(x: 0, y: 0, width: 1, height: 1)
            UIGraphicsBeginImageContextWithOptions(rect.size, false, 0)
            tintColor.setFill()
            UIRectFill(rect)
            let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
            UIGraphicsEndImageContext()
            return image
        }
    
        func withBackground(color: UIColor, opaque: Bool = true) -> UIImage {
            UIGraphicsBeginImageContextWithOptions(size, opaque, scale)
            guard let ctx = UIGraphicsGetCurrentContext() else { return self }
            defer { UIGraphicsEndImageContext() }
            let rect = CGRect(origin: .zero, size: size)
            ctx.setFillColor(color.cgColor)
            ctx.fill(rect)
            ctx.concatenate(CGAffineTransform(a: 1, b: 0, c: 0, d: -1, tx: 0, ty: size.height))
            ctx.draw(cgImage!, in: rect)
            return UIGraphicsGetImageFromCurrentImageContext() ?? self
        }
    
        var averageColor: UIColor? {
            guard let inputImage = CIImage(image: self) else { return nil }
            let extentVector = CIVector(x: inputImage.extent.origin.x, y: inputImage.extent.origin.y, z: inputImage.extent.size.width, w: inputImage.extent.size.height)
    
            guard let filter = CIFilter(name: "CIAreaAverage", parameters: [kCIInputImageKey: inputImage, kCIInputExtentKey: extentVector]) else { return nil }
            guard let outputImage = filter.outputImage else { return nil }
    
            var bitmap = [UInt8](repeating: 0, count: 4)
            let context = CIContext(options: [.workingColorSpace: kCFNull as Any])
            context.render(outputImage, toBitmap: &bitmap, rowBytes: 4, bounds: CGRect(x: 0, y: 0, width: 1, height: 1), format: .RGBA8, colorSpace: nil)
    
            return UIColor(red: CGFloat(bitmap[0]) / 255, green: CGFloat(bitmap[1]) / 255, blue: CGFloat(bitmap[2]) / 255, alpha: CGFloat(bitmap[3]) / 255)
        }
    }
    
    extension NSLayoutConstraint {
        func constraintWithMultiplier(_ multiplier: CGFloat) -> NSLayoutConstraint {
            return NSLayoutConstraint(item: self.firstItem!, attribute: self.firstAttribute, relatedBy: self.relation, toItem: self.secondItem, attribute: self.secondAttribute, multiplier: multiplier, constant: self.constant)
        }
    }
    
    extension UIScreen {
    
        enum SizeType: CGFloat {
            case unknown = 0.0
            case iPhone4 = 960.0
            case iPhone5 = 1136.0
            case iPhone6 = 1334.0
            case iPhone6Plus = 1920.0
        }
    
        var sizeType: SizeType {
            let height = nativeBounds.height
            guard let sizeType = SizeType(rawValue: height) else { return .unknown }
            return sizeType
        }
    }
    

    第 2 步:将您的视图关联类连接为“CUIView”,如下图所示

    第 3 步: 给出圆角半径并设置背景,如下图。

    对于所有组 textField 和 textfield,您可以使用视图作为父视图和关联类来获得此结果。对于下划线,您可以使用最小高度的简单视图来获得所需的设计。

    【讨论】:

    • 感谢您提供解决方案,但这不仅适用于个人资料图片(第一个单元格)吗?我正在尝试在第二部分中创建单元格的效果,即文本字段。
    • 此解决方案不适用于 tableview。您只需实现 view 即可实现此目的。如果您想在第一个和最后一个单元格的第 2 部分下方的 tableview 单元格中创建它,请将视图作为背景并实施以下扩展以获得所需的视图。对于所有其他部分,只需将给定的类用于曲线视图。 (只是分享我的想法,希望它会有所帮助)。链接:stackoverflow.com/a/46542943/7643240
    猜你喜欢
    • 1970-01-01
    • 2017-04-28
    • 1970-01-01
    • 2018-08-06
    • 2017-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多