添加即时收款流程并对齐 Android
This commit is contained in:
37
suixinkan/Common/PhotoLibrarySaver.swift
Normal file
37
suixinkan/Common/PhotoLibrarySaver.swift
Normal file
@ -0,0 +1,37 @@
|
||||
//
|
||||
// PhotoLibrarySaver.swift
|
||||
// suixinkan
|
||||
//
|
||||
|
||||
import Photos
|
||||
import UIKit
|
||||
|
||||
/// 将图片保存到系统相册,供收款二维码保存使用。
|
||||
enum PhotoLibrarySaver {
|
||||
|
||||
/// 请求写入权限并将图片保存到相册。
|
||||
static func saveImage(_ image: UIImage) async -> Bool {
|
||||
let status = await requestAuthorizationIfNeeded()
|
||||
guard status == .authorized || status == .limited else {
|
||||
return false
|
||||
}
|
||||
|
||||
return await withCheckedContinuation { continuation in
|
||||
PHPhotoLibrary.shared().performChanges({
|
||||
PHAssetChangeRequest.creationRequestForAsset(from: image)
|
||||
}, completionHandler: { success, _ in
|
||||
continuation.resume(returning: success)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private static func requestAuthorizationIfNeeded() async -> PHAuthorizationStatus {
|
||||
let current = PHPhotoLibrary.authorizationStatus(for: .addOnly)
|
||||
switch current {
|
||||
case .notDetermined:
|
||||
return await PHPhotoLibrary.requestAuthorization(for: .addOnly)
|
||||
default:
|
||||
return current
|
||||
}
|
||||
}
|
||||
}
|
||||
59
suixinkan/Common/QRCodeGenerator.swift
Normal file
59
suixinkan/Common/QRCodeGenerator.swift
Normal file
@ -0,0 +1,59 @@
|
||||
//
|
||||
// QRCodeGenerator.swift
|
||||
// suixinkan
|
||||
//
|
||||
|
||||
import CoreImage
|
||||
import UIKit
|
||||
|
||||
/// 圆角样式二维码生成器,对齐 Android `QrCodeUtils.generateStyledQrBitmap`。
|
||||
enum QRCodeGenerator {
|
||||
|
||||
private static let defaultPixelSize = 580
|
||||
private static let defaultCornerRadius: CGFloat = 24
|
||||
|
||||
/// 根据内容生成带圆角背景的二维码图片。
|
||||
static func generateStyledQRCode(
|
||||
content: String,
|
||||
pixelSize: Int = defaultPixelSize,
|
||||
backgroundColor: UIColor = AppColor.inputBackground,
|
||||
cornerRadius: CGFloat = defaultCornerRadius
|
||||
) -> UIImage? {
|
||||
guard !content.isEmpty,
|
||||
let qrImage = makeQRCodeImage(from: content, pixelSize: pixelSize) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let size = CGSize(width: pixelSize, height: pixelSize)
|
||||
let format = UIGraphicsImageRendererFormat()
|
||||
format.scale = 1
|
||||
let renderer = UIGraphicsImageRenderer(size: size, format: format)
|
||||
return renderer.image { context in
|
||||
let rect = CGRect(origin: .zero, size: size)
|
||||
let path = UIBezierPath(roundedRect: rect, cornerRadius: cornerRadius)
|
||||
backgroundColor.setFill()
|
||||
path.fill()
|
||||
|
||||
context.cgContext.saveGState()
|
||||
path.addClip()
|
||||
qrImage.draw(in: rect)
|
||||
context.cgContext.restoreGState()
|
||||
}
|
||||
}
|
||||
|
||||
private static func makeQRCodeImage(from content: String, pixelSize: Int) -> UIImage? {
|
||||
guard let filter = CIFilter(name: "CIQRCodeGenerator") else { return nil }
|
||||
let data = Data(content.utf8)
|
||||
filter.setValue(data, forKey: "inputMessage")
|
||||
filter.setValue("M", forKey: "inputCorrectionLevel")
|
||||
guard let outputImage = filter.outputImage else { return nil }
|
||||
|
||||
let scale = CGFloat(pixelSize) / outputImage.extent.width
|
||||
let scaledImage = outputImage.transformed(by: CGAffineTransform(scaleX: scale, y: scale))
|
||||
let context = CIContext()
|
||||
guard let cgImage = context.createCGImage(scaledImage, from: scaledImage.extent) else {
|
||||
return nil
|
||||
}
|
||||
return UIImage(cgImage: cgImage)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user