Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Threema/Threema/SharedUI/Components/   (Social Medium ©)  Datei vom 26.9.2026 mit Größe 7 kB image not shown  

Quelle  BlurCircleView.swift   Sprache: JAVA

 

import UIKit

protocol BlurCircleViewConfiguration {
    var scaledSize: CGFloat { get }
    var symbolConfiguration: UIImage.SymbolConfiguration { get }
    var textStyle: UIFont.TextStyle { get }
    var textStyleFontMetrics: UIFontMetrics { get }
}

extension BlurCircleView {
    
    public enum BlurCircleViewConfigurationType {
        case `default`
        case thumbnail
        case retryAndCancel
    }
    
    private struct DefaultConfiguration: BlurCircleViewConfiguration {
        
        /// Diameter of circular view adjusted for current content size
        var scaledSize: CGFloat {
            let defaultSize: CGFloat = 52
            return textStyleFontMetrics.scaledValue(for: defaultSize)
        }
        
        /// Configuration of symbol in the center
        var symbolConfiguration: UIImage.SymbolConfiguration {
            let textStyleAndScaleConfiguration = UIImage.SymbolConfiguration(textStyle: textStyle, scale: .large)
            let weightConfiguration = UIImage.SymbolConfiguration(weight: .bold)
            return textStyleAndScaleConfiguration.applying(weightConfiguration)
        }
        
        // These should always use the same TextStyle
        let textStyle: UIFont.TextStyle = .title3
        let textStyleFontMetrics = UIFontMetrics(forTextStyle: .title3)
    }
    
    private struct ThumbnailConfiguration: BlurCircleViewConfiguration {
        
        /// Diameter of circular view adjusted for current content size
        var scaledSize: CGFloat {
            let defaultSize: CGFloat = 20
            return textStyleFontMetrics.scaledValue(for: defaultSize)
        }
        
        /// Configuration of symbol in the center
        var symbolConfiguration: UIImage.SymbolConfiguration {
            let textStyleAndScaleConfiguration = UIImage.SymbolConfiguration(textStyle: textStyle, scale: .small)
            let weightConfiguration = UIImage.SymbolConfiguration(weight: .bold)
            return textStyleAndScaleConfiguration.applying(weightConfiguration)
        }
        
        // These should always use the same TextStyle
        let textStyle: UIFont.TextStyle = .caption1
        let textStyleFontMetrics = UIFontMetrics(forTextStyle: .caption1)
    }
    
    private struct RetryAndCancelButtonConfiguration: BlurCircleViewConfiguration {
        
        /// Diameter of circular view adjusted for current content size
        var scaledSize: CGFloat {
            let defaultSize: CGFloat = 40
            return textStyleFontMetrics.scaledValue(for: defaultSize)
        }
        
        /// Configuration of symbol in the center
        var symbolConfiguration: UIImage.SymbolConfiguration {
            let textStyleAndScaleConfiguration = UIImage.SymbolConfiguration(textStyle: textStyle, scale: .medium)
            let weightConfiguration = UIImage.SymbolConfiguration(weight: .bold)
            return textStyleAndScaleConfiguration.applying(weightConfiguration)
        }
        
        // These should always use the same TextStyle
        let textStyle: UIFont.TextStyle = .body
        let textStyleFontMetrics = UIFontMetrics(forTextStyle: .body)
    }
}

/// Circle view with an vibrant symbol in the center and a blurry background
///
/// Use as-is. You should not add your own subviews.
final class BlurCircleView: UIVisualEffectView {
    
    private let viewConfiguration: BlurCircleViewConfiguration
    
    private var currentSfSymbolName: String
    
    private lazy var sizeConstraint: NSLayoutConstraint = widthAnchor
        .constraint(equalToConstant: viewConfiguration.scaledSize)
    
    // MARK: Views
    
    private lazy var symbolImageView: UIImageView = {
        let imageView = UIImageView()
        imageView.preferredSymbolConfiguration = viewConfiguration.symbolConfiguration
        imageView.contentMode = .center
        return imageView
    }()
    
