mirror of
https://github.com/material-components/material-components-ios.git
synced 2026-02-20 08:27:32 +08:00
227 lines
8.2 KiB
Swift
227 lines
8.2 KiB
Swift
// Copyright 2018-present the Material Components for iOS authors. All Rights Reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
import UIKit
|
|
import MaterialComponents.MaterialCards
|
|
import MaterialComponents.MaterialShapeLibrary
|
|
|
|
class CardView: MDCCard {
|
|
|
|
let contentView = UIView()
|
|
let label = UILabel()
|
|
let imageView = UIImageView()
|
|
|
|
var imageWidthConstraint: NSLayoutConstraint!
|
|
var shouldUpdateConstraints = true
|
|
|
|
override init(frame: CGRect) {
|
|
super.init(frame: frame)
|
|
commonCardViewInit()
|
|
}
|
|
|
|
required init?(coder aDecoder: NSCoder) {
|
|
super.init(coder: aDecoder)
|
|
commonCardViewInit()
|
|
}
|
|
|
|
func commonCardViewInit() {
|
|
self.layoutMargins = .zero
|
|
contentView.layoutMargins = .zero
|
|
contentView.translatesAutoresizingMaskIntoConstraints = false
|
|
contentView.isUserInteractionEnabled = false
|
|
self.addSubview(contentView)
|
|
|
|
label.text =
|
|
"abcde fghi jklm nopq rstuv wxyz abcd efgh ijkl mnop qrst uvw xyz abcde fghi jkl"
|
|
+ "nopq rstuv wxyz abcd efgh ijkl mnop qrst uvw xyz abcde fghi jklm nopq rstuv wxyz abcdefg"
|
|
label.numberOfLines = 0
|
|
label.translatesAutoresizingMaskIntoConstraints = false
|
|
self.contentView.addSubview(label)
|
|
|
|
imageView.clipsToBounds = true
|
|
imageView.contentMode = .scaleAspectFill
|
|
imageView.translatesAutoresizingMaskIntoConstraints = false
|
|
let bundle = Bundle(for: ShapedCardViewController.self)
|
|
imageView.image = UIImage(named: "sample-image", in: bundle, compatibleWith: nil)
|
|
self.contentView.addSubview(imageView)
|
|
setupConstraints()
|
|
}
|
|
|
|
func setupConstraints() {
|
|
contentView.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
|
|
contentView.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true
|
|
contentView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
|
|
contentView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
|
|
|
|
let margins = self.contentView.layoutMarginsGuide
|
|
label.leadingAnchor.constraint(equalTo: margins.leadingAnchor).isActive = true
|
|
label.trailingAnchor.constraint(equalTo: margins.trailingAnchor).isActive = true
|
|
imageView.centerXAnchor.constraint(equalTo: margins.centerXAnchor).isActive = true
|
|
|
|
imageView.topAnchor.constraint(equalTo: self.contentView.topAnchor).isActive = true
|
|
label.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor).isActive = true
|
|
|
|
imageView.bottomAnchor.constraint(equalTo: label.topAnchor).isActive = true
|
|
imageView.heightAnchor.constraint(equalTo: label.heightAnchor, multiplier: 1).isActive = true
|
|
|
|
imageWidthConstraint = imageView.widthAnchor.constraint(equalToConstant: 0)
|
|
imageWidthConstraint.isActive = true
|
|
}
|
|
|
|
override func layoutSubviews() {
|
|
super.layoutSubviews()
|
|
let shapeLayer = (self.layer as! MDCShapedShadowLayer).shapeLayer
|
|
contentView.layer.mask = shapeLayer
|
|
imageWidthConstraint.constant = shapeLayer.path!.boundingBox.size.width
|
|
}
|
|
|
|
}
|
|
|
|
class ShapedCardViewController: UIViewController {
|
|
var card = CardView()
|
|
var primarySlider = UISlider()
|
|
var secondarySlider = UISlider()
|
|
|
|
override func viewDidLoad() {
|
|
view.backgroundColor = .white
|
|
super.viewDidLoad()
|
|
|
|
initialShape()
|
|
|
|
view.addSubview(card)
|
|
view.addSubview(primarySlider)
|
|
view.addSubview(secondarySlider)
|
|
|
|
card.translatesAutoresizingMaskIntoConstraints = false
|
|
card.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor, constant: 20).isActive = true
|
|
card.bottomAnchor.constraint(equalTo: primarySlider.topAnchor, constant: -20).isActive = true
|
|
card.leadingAnchor.constraint(equalTo: view.layoutMarginsGuide.leadingAnchor).isActive = true
|
|
card.trailingAnchor.constraint(equalTo: view.layoutMarginsGuide.trailingAnchor).isActive = true
|
|
|
|
primarySlider.translatesAutoresizingMaskIntoConstraints = false
|
|
primarySlider.bottomAnchor.constraint(
|
|
equalTo: secondarySlider.topAnchor,
|
|
constant: -20
|
|
).isActive = true
|
|
primarySlider.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
|
|
primarySlider.widthAnchor.constraint(
|
|
equalTo: view.widthAnchor,
|
|
multiplier: 0.5,
|
|
constant: 0
|
|
).isActive = true
|
|
primarySlider.addTarget(
|
|
self,
|
|
action: #selector(didChangeSliderValue(slider:)),
|
|
for: .valueChanged)
|
|
|
|
secondarySlider.translatesAutoresizingMaskIntoConstraints = false
|
|
secondarySlider.bottomAnchor.constraint(
|
|
equalTo: view.bottomAnchor,
|
|
constant: -20
|
|
).isActive = true
|
|
secondarySlider.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
|
|
secondarySlider.widthAnchor.constraint(
|
|
equalTo: view.widthAnchor,
|
|
multiplier: 0.5,
|
|
constant: 0
|
|
).isActive = true
|
|
secondarySlider.addTarget(
|
|
self,
|
|
action: #selector(didChangeSliderValue(slider:)),
|
|
for: .valueChanged)
|
|
|
|
let barButton = UIBarButtonItem(
|
|
title: "Change Shape",
|
|
style: .plain,
|
|
target: self,
|
|
action: #selector(changeShape))
|
|
self.navigationItem.rightBarButtonItem = barButton
|
|
}
|
|
|
|
override func viewWillLayoutSubviews() {
|
|
super.viewWillLayoutSubviews()
|
|
primarySlider.maximumValue = Float(min(card.bounds.width, card.bounds.height) / 2)
|
|
primarySlider.sendActions(for: .valueChanged)
|
|
secondarySlider.maximumValue = Float(min(card.bounds.width, card.bounds.height) / 2)
|
|
secondarySlider.sendActions(for: .valueChanged)
|
|
}
|
|
|
|
@objc func didChangeSliderValue(slider: UISlider) {
|
|
if let shape = card.shapeGenerator as? MDCRectangleShapeGenerator {
|
|
if slider == primarySlider {
|
|
let cutCornerTreatment = MDCCutCornerTreatment(cut: CGFloat(slider.value))
|
|
shape.setCorners(cutCornerTreatment)
|
|
} else if slider == secondarySlider {
|
|
let triangleEdgeTreatment = MDCTriangleEdgeTreatment(
|
|
size: CGFloat(slider.value),
|
|
style: MDCTriangleEdgeStyleCut)
|
|
shape.setEdges(triangleEdgeTreatment)
|
|
}
|
|
card.setNeedsLayout()
|
|
}
|
|
}
|
|
|
|
@objc func changeShape() {
|
|
primarySlider.isHidden = true
|
|
secondarySlider.isHidden = true
|
|
switch card.shapeGenerator {
|
|
case is MDCRectangleShapeGenerator:
|
|
let shapeGenerator = MDCCurvedRectShapeGenerator(
|
|
cornerSize: CGSize(
|
|
width: 50,
|
|
height: 100))
|
|
card.shapeGenerator = shapeGenerator
|
|
card.contentView.layoutMargins = UIEdgeInsets(top: 0, left: 40, bottom: 0, right: 40)
|
|
case is MDCCurvedRectShapeGenerator:
|
|
let shapeGenerator = MDCPillShapeGenerator()
|
|
card.shapeGenerator = shapeGenerator
|
|
card.contentView.layoutMargins = UIEdgeInsets(top: 0, left: 80, bottom: 0, right: 80)
|
|
case is MDCPillShapeGenerator:
|
|
let shapeGenerator = MDCSlantedRectShapeGenerator()
|
|
shapeGenerator.slant = 40
|
|
card.shapeGenerator = shapeGenerator
|
|
card.contentView.layoutMargins = UIEdgeInsets(top: 0, left: 40, bottom: 0, right: 40)
|
|
case is MDCSlantedRectShapeGenerator:
|
|
fallthrough
|
|
default:
|
|
initialShape()
|
|
}
|
|
card.setNeedsLayout()
|
|
}
|
|
|
|
func initialShape() {
|
|
primarySlider.isHidden = false
|
|
secondarySlider.isHidden = false
|
|
|
|
let shapeGenerator = MDCRectangleShapeGenerator()
|
|
let cutCornerTreatment = MDCCutCornerTreatment(cut: 0)
|
|
shapeGenerator.setCorners(cutCornerTreatment)
|
|
let triangleEdgeTreatment = MDCTriangleEdgeTreatment(size: 0, style: MDCTriangleEdgeStyleCut)
|
|
shapeGenerator.setEdges(triangleEdgeTreatment)
|
|
card.shapeGenerator = shapeGenerator
|
|
card.contentView.layoutMargins = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)
|
|
}
|
|
}
|
|
|
|
extension ShapedCardViewController {
|
|
|
|
@objc class func catalogMetadata() -> [String: Any] {
|
|
return [
|
|
"breadcrumbs": ["Cards", "Shaped Card"],
|
|
"primaryDemo": false,
|
|
"presentable": false,
|
|
]
|
|
}
|
|
}
|