Реалізація генерації QR-кодів у мобільному додатку
QR-код генерується вбудованими засобами обох платформ без сторонніх бібліотек. На iOS — CIFilter, на Android — ZXing чи ML Kit. Складність не в генерації, а в кастомізації: логотип у центрі, фірмові кольори, округлі кути модулів — все це потребує ручної роботи з CoreGraphics чи Android Canvas.
iOS: CIFilter та кастомізація
Базова генерація через CoreImage:
func generateQRCode(from string: String) -> UIImage? {
guard let data = string.data(using: .utf8),
let filter = CIFilter(name: "CIQRCodeGenerator") else { return nil }
filter.setValue(data, forKey: "inputMessage")
filter.setValue("H", forKey: "inputCorrectionLevel") // H = 30% коррекція — потрібна при логотипі в центрі
guard let ciImage = filter.outputImage else { return nil }
// Масштабувати без blur — через трансформацію, не UIImage(ciImage:) з resize
let scale = 10.0
let scaledImage = ciImage.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)
}
CIQRCodeGenerator завжди генерирує чорно-білий QR. Для кольорового — замінити білий фон та чорні модулі через CIFalseColor filter, чи малювати поверх через UIGraphicsImageRenderer.
Логотип у центрі. Рівень коррекції H (30%) дозволяє перекрити до 30% площі QR-коду без втрати читаємості. Логотип розміром ~25% від QR працює надійно. Накладається через UIGraphicsImageRenderer:
func addLogo(_ logo: UIImage, to qrImage: UIImage) -> UIImage {
let renderer = UIGraphicsImageRenderer(size: qrImage.size)
return renderer.image { _ in
qrImage.draw(in: CGRect(origin: .zero, size: qrImage.size))
let logoSize = CGSize(width: qrImage.size.width * 0.25, height: qrImage.size.height * 0.25)
let logoOrigin = CGPoint(
x: (qrImage.size.width - logoSize.width) / 2,
y: (qrImage.size.height - logoSize.height) / 2
)
logo.draw(in: CGRect(origin: logoOrigin, size: logoSize))
}
}
Округлі модулі та точечний стиль — CIFilter цього не вміє. Потрібно парсити бітову матрицю QR та малювати кожен модуль вручну через UIBezierPath. Бібліотека QRCode (Swift Package) робит це та дає широкі можливості кастомізації.
Android: ZXing та ML Kit
ZXing — де-факто стандарт для QR на Android:
import com.google.zxing.BarcodeFormat
import com.google.zxing.qrcode.QRCodeWriter
fun generateQRCode(content: String, size: Int): Bitmap {
val writer = QRCodeWriter()
val bitMatrix = writer.encode(content, BarcodeFormat.QR_CODE, size, size)
val bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.RGB_565)
for (x in 0 until size) {
for (y in 0 until size) {
bitmap.setPixel(x, y, if (bitMatrix[x, y]) Color.BLACK else Color.WHITE)
}
}
return bitmap
}
Для кастомних кольорів — замінити Color.BLACK / Color.WHITE. Для логотипу — наложити через Canvas:
fun addLogoToBitmap(qrBitmap: Bitmap, logo: Bitmap): Bitmap {
val result = qrBitmap.copy(Bitmap.Config.ARGB_8888, true)
val canvas = Canvas(result)
val logoSize = qrBitmap.width / 4
val left = (qrBitmap.width - logoSize) / 2f
val top = (qrBitmap.height - logoSize) / 2f
val scaledLogo = Bitmap.createScaledBitmap(logo, logoSize, logoSize, true)
canvas.drawBitmap(scaledLogo, left, top, null)
return result
}
ML Kit Barcode Scanning — Google-бібліотека, яка вміє не тільки QR, але й EAN, Code 128, Data Matrix. Для генерації не підходить (тільки сканування), але часто потрібна рядом — показати QR та тут же дати можливість відсканувати чужий.
Динамічні QR та UTM-метки
QR з фіксованим URL — статичний. QR, який веде на редирект-сервіс (короткий лінк, який можна змінити без перегенерації QR) — динамічний. Для маркетингу: кожен QR-код унікальний, містить UTM-метки, аналітика переходів. Генерація на сервері через бібліотеку (python-qrcode, qrcode npm) з збереженням PNG на CDN.
На мобільному клієнті у цьому випадку — тільки відображення готового PNG або <img> тег через WebView.
Збереження та шаринг
Зберегти у галерею: на iOS — UIImageWriteToSavedPhotosAlbum чи PHPhotoLibrary.shared().performChanges. Потребує дозволу NSPhotoLibraryAddUsageDescription. На Android 10+: MediaStore.Images.Media.insertImage через ContentResolver, без дозволу WRITE_EXTERNAL_STORAGE.
Поділитися: UIActivityViewController з UIImage (iOS), Intent.ACTION_SEND з URI через FileProvider (Android).
1 робочий день для базової генерації. Кастомний стиль модулів, логотип, брендування — 2–3 дні. Вартість розраховується індивідуально.