    // All the stuff to make it blurry and vibrant
    private let blurEffect = UIBlurEffect(style: .systemMaterial)
    private lazy var vibrantEffectView = UIVisualEffectView(
        effect: UIVibrancyEffect(blurEffect: blurEffect, style: .fill)
    )
    
    // MARK: - Lifecycle
    
    /// Create a new view
    ///
    /// - Parameters:
    ///   - sfSymbolName: Name of SF Symbol to show. Use just the SF Symbol name.
    ///   - configuration: BlurCircleViewConfigurationType, default value is .default
    init(
        sfSymbolName: String,
        configuration: BlurCircleViewConfigurationType = .default
    ) {
        
        switch configuration {
        case .default:
            self.viewConfiguration = DefaultConfiguration()
        case .thumbnail:
            self.viewConfiguration = ThumbnailConfiguration()
        case .retryAndCancel:
            self.viewConfiguration = RetryAndCancelButtonConfiguration()
        }
        
        self.currentSfSymbolName = sfSymbolName
        
        super.init(effect: blurEffect)
        
        configureView()
        registerObservers()
        updateSize()
    }
    
    @available(*, unavailable)
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    // MARK: - Configure
    
    private func configureView() {
        // Content
        symbolImageView.image = UIImage(systemName: currentSfSymbolName)
                        
        // Layout: size
        NSLayoutConstraint.activate([
            sizeConstraint,
            heightAnchor.constraint(equalTo: widthAnchor),
        ])
                
        // Layout: Background & symbol
        vibrantEffectView.contentView.addSubview(symbolImageView)
        contentView.addSubview(vibrantEffectView)
        
        symbolImageView.translatesAutoresizingMaskIntoConstraints = false
        vibrantEffectView.translatesAutoresizingMaskIntoConstraints = false
        
        NSLayoutConstraint.activate([
            symbolImageView.centerYAnchor.constraint(equalTo: vibrantEffectView.centerYAnchor),
            symbolImageView.centerXAnchor.constraint(equalTo: vibrantEffectView.centerXAnchor),
            
            vibrantEffectView.topAnchor.constraint(equalTo: topAnchor),
            vibrantEffectView.leadingAnchor.constraint(equalTo: leadingAnchor),
            vibrantEffectView.bottomAnchor.constraint(equalTo: bottomAnchor),
            vibrantEffectView.trailingAnchor.constraint(equalTo: trailingAnchor),
        ])
        
        // Show circle
        clipsToBounds = true
        
        if UIAccessibility.isReduceTransparencyEnabled || UIAccessibility.isDarkerSystemColorsEnabled {
            backgroundColor = Colors.backgroundChatBar
        }
    }
    
    private func registerObservers() {
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(contentSizeCategoryDidChange),
            name: UIContentSizeCategory.didChangeNotification,
            object: nil
        )
    }
    
    // MARK: - Updates
    
    func updateSymbol(to sfSymbolName: String) {
        guard currentSfSymbolName != sfSymbolName else {
            // Don't update symbol if it is still the same
            return
        }
        
        symbolImageView.image = UIImage(systemName: sfSymbolName)
        currentSfSymbolName = sfSymbolName
    }
    
    private func updateSize() {
        sizeConstraint.constant = viewConfiguration.scaledSize
        layer.cornerRadius = viewConfiguration.scaledSize / 2
    }
    
    func highlight(_ highlight: Bool, highlightingDuration: Double = 0.15, highlightingAlpha: Double = 0.8) {
        UIView.animate(withDuration: highlightingDuration) {
            self.alpha = highlight ? highlightingAlpha : 1
        }
    }
    
    // MARK: - Notifications
    
    @objc private func contentSizeCategoryDidChange() {
        updateSize()
    }
    
    // MARK: - Layout
    
    override var intrinsicContentSize: CGSize {
        CGSize(width: viewConfiguration.scaledSize, height: viewConfiguration.scaledSize)
    }
}

Messung
CHZG
859610093

¤ Dauer der Verarbeitung: 0.4 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover


Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.