我正在使用此代码制作自定义相机裁剪:
UIImagePickerController editing view circle overlay
这在相机胶卷中完美无效,但不拍照
如果我更改[navigationController.viewControllers count] == 3 - > [navigationController.viewControllers count] == 1也适用于相机,但不适用于下一个视图(预览视图,您接受使用该照片)
有人帮助我吗??
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex{
if (buttonIndex == 0) {
NSLog(@"Camara");
UIImagePickerController * imagePicker = [[UIImagePickerController alloc] init];
imagePicker.allowsEditing = YES;
imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
imagePicker.delegate = self;
self.isCamera = YES;
[self presentViewController:imagePicker animated:YES completion:nil];
}else{
NSLog(@"Carrete");
UIImagePickerController *imagePickerController = [[UIImagePickerController alloc]init];
imagePickerController.allowsEditing = YES;
imagePickerController.delegate = self;
imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
self.isCamera = NO;
[self presentViewController:imagePickerController animated:YES completion:nil];
}
}
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated{
if (self.isCamera) {
if ([navigationController.viewControllers count] == 1)
{
CGFloat screenHeight = [[UIScreen mainScreen] bounds].size.height;
UIView *plCropOverlay = [[[viewController.view.subviews objectAtIndex:1]subviews] objectAtIndex:0];
plCropOverlay.hidden = YES;
int position = 0;
if (screenHeight == 568)
{
position = 124;
}
else
{
position = 80;
}
CAShapeLayer *circleLayer = [CAShapeLayer layer];
UIBezierPath *path2 = [UIBezierPath bezierPathWithOvalInRect:
CGRectMake(0.0f, position, 320.0f, 320.0f)];
[path2 setUsesEvenOddFillRule:YES];
[circleLayer setPath:[path2 CGPath]];
[circleLayer setFillColor:[[UIColor clearColor] CGColor]];
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, 320, screenHeight-72) cornerRadius:0];
[path appendPath:path2];
[path setUsesEvenOddFillRule:YES];
CAShapeLayer *fillLayer = [CAShapeLayer layer];
fillLayer.path = path.CGPath;
fillLayer.fillRule = kCAFillRuleEvenOdd;
fillLayer.fillColor = [UIColor blackColor].CGColor;
fillLayer.opacity = 0.8;
[viewController.view.layer addSublayer:fillLayer];
UILabel *moveLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 10, 320, 50)];
[moveLabel setText:@"Move and Scale"];
[moveLabel setTextAlignment:NSTextAlignmentCenter];
[moveLabel setTextColor:[UIColor whiteColor]];
[viewController.view addSubview:moveLabel];
}
}else{
if ([navigationController.viewControllers count] == 3)
{
CGFloat screenHeight = [[UIScreen mainScreen] bounds].size.height;
UIView *plCropOverlay = [[[viewController.view.subviews objectAtIndex:1]subviews] objectAtIndex:0];
plCropOverlay.hidden = YES;
int position = 0;
if (screenHeight == 568)
{
position = 124;
}
else
{
position = 80;
}
CAShapeLayer *circleLayer = [CAShapeLayer layer];
UIBezierPath *path2 = [UIBezierPath bezierPathWithOvalInRect:
CGRectMake(0.0f, position, 320.0f, 320.0f)];
[path2 setUsesEvenOddFillRule:YES];
[circleLayer setPath:[path2 CGPath]];
[circleLayer setFillColor:[[UIColor clearColor] CGColor]];
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, 320, screenHeight-72) cornerRadius:0];
[path appendPath:path2];
[path setUsesEvenOddFillRule:YES];
CAShapeLayer *fillLayer = [CAShapeLayer layer];
fillLayer.path = path.CGPath;
fillLayer.fillRule = kCAFillRuleEvenOdd;
fillLayer.fillColor = [UIColor blackColor].CGColor;
fillLayer.opacity = 0.8;
[viewController.view.layer addSublayer:fillLayer];
UILabel *moveLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 10, 320, 50)];
[moveLabel setText:@"Move and Scale"];
[moveLabel setTextAlignment:NSTextAlignmentCenter];
[moveLabel setTextColor:[UIColor whiteColor]];
[viewController.view addSubview:moveLabel];
}
}
}
答案 0 :(得分:1)
我为此花费了很长时间,但终于有了一个可行的解决方案。
我用Swift或SwiftUI编写代码已有很长时间了,我绝对欢迎大家提出改进代码的意见。在某些地方,我留下了一些您可以取消注释的调试代码。将我的脑袋缠在数学上比能干的,经过深思熟虑的方法要花更多的尝试和错误!
此代码中的缺点:第一,最好从ContentView()打开Impage选择器,然后显示我的自定义视图。我不知道该怎么做。 第二,如果ContentView()中已经有图像,则最好在自定义视图中填充该图像。但是,然后,用户可能希望能够获得“原始”图像并对其进行移动和缩放。这将需要更多的答案。即,您是否要将原始照片保存在某些url /应用程序文件夹中以及裁剪的版本中?甚至保存带有原始图片和重新创建裁剪视图所需的CGRect的字典? 第三。如果所选照片恰好等于屏幕大小(屏幕截图),则似乎存在错误;它可以缩放得太低。
在一个新的SwiftUI生命周期应用程序中,我具有以下SwiftUI视图:
这是您将得到的:
我还使用这种至关重要的解决方案进行裁剪:
最后,我的一些代码访问系统UIcolors,所以我在其中使用扩展名
import SwiftUI
struct ContentView: View {
@State private var isShowingPhotoSelectionSheet = false
@State private var finalImage: UIImage?
@State private var inputImage: UIImage?
var body: some View {
VStack {
if finalImage != nil {
Image(uiImage: finalImage!)
.resizable()
.frame(width: 100, height: 100)
.scaledToFill()
.aspectRatio(contentMode: .fit)
.clipShape(Circle())
.shadow(radius: 4)
} else {
Image(systemName: "person.crop.circle.fill")
.resizable()
.scaledToFill()
.frame(width: 100, height: 100)
.aspectRatio(contentMode: .fit)
.foregroundColor(.systemGray2)
}
Button (action: {
self.isShowingPhotoSelectionSheet = true
}, label: {
Text("Change photo")
.foregroundColor(.systemRed)
.font(.footnote)
})
}
.background(Color.systemBackground)
.statusBar(hidden: isShowingPhotoSelectionSheet)
.fullScreenCover(isPresented: $isShowingPhotoSelectionSheet, onDismiss: loadImage) {
ImageMoveAndScaleSheet(croppedImage: $finalImage)
}
}
func loadImage() {
guard let inputImage = inputImage else { return }
finalImage = inputImage
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
在Change photo
上单击/点击会弹出下一个视图:
这是一个全屏模式,在打开时会隐藏状态栏。
import SwiftUI
struct ImageMoveAndScaleSheet: View {
@Environment(\.presentationMode) var presentationMode
@State private var isShowingImagePicker = false
///The croped image is what will will send back to the parent view.
///It should be the part of the image in the square defined by the
///cutout circle's diamter. See below, the cutout circle has an "inset" value
///which can be changed.
@Binding var croppedImage: UIImage?
///The input image is received from the ImagePicker.
///We will need to calculate and refer to its aspectr ratio in the functions.
@State private var inputImage: UIImage?
@State private var inputW: CGFloat = 750.5556577
@State private var inputH: CGFloat = 1336.5556577
@State private var theAspectRatio: CGFloat = 0.0
///The profileImage is what wee see on this view. When added from the
///ImapgePicker, it will be sized to fit the screen,
///meaning either its width will match the width of the device's screen,
///or its height will match the height of the device screen.
///This is not suitable for landscape mode or for iPads.
@State private var profileImage: Image?
@State private var profileW: CGFloat = 0.0
@State private var profileH: CGFloat = 0.0
///Zoom and Drag ...
@State private var currentAmount: CGFloat = 0
@State private var finalAmount: CGFloat = 1
@State private var currentPosition: CGSize = .zero
@State private var newPosition: CGSize = .zero
///We track of amount the image is moved for use in functions below.
@State private var horizontalOffset: CGFloat = 0.0
@State private var verticalOffset: CGFloat = 0.0
var body: some View {
ZStack {
ZStack {
Color.black.opacity(0.8)
if profileImage != nil {
profileImage?
.resizable()
.scaleEffect(finalAmount + currentAmount)
.scaledToFill()
.aspectRatio(contentMode: .fit)
.offset(x: self.currentPosition.width, y: self.currentPosition.height)
} else {
Image(systemName: "person.crop.circle.fill")
.resizable()
.scaleEffect(finalAmount + currentAmount)
.scaledToFill()
.aspectRatio(contentMode: .fit)
.foregroundColor(.systemGray2)
}
}
Rectangle()
.fill(Color.black).opacity(0.55)
.mask(HoleShapeMask().fill(style: FillStyle(eoFill: true)))
VStack {
Text((profileImage != nil) ? "Move and Scale" : "Select a Photo by tapping the icon below")
.foregroundColor(.white)
.padding(.top, 50)
Spacer()
HStack{
ZStack {
HStack {
Button(
action: {presentationMode.wrappedValue.dismiss()},
label: { Text("Cancel") })
Spacer()
Button(
action: {
self.save()
presentationMode.wrappedValue.dismiss()
})
{ Text("Save") }
.opacity((profileImage != nil) ? 1.0 : 0.2)
.disabled((profileImage != nil) ? false: true)
}
.padding(.horizontal)
.foregroundColor(.white)
Image(systemName: "circle.fill")
.font(.custom("system", size: 45))
.opacity(0.9)
.foregroundColor(.white)
Image(systemName: "photo.on.rectangle")
.imageScale(.medium)
.foregroundColor(.black)
.onTapGesture {
isShowingImagePicker = true
}
}
.padding(.bottom, 5)
}
}
.padding()
}
.edgesIgnoringSafeArea(.all)
//MARK: - Gestures
.gesture(
MagnificationGesture()
.onChanged { amount in
self.currentAmount = amount - 1
// repositionImage()
}
.onEnded { amount in
self.finalAmount += self.currentAmount
self.currentAmount = 0
repositionImage()
}
)
.simultaneousGesture(
DragGesture()
.onChanged { value in
self.currentPosition = CGSize(width: value.translation.width + self.newPosition.width, height: value.translation.height + self.newPosition.height)
}
.onEnded { value in
self.currentPosition = CGSize(width: value.translation.width + self.newPosition.width, height: value.translation.height + self.newPosition.height)
self.newPosition = self.currentPosition
repositionImage()
}
)
.simultaneousGesture(
TapGesture(count: 2)
.onEnded({
resetImageOriginAndScale()
})
)
.sheet(isPresented: $isShowingImagePicker, onDismiss: loadImage) {
ImagePicker(image: self.$inputImage)
.accentColor(Color.systemRed)
}
}
//MARK: - functions
private func HoleShapeMask() -> Path {
let rect = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
let insetRect = CGRect(x: inset, y: inset, width: UIScreen.main.bounds.width - ( inset * 2 ), height: UIScreen.main.bounds.height - ( inset * 2 ))
var shape = Rectangle().path(in: rect)
shape.addPath(Circle().path(in: insetRect))
return shape
}
///Called when the ImagePicker is dismissed.
///We want to measure the image receoived and determine the aspect ratio.
private func loadImage() {
guard let inputImage = inputImage else { return }
let w = inputImage.size.width
let h = inputImage.size.height
profileImage = Image(uiImage: inputImage)
inputW = w
inputH = h
theAspectRatio = w / h
resetImageOriginAndScale()
}
///The profileImage will size to fit the screen.
///But we need to know the width and height
///to set the related @State variables.
///Douobke-tpping the image will also set it
///as it was sized originally upon loading.
private func resetImageOriginAndScale() {
withAnimation(.easeInOut){
if theAspectRatio >= screenAspect {
profileW = UIScreen.main.bounds.width
profileH = profileW / theAspectRatio
} else {
profileH = UIScreen.main.bounds.height
profileW = profileH * theAspectRatio
}
currentAmount = 0
finalAmount = 1
currentPosition = .zero
newPosition = .zero
}
}
private func repositionImage() {
//Screen width
let w = UIScreen.main.bounds.width
if theAspectRatio > screenAspect {
profileW = UIScreen.main.bounds.width * finalAmount
profileH = profileW / theAspectRatio
} else {
profileH = UIScreen.main.bounds.height * finalAmount
profileW = profileH * theAspectRatio
}
horizontalOffset = (profileW - w ) / 2
verticalOffset = ( profileH - w ) / 2
///Keep the user from zooming too far in. Adjust as required by the individual project.
if finalAmount > 4.0 {
withAnimation{
finalAmount = 4.0
}
}
///The following if statements keep the image filling the circle cutout.
if profileW >= UIScreen.main.bounds.width {
if newPosition.width > horizontalOffset {
withAnimation(.easeInOut) {
newPosition = CGSize(width: horizontalOffset + inset, height: newPosition.height)
currentPosition = CGSize(width: horizontalOffset + inset, height: currentPosition.height)
}
}
if newPosition.width < ( horizontalOffset * -1) {
withAnimation(.easeInOut){
newPosition = CGSize(width: ( horizontalOffset * -1) - inset, height: newPosition.height)
currentPosition = CGSize(width: ( horizontalOffset * -1 - inset), height: currentPosition.height)
}
}
} else {
withAnimation(.easeInOut) {
newPosition = CGSize(width: 0, height: newPosition.height)
currentPosition = CGSize(width: 0, height: newPosition.height)
}
}
if profileH >= UIScreen.main.bounds.width {
if newPosition.height > verticalOffset {
withAnimation(.easeInOut){
newPosition = CGSize(width: newPosition.width, height: verticalOffset + inset)
currentPosition = CGSize(width: newPosition.width, height: verticalOffset + inset)
}
}
if newPosition.height < ( verticalOffset * -1) {
withAnimation(.easeInOut){
newPosition = CGSize(width: newPosition.width, height: ( verticalOffset * -1) - inset)
currentPosition = CGSize(width: newPosition.width, height: ( verticalOffset * -1) - inset)
}
}
} else {
withAnimation (.easeInOut){
newPosition = CGSize(width: newPosition.width, height: 0)
currentPosition = CGSize(width: newPosition.width, height: 0)
}
}
if profileW <= UIScreen.main.bounds.width && theAspectRatio > screenAspect {
resetImageOriginAndScale()
}
if profileH <= UIScreen.main.bounds.height && theAspectRatio < screenAspect {
resetImageOriginAndScale()
}
}
private func save() {
let scale = (inputImage?.size.width)! / profileW
let xPos = ( ( ( profileW - UIScreen.main.bounds.width ) / 2 ) + inset + ( currentPosition.width * -1 ) ) * scale
let yPos = ( ( ( profileH - UIScreen.main.bounds.width ) / 2 ) + inset + ( currentPosition.height * -1 ) ) * scale
let radius = ( UIScreen.main.bounds.width - inset * 2 ) * scale
croppedImage = imageWithImage(image: inputImage!, croppedTo: CGRect(x: xPos, y: yPos, width: radius, height: radius))
///Debug maths
print("Input: w \(inputW) h \(inputH)")
print("Profile: w \(profileW) h \(profileH)")
print("X Origin: \( ( ( profileW - UIScreen.main.bounds.width - inset ) / 2 ) + ( currentPosition.width * -1 ) )")
print("Y Origin: \( ( ( profileH - UIScreen.main.bounds.width - inset) / 2 ) + ( currentPosition.height * -1 ) )")
print("Scale: \(scale)")
print("Profile:\(profileW) + \(profileH)" )
print("Curent Pos: \(currentPosition.debugDescription)")
print("Radius: \(radius)")
print("x:\(xPos), y:\(yPos)")
}
let inset: CGFloat = 15
let screenAspect = UIScreen.main.bounds.width / UIScreen.main.bounds.height
}
除了拖动和缩放手势外,主要功能是外观和(可能还需要清理!)。
ImageManipulation.swift
文件中的功能。同样,这只是来自Hacking With Swift。 (谢谢保罗!)https://twitter.com/twostraws/
import SwiftUI
struct ImagePicker: UIViewControllerRepresentable {
@Environment(\.presentationMode) var presentationMode
@Binding var image: UIImage?
class Coordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
let parent: ImagePicker
init(_ parent: ImagePicker) {
self.parent = parent
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let uiImage = info[.originalImage] as? UIImage {
parent.image = uiImage
}
parent.presentationMode.wrappedValue.dismiss()
}
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIViewController(context: UIViewControllerRepresentableContext<ImagePicker>) -> UIImagePickerController {
let picker = UIImagePickerController()
picker.delegate = context.coordinator
return picker
}
func updateUIViewController(_ uiViewController: UIImagePickerController, context: UIViewControllerRepresentableContext<ImagePicker>) {
}
}
其中包含以下代码:
import UIKit
func imageWithImage(image: UIImage, croppedTo rect: CGRect) -> UIImage {
UIGraphicsBeginImageContext(rect.size)
let context = UIGraphicsGetCurrentContext()
let drawRect = CGRect(x: -rect.origin.x, y: -rect.origin.y,
width: image.size.width, height: image.size.height)
context?.clip(to: CGRect(x: 0, y: 0,
width: rect.size.width, height: rect.size.height))
image.draw(in: drawRect)
let subImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return subImage!
}
## Colors.swift ##
A handy extension to access system UIColors in SwiftUI:
import Foundation
import SwiftUI
extension Color {
static var label: Color {
return Color(UIColor.label)
}
static var secondaryLabel: Color {
return Color(UIColor.secondaryLabel)
}
static var tertiaryLabel: Color {
return Color(UIColor.tertiaryLabel)
}
static var quaternaryLabel: Color {
return Color(UIColor.quaternaryLabel)
}
static var systemFill: Color {
return Color(UIColor.systemFill)
}
static var secondarySystemFill: Color {
return Color(UIColor.secondarySystemFill)
}
static var tertiarySystemFill: Color {
return Color(UIColor.tertiarySystemFill)
}
static var quaternarySystemFill: Color {
return Color(UIColor.quaternarySystemFill)
}
static var systemBackground: Color {
return Color(UIColor.systemBackground)
}
static var secondarySystemBackground: Color {
return Color(UIColor.secondarySystemBackground)
}
static var tertiarySystemBackground: Color {
return Color(UIColor.tertiarySystemBackground)
}
static var systemGroupedBackground: Color {
return Color(UIColor.systemGroupedBackground)
}
static var secondarySystemGroupedBackground: Color {
return Color(UIColor.secondarySystemGroupedBackground)
}
static var tertiarySystemGroupedBackground: Color {
return Color(UIColor.tertiarySystemGroupedBackground)
}
static var systemRed: Color {
return Color(UIColor.systemRed)
}
static var systemBlue: Color {
return Color(UIColor.systemBlue)
}
static var systemPink: Color {
return Color(UIColor.systemPink)
}
static var systemTeal: Color {
return Color(UIColor.systemTeal)
}
static var systemGreen: Color {
return Color(UIColor.systemGreen)
}
static var systemIndigo: Color {
return Color(UIColor.systemIndigo)
}
static var systemOrange: Color {
return Color(UIColor.systemOrange)
}
static var systemPurple: Color {
return Color(UIColor.systemPurple)
}
static var systemYellow: Color {
return Color(UIColor.systemYellow)
}
static var systemGray: Color {
return Color(UIColor.systemGray)
}
static var systemGray2: Color {
return Color(UIColor.systemGray2)
}
static var systemGray3: Color {
return Color(UIColor.systemGray3)
}
static var systemGray4: Color {
return Color(UIColor.systemGray4)
}
static var systemGray5: Color {
return Color(UIColor.systemGray5)
}
static var systemGray6: Color {
return Color(UIColor.systemGray6)
}
}
答案 1 :(得分:0)
虽然我认为我的回复可能为时已晚,但我最终将我的解决方案与此问题混合起来:https://gist.github.com/hamin/e8c6dfe00d9c81375f3e,其中:
为了让相机上的叠加层正常工作,我正在收听由于添加或删除圆圈叠加而导致的通知(拍摄和拒绝图片)
保持上面提到的解决方案,我需要循环通过UINavigationController并在请求时绘制圆形叠加。
总结一下,请在下面找到我用Swift编写的解决方案:
public class CustomPicture: NSObject {
//MARK: - Properties
private var myPickerController: UIImagePickerController?
private var plCropOverlayBottomBar: UIView?
private var customLayer: CAShapeLayer?
//MARK: - Constants
private let screenHeight = UIScreen.mainScreen().bounds.size.height
private let screenWidth = UIScreen.mainScreen().bounds.size.width
private let kCameraNotificationIrisAnimationEnd = "_UIImagePickerControllerUserDidCaptureItem"
private let kCameraNotificationUserRejection = "_UIImagePickerControllerUserDidRejectItem"
private let kPUUIImageViewController = "PUUIImageViewController"
private let kPLUIImageViewController = "PLUIImageViewController"
private let kPLCropOverlayCropView = "PLCropOverlayCropView"
private let kPLCropOverlayBottomBar = "PLCropOverlayBottomBar"
//MARK: - Overrides
deinit {
NSNotificationCenter.defaultCenter().removeObserver(self)
}
//MARK: - Privates
private func camera() {
listenToCameraNotifications()
let myPickerController = UIImagePickerController()
myPickerController.delegate = self
myPickerController.sourceType = .Camera
myPickerController.allowsEditing = true
self.myPickerController = myPickerController
self.navigationController?.presentViewController(myPickerController, animated: true, completion: nil)
}
private func listenToCameraNotifications() {
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(cameraNotificationIrisEnd), name: kCameraNotificationIrisAnimationEnd, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(cameraNotificationRejected), name: kCameraNotificationUserRejection, object: nil)
}
private func photoLibrary() {
let myPickerController = UIImagePickerController()
myPickerController.delegate = self
myPickerController.allowsEditing = true
myPickerController.sourceType = .PhotoLibrary
self.myPickerController = myPickerController
self.navigationController?.presentViewController(myPickerController, animated: true, completion: nil)
}
//MARK: - Selector
/**
Listen to notification sent after reject button has been touched
*/
func cameraNotificationRejected() {
customLayer!.removeFromSuperlayer()
plCropOverlayBottomBar!.removeFromSuperview()
}
/**
Listen to notification sent after picture has been taken
*/
func cameraNotificationIrisEnd() {
addCircleOverlay(viewController: self.myPickerController!)
}
}
extension CustomPicture: UINavigationControllerDelegate {
//MARK: - Override
public func navigationController(navigationController: UINavigationController, willShowViewController: UIViewController, animated: Bool) {
if isImageViewer(navigationController: navigationController) {
addCircleOverlay(viewController: willShowViewController)
}
}
//MARK: - Private
private func addCircleOverlay(viewController viewController: UIViewController) {
hidePLCropOverlay(view: viewController.view)
setPLCropOverlayBottomBar(view: viewController.view)
setCustomLayer(viewController: viewController)
}
private func getCirclePath() -> UIBezierPath {
let circlePath = UIBezierPath(ovalInRect: CGRectMake(0, screenHeight / 2 - screenWidth / 2, screenWidth, screenWidth))
circlePath.usesEvenOddFillRule = true
let circleLayer = CAShapeLayer()
circleLayer.path = circlePath.CGPath
circleLayer.fillColor = UIColor.clearColor().CGColor
return circlePath
}
private func getMaskPath(screenWidth screenWidth: CGFloat, screenHeight: CGFloat, circlePath: UIBezierPath) -> UIBezierPath {
let maskPath = UIBezierPath(roundedRect: CGRectMake(0, 0, screenWidth, screenHeight), cornerRadius: 0)
maskPath.appendPath(circlePath)
maskPath.usesEvenOddFillRule = true
return maskPath
}
private func hidePLCropOverlay(view view: UIView) {
for myView in view.subviews {
if myView.isKindOfClass(NSClassFromString(kPLCropOverlayCropView)!) {
myView.hidden = true
break
} else {
hidePLCropOverlay(view: myView as UIView)
}
}
}
private func isImageViewer(navigationController navigationController: UINavigationController) -> Bool {
if (navigationController.viewControllers.count == 3 &&
(navigationController.viewControllers[2].dynamicType.description() == kPUUIImageViewController ||
navigationController.viewControllers[2].dynamicType.description() == kPLUIImageViewController)) {
return true
}
return false
}
private func setPLCropOverlayBottomBar(view view: UIView) {
for myView in view.subviews {
if myView.isKindOfClass(NSClassFromString(kPLCropOverlayBottomBar)!) {
plCropOverlayBottomBar = myView
break
}
else {
savePLCropOverlayBottomBar(view: myView as UIView)
}
}
}
private func setCustomLayer(viewController viewController: UIViewController) {
let circlePath = getCirclePath()
let maskPath = getMaskPath(screenWidth: screenWidth, screenHeight: screenHeight, circlePath: circlePath)
let maskLayer = CAShapeLayer()
maskLayer.path = maskPath.CGPath
maskLayer.fillRule = kCAFillRuleEvenOdd
maskLayer.fillColor = UIColor.blackColor().colorWithAlphaComponent(0.8).CGColor
customLayer = maskLayer
viewController.view.layer.addSublayer(customLayer!)
viewController.view.addSubview(plCropOverlayBottomBar!) // put back overlayBottomBar once we set its parent to hidden (subview of PLCropOverlay)
}
}
答案 2 :(得分:0)
以下是可帮助您创建裁剪叠加层的解决方案: -
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
if ([navigationController.viewControllers count] == 3)
{
CGFloat screenHeight = [[UIScreen mainScreen] bounds].size.height;
UIView *plCropOverlay = [[[viewController.view.subviews objectAtIndex:1]subviews] objectAtIndex:0];
plCropOverlay.hidden = YES;
int position = 0;
if (screenHeight == 568)
{
position = 124;
}
else
{
position = 80;
}
CAShapeLayer *circleLayer = [CAShapeLayer layer];
UIBezierPath *path2 = [UIBezierPath bezierPathWithOvalInRect:
CGRectMake(0.0f, position, 320.0f, 320.0f)];
[path2 setUsesEvenOddFillRule:YES];
[circleLayer setPath:[path2 CGPath]];
[circleLayer setFillColor:[[UIColor clearColor] CGColor]];
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, 320, screenHeight-72) cornerRadius:0];
[path appendPath:path2];
[path setUsesEvenOddFillRule:YES];
CAShapeLayer *fillLayer = [CAShapeLayer layer];
fillLayer.path = path.CGPath;
fillLayer.fillRule = kCAFillRuleEvenOdd;
fillLayer.fillColor = [UIColor blackColor].CGColor;
fillLayer.opacity = 0.8;
[viewController.view.layer addSublayer:fillLayer];
UILabel *moveLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 10, 320, 50)];
[moveLabel setText:@"Move and Scale"];
[moveLabel setTextAlignment:NSTextAlignmentCenter];
[moveLabel setTextColor:[UIColor whiteColor]];
[viewController.view addSubview:moveLabel];
}
}
答案 3 :(得分:0)
extension ProfileViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) {
guard imagePickerController?.sourceType == .camera else {
return
}
guard let view = viewController.view.subviews(deep: true, where: {
String(describing: type(of:$0)) == "CAMPreviewView"
}).first else {
return
}
viewController.view.layoutIfNeeded()
let camPreviewBounds = view.bounds
let circleRect = CGRect(
x: camPreviewBounds.minX + (camPreviewBounds.width - 320) * 0.5,
y: camPreviewBounds.minY + (camPreviewBounds.height - 320) * 0.5,
width: 320,
height: 320
)
let path = UIBezierPath(roundedRect: camPreviewBounds, cornerRadius: 0)
path.append(UIBezierPath(ovalIn: circleRect))
let layer = CAShapeLayer()
layer.path = path.cgPath
layer.fillRule = CAShapeLayerFillRule.evenOdd;
layer.fillColor = UIColor.black.cgColor
layer.opacity = 0.8;
view.layer.addSublayer(layer)
}
}