見上げましたが、UIViewに内側の影を追加する方法が見つかりませんでした。Swiftの場合は上(上から下)だけです。 Swiftで内側の円を追加する最良の方法は何ですか?
編集:SOでいくつかの質問と回答を見つけましたが、これらはobj-cにあるか、非常に複雑に見えます。
私が達成したいこと:
ここに、純粋なSwift私が作り上げたバージョンがあります:
public class EdgeShadowLayer: CAGradientLayer {
public enum Edge {
case Top
case Left
case Bottom
case Right
}
public init(forView view: UIView,
Edge: Edge = Edge.Top,
shadowRadius radius: CGFloat = 20.0,
toColor: UIColor = UIColor.white,
fromColor: UIColor = UIColor.black) {
super.init()
self.colors = [fromColor.cgColor, toColor.cgColor]
self.shadowRadius = radius
let viewFrame = view.frame
switch Edge {
case .Top:
startPoint = CGPoint(x: 0.5, y: 0.0)
endPoint = CGPoint(x: 0.5, y: 1.0)
self.frame = CGRect(x: 0.0, y: 0.0, width: viewFrame.width, height: shadowRadius)
case .Bottom:
startPoint = CGPoint(x: 0.5, y: 1.0)
endPoint = CGPoint(x: 0.5, y: 0.0)
self.frame = CGRect(x: 0.0, y: viewFrame.height - shadowRadius, width: viewFrame.width, height: shadowRadius)
case .Left:
startPoint = CGPoint(x: 0.0, y: 0.5)
endPoint = CGPoint(x: 1.0, y: 0.5)
self.frame = CGRect(x: 0.0, y: 0.0, width: shadowRadius, height: viewFrame.height)
case .Right:
startPoint = CGPoint(x: 1.0, y: 0.5)
endPoint = CGPoint(x: 0.0, y: 0.5)
self.frame = CGRect(x: viewFrame.width - shadowRadius, y: 0.0, width: shadowRadius, height: viewFrame.height)
}
}
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
それを使用するには、
let topShadow = EdgeShadowLayer(forView: targetView, Edge: .Top)
targetView.layer.addSublayer(topShadow)
デフォルトでは、深さ20ポイントの黒から白へのグラデーションになっています。
サンプルのUIViewController
を含む完全なコードは、ビューの4隅すべてで影を切り替えることができます。 https://github.com/jrtibbetts/Tenebrae にあります。 EdgeShadowLayer
もかなり徹底的に文書化しました。
Objective-Cを使用して、UIViewに内部シャドウを実装しました。コードをSwiftに翻訳しようとしています。私の貧しいSwift構文を許してください
uIView.didMoveToSuperviewで以下の関数を呼び出すことができます
func drawShadow() {
if nil == self.shadowLayer {
let size = self.frame.size
self.clipsToBounds = true
let layer: CALayer = CALayer()
layer.backgroundColor = UIColor.lightGrayColor().CGColor
layer.position = CGPointMake(size.width / 2, -size.height / 2 + 0.5)
layer.bounds = CGRectMake(0, 0, size.width, size.height)
layer.shadowColor = UIColor.darkGrayColor().CGColor
layer.shadowOffset = CGSizeMake(0.5, 0.5)
layer.shadowOpacity = 0.8
layer.shadowRadius = 5.0
self.shadowLayer = layer
self.layer.addSublayer(layer)
}
}
toColor
としてclearを使用して@ anoop4realによって行われた変更を微調整し、デフォルトで0.0に設定された不透明度を除き、デフォルトを含むCALayerのシャドウ設定とインターフェイスをよりインラインにしました。最も自然に見えるため、デフォルトの0.6を使用しました。
extension UIView {
func addShadow(to edges: [UIRectEdge], radius: CGFloat = 3.0, opacity: Float = 0.6, color: CGColor = UIColor.black.cgColor) {
let fromColor = color
let toColor = UIColor.clear.cgColor
let viewFrame = self.frame
for Edge in edges {
let gradientLayer = CAGradientLayer()
gradientLayer.colors = [fromColor, toColor]
gradientLayer.opacity = opacity
switch Edge {
case .top:
gradientLayer.startPoint = CGPoint(x: 0.5, y: 0.0)
gradientLayer.endPoint = CGPoint(x: 0.5, y: 1.0)
gradientLayer.frame = CGRect(x: 0.0, y: 0.0, width: viewFrame.width, height: radius)
case .bottom:
gradientLayer.startPoint = CGPoint(x: 0.5, y: 1.0)
gradientLayer.endPoint = CGPoint(x: 0.5, y: 0.0)
gradientLayer.frame = CGRect(x: 0.0, y: viewFrame.height - radius, width: viewFrame.width, height: radius)
case .left:
gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.5)
gradientLayer.endPoint = CGPoint(x: 1.0, y: 0.5)
gradientLayer.frame = CGRect(x: 0.0, y: 0.0, width: radius, height: viewFrame.height)
case .right:
gradientLayer.startPoint = CGPoint(x: 1.0, y: 0.5)
gradientLayer.endPoint = CGPoint(x: 0.0, y: 0.5)
gradientLayer.frame = CGRect(x: viewFrame.width - radius, y: 0.0, width: radius, height: viewFrame.height)
default:
break
}
self.layer.addSublayer(gradientLayer)
}
}
func removeAllShadows() {
if let sublayers = self.layer.sublayers, !sublayers.isEmpty {
for sublayer in sublayers {
sublayer.removeFromSuperlayer()
}
}
}
}
上部のビューはデフォルト設定であり、下部はより明確に表示するために半径5.0を使用しています。
view1.addShadow([.top, .bottom, .left, .right])
view2.addShadow([.top, .bottom, .left, .right], radius: 5.0)
view2.backgroundColor = .orange
私はSwift 3で@NRitHソリューションを書き直し、それを少しリファクタリングしました:
final class SideShadowLayer: CAGradientLayer {
enum Side {
case top,
bottom,
left,
right
}
init(frame: CGRect, side: Side, shadowWidth: CGFloat,
fromColor: UIColor = .black,
toColor: UIColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0),
opacity: Float = 0.5) {
super.init()
colors = [fromColor.cgColor, toColor.cgColor]
self.opacity = opacity
switch side {
case .bottom:
startPoint = CGPoint(x: 0.5, y: 1.0)
endPoint = CGPoint(x: 0.5, y: 0.0)
self.frame = CGRect(x: 0, y: frame.height - shadowWidth, width: frame.width, height: shadowWidth)
case .top:
startPoint = CGPoint(x: 0.5, y: 0.0)
endPoint = CGPoint(x: 0.5, y: 1.0)
self.frame = CGRect(x: 0, y: 0, width: frame.width, height: shadowWidth)
case .left:
startPoint = CGPoint(x: 0.0, y: 0.5)
endPoint = CGPoint(x: 1.0, y: 0.5)
self.frame = CGRect(x: 0, y: 0, width: shadowWidth, height: frame.height)
case .right:
startPoint = CGPoint(x: 1.0, y: 0.5)
endPoint = CGPoint(x: 0.0, y: 0.5)
self.frame = CGRect(x: frame.width - shadowWidth, y: 0, width: shadowWidth, height: frame.height)
}
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
@NRitHの答えを更新し、拡張機能も変更して、複数のエッジを一度に操作できるようにしました
使用法
myview.addShadow(to: [.top,.bottom], radius: 15.0)
extension UIView{
func addShadow(to edges:[UIRectEdge], radius:CGFloat){
let toColor = UIColor(colorLiteralRed: 235.0/255.0, green: 235.0/255.0, blue: 235.0/255.0, alpha: 1.0)
let fromColor = UIColor(colorLiteralRed: 188.0/255.0, green: 188.0/255.0, blue: 188.0/255.0, alpha: 1.0)
// Set up its frame.
let viewFrame = self.frame
for Edge in edges{
let gradientlayer = CAGradientLayer()
gradientlayer.colors = [fromColor.cgColor,toColor.cgColor]
gradientlayer.shadowRadius = radius
switch Edge {
case UIRectEdge.top:
gradientlayer.startPoint = CGPoint(x: 0.5, y: 0.0)
gradientlayer.endPoint = CGPoint(x: 0.5, y: 1.0)
gradientlayer.frame = CGRect(x: 0.0, y: 0.0, width: viewFrame.width, height: gradientlayer.shadowRadius)
case UIRectEdge.bottom:
gradientlayer.startPoint = CGPoint(x: 0.5, y: 1.0)
gradientlayer.endPoint = CGPoint(x: 0.5, y: 0.0)
gradientlayer.frame = CGRect(x: 0.0, y: viewFrame.height - gradientlayer.shadowRadius, width: viewFrame.width, height: gradientlayer.shadowRadius)
case UIRectEdge.left:
gradientlayer.startPoint = CGPoint(x: 0.0, y: 0.5)
gradientlayer.endPoint = CGPoint(x: 1.0, y: 0.5)
gradientlayer.frame = CGRect(x: 0.0, y: 0.0, width: gradientlayer.shadowRadius, height: viewFrame.height)
case UIRectEdge.right:
gradientlayer.startPoint = CGPoint(x: 1.0, y: 0.5)
gradientlayer.endPoint = CGPoint(x: 0.0, y: 0.5)
gradientlayer.frame = CGRect(x: viewFrame.width - gradientlayer.shadowRadius, y: 0.0, width: gradientlayer.shadowRadius, height: viewFrame.height)
default:
break
}
self.layer.addSublayer(gradientlayer)
}
}
func removeAllSublayers(){
if let sublayers = self.layer.sublayers, !sublayers.isEmpty{
for sublayer in sublayers{
sublayer.removeFromSuperlayer()
}
}
}
}
これは、ビューに内部シャドウを追加する方法です。
func addInerShadowLayer()
{
clipsToBounds = true
let shapeLayer = CAShapeLayer()
let path = UIBezierPath(roundedRect: CGRect(x: -10, y: -self.frame.height/2, width: self.frame.width + 20, height: self.frame.height*2), cornerRadius: 0)
let buttonPath = UIBezierPath(roundedRect: CGRect(x: -1, y: -1, width: self.frame.width+2, height: self.frame.height+2), cornerRadius: self.frame.height/2)
path.append(buttonPath.reversing())
shapeLayer.path = path.cgPath
self.layer.addSublayer(shapeLayer)
shapeLayer.shadowOpacity = 0.1
shapeLayer.shadowColor = UIColor.red.cgColor
shapeLayer.shadowOffset = CGSize(width: 0, height: 4)
shapeLayer.shadowRadius = 3
}