UIView iOS Swift下的多个阴影

时间:2019-03-21 17:05:49

标签: ios swift uiview calayer shadow

我正在尝试制作一个带有2个彩色阴影的圆角UIButton。为什么是红色(此时还覆盖了按钮的蓝色“阴影”层?如何使阴影在按钮画布下方)。我认为这有助于插入子层,而不仅仅是添加子层。

Shadows are above button

我已经在操场上说明了这个问题

import UIKit
import PlaygroundSupport

这是我正在尝试实施的按钮

class PrimaryButton: UIButton {
    required init(text: String = "Test 1", hasShadow: Bool = true) {
        super.init(frame: .zero)
        setTitle(text, for: .normal)
        backgroundColor = UIColor.blue
        layer.cornerRadius = 48 / 2
        layer.masksToBounds = false
        if hasShadow {
            insertShadow()
        }
    }

    fileprivate func insertShadow() {
        let layer2 = CALayer(layer: layer), layer3 = CALayer(layer: layer)
        layer2.applySketchShadow(color: UIColor.red, alpha: 0.5, x: 0, y: 15, blur: 35, spread: -10)
        layer3.applySketchShadow(color: UIColor.blue, alpha: 0.5, x: 0, y: 10, blur: 21, spread: -9)
        layer.insertSublayer(layer2, at: 0)
        layer.insertSublayer(layer3, at: 0)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        layer.sublayers?.forEach { (sublayer) in
            sublayer.shadowPath = UIBezierPath(rect: bounds).cgPath
        }
    }
}

这是一个扩展,可帮助添加Sketch规范中的阴影:

extension CALayer {
    func applySketchShadow(
        color: UIColor = .black,
        alpha: Float = 0.5,
        x: CGFloat = 0,
        y: CGFloat = 2,
        blur: CGFloat = 4,
        spread: CGFloat = 0)
    {
        shadowColor = color.cgColor
        shadowOpacity = alpha
        shadowOffset = CGSize(width: x, height: y)
        shadowRadius = blur / 2.0
        if spread == 0 {
            shadowPath = nil
        } else {
            let dx = -spread
            let rect = bounds.insetBy(dx: dx, dy: dx)
            shadowPath = UIBezierPath(rect: rect).cgPath
        }
        masksToBounds = false
    }
}


class MyViewController : UIViewController {
    override func loadView() {
        let view = UIView()
        view.backgroundColor = .white

        let button = PrimaryButton()
        button.frame = CGRect(x: 150, y: 200, width: 200, height: 48)
        view.addSubview(button)
        self.view = view
    }
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()

3 个答案:

答案 0 :(得分:2)

在我看来是合法的。 <%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Site.master.cs" Inherits="WebApplication2.SiteMaster" %> <!DOCTYPE html> <html lang="en"> <head runat="server"> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title><%: Page.Title %> - My ASP.NET Application</title> <asp:PlaceHolder runat="server"> <%: Scripts.Render("~/bundles/modernizr") %> </asp:PlaceHolder> <webopt:bundlereference runat="server" path="~/Content/css" /> <link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" /> </head> <body> <form runat="server"> <asp:ScriptManager runat="server"> <Scripts> <%--To learn more about bundling scripts in ScriptManager see https://go.microsoft.com/fwlink/?LinkID=301884 --%> <%--Framework Scripts--%> <asp:ScriptReference Name="MsAjaxBundle" /> <asp:ScriptReference Name="jquery" /> <asp:ScriptReference Name="bootstrap" /> <asp:ScriptReference Name="WebForms.js" Assembly="System.Web" Path="~/Scripts/WebForms/WebForms.js" /> <asp:ScriptReference Name="WebUIValidation.js" Assembly="System.Web" Path="~/Scripts/WebForms/WebUIValidation.js" /> <asp:ScriptReference Name="MenuStandards.js" Assembly="System.Web" Path="~/Scripts/WebForms/MenuStandards.js" /> <asp:ScriptReference Name="GridView.js" Assembly="System.Web" Path="~/Scripts/WebForms/GridView.js" /> <asp:ScriptReference Name="DetailsView.js" Assembly="System.Web" Path="~/Scripts/WebForms/DetailsView.js" /> <asp:ScriptReference Name="TreeView.js" Assembly="System.Web" Path="~/Scripts/WebForms/TreeView.js" /> <asp:ScriptReference Name="WebParts.js" Assembly="System.Web" Path="~/Scripts/WebForms/WebParts.js" /> <asp:ScriptReference Name="Focus.js" Assembly="System.Web" Path="~/Scripts/WebForms/Focus.js" /> <asp:ScriptReference Name="WebFormsBundle" /> <%--Site Scripts--%> </Scripts> </asp:ScriptManager> <div class="navbar navbar-inverse navbar-fixed-top"> <div class="container"> <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" runat="server" href="~/">Application name</a> </div> <div class="navbar-collapse collapse"> <ul class="nav navbar-nav"> <li><a runat="server" href="~/">Home</a></li> <li><a runat="server" href="~/About">About</a></li> <li><a runat="server" href="~/Contact">Contact</a></li> </ul> <asp:LoginView runat="server" ViewStateMode="Disabled"> <AnonymousTemplate> <ul class="nav navbar-nav navbar-right"> <li><a runat="server" href="~/Account/Register">Register</a></li> <li><a runat="server" href="~/Account/Login">Log in</a></li> </ul> </AnonymousTemplate> <LoggedInTemplate> <ul class="nav navbar-nav navbar-right"> <li><a runat="server" href="~/Account/Manage" title="Manage your account">Hello, <%: Context.User.Identity.GetUserName() %> !</a></li> <li> <asp:LoginStatus runat="server" LogoutAction="Redirect" LogoutText="Log off" LogoutPageUrl="~/" OnLoggingOut="Unnamed_LoggingOut" /> </li> </ul> </LoggedInTemplate> </asp:LoginView> </div> </div> </div> <div class="container body-content"> <asp:ContentPlaceHolder ID="MainContent" runat="server"> </asp:ContentPlaceHolder> <hr /> <footer> <p>&copy; <%: DateTime.Now.Year %> - My ASP.NET Application</p> </footer> </div> </form> </body> </html> layer1是按钮层的子层。

您可以添加第三层作为背景。这是一个基于您的代码的示例:

layer2

请注意,我将大多数代码放在class PrimaryButton: UIButton { let layer1 = CALayer(), layer2 = CALayer(), layer3 = CALayer() override func layoutSubviews() { super.layoutSubviews() layer1.backgroundColor = UIColor.blue.cgColor layer1.cornerRadius = 48 / 2 [layer1, layer2, layer3].forEach { $0.masksToBounds = false $0.frame = layer.bounds layer.insertSublayer($0, at: 0) } layer2.applySketchShadow(color: UIColor.red, alpha: 0.5, x: 0, y: 15, blur: 35, spread: -10) layer3.applySketchShadow(color: UIColor.blue, alpha: 0.5, x: 0, y: 10, blur: 21, spread: -9) } } 内,因为您的大多数方法都使用按钮的实际边界。

答案 1 :(得分:1)

将您的插入内容更改为:

words = re.findall(r'\w+|\S+', text)

应该这样做。

答案 2 :(得分:0)

另一种方法是在不更改班级的情况下添加双按钮。

    let button = PrimaryButton()
    button.frame = CGRect(x: 150, y: 200, width: 200, height: 48)
    button.backgroundColor = UIColor.clear
    view.addSubview(button)
    self.view = view
    let button1 = PrimaryButton()
    button1.frame = CGRect(x: 0, y: 0, width: 200, height: 48)
    button.addSubview(button1)
    button1.layer.sublayers?.forEach{$0.removeFromSuperlayer()}