#ios #swift #user-interface #ios-charts
Вопрос:
используя библиотеку диаграмм, у меня есть представление с изображением или инициалами имени до вставки данных. Я хотел бы использовать этот вид в качестве изображения поверх полос. Поскольку это не возраст, я должен преобразовать его в UIImage с помощью пользовательского метода, так как значок не принимает представления, а только изображения.
Если я попытаюсь изменить значения кадров, я не смогу понять, почему я этого хочу, так как круглый вид немного меньше, в данном случае тот же размер баров, а не «децентрированный».
слева: начальная ситуация (круг немного больше ширины бара) справа: после изменения ширины и высоты на 52
в моем пользовательском представлении есть этот код, который, я думаю, может быть полезен здесь (не может быть изменен с учетом intrinsicContentSize):
public var model: BrandViewModel! { didSet { self.updateOutlets() } }
open override var intrinsicContentSize: CGSize { CGSize(width: 72, height: 72) }
open override func configure() {
super.configure()
self.backgroundColor = .white
self.layer.cornerRadius = self.intrinsicContentSize.width / 2
self.imageView.layer.cornerRadius = self.imageView.bounds.width / 2
self.initialsContainer.layer.cornerRadius = self.imageView.layer.cornerRadius
self.setupShadow()
}
Мой класс для диаграммы:
public struct BarChartValue {
public var value: Double?
public var name: String?
public var color: UIColor?
public init(value: Double?, name: String?, color: UIColor?) {
self.value = value
self.name = name
self.color = color
}
}
public class CorporateBarChartView: BarChartView {
public override func awakeFromNib() {
super.awakeFromNib()
self.setup()
}
public var values: [BarChartValue]? {
willSet {
self.setDataCount(withValues: newValue)
}
}
private func setup() {
self.chartDescription.enabled = false
self.highlightPerTapEnabled = false
self.legend.enabled = false
self.drawBarShadowEnabled = false
self.drawValueAboveBarEnabled = false
self.leftAxis.enabled = false
self.rightAxis.enabled = false
self.xAxis.enabled = false
self.pinchZoomEnabled = false
self.doubleTapToZoomEnabled = false
self.leftAxis.axisMinimum = 0
self.isUserInteractionEnabled = false
}
func setDataCount(withValues values: [BarChartValue]?) {
guard let values = values else { return }
let silverPlaceholder = UIColor.gray.withAlphaComponent(0.2)
let dataEntries = values.enumerated().map({ (index, value) -> BarChartDataEntry in
let brandView = BrandView()
brandView.model = BrandViewModel(name: value.name, image: nil)
let view = UIView(frame: CGRect(x: 0, y: 0, width: 72, height: 72))
view.addSubview(brandView)
view.backgroundColor = .red//.clear
brandView.backgroundColor = .green//.clear
let image = self.image(with: view)
return BarChartDataEntry(x: Double(index), y: value.value ?? 0, icon: image)
})
var set: BarChartDataSet! = nil
set = BarChartDataSet(entries: dataEntries)
set.colors = values.map({ (model) -> NSUIColor in
return (model.color ?? silverPlaceholder)
})
set.drawValuesEnabled = false
let data = BarChartData(dataSet: set)
data.barWidth = 0.3
self.data = data
}
func image(with view: UIView) -> UIImage? {
UIGraphicsBeginImageContextWithOptions(view.bounds.size, false, 0.0)
defer { UIGraphicsEndImageContext() }
if let context = UIGraphicsGetCurrentContext() {
view.layer.render(in: context)
let image = UIGraphicsGetImageFromCurrentImageContext()
return image
}
return nil
}
}
Ответ №1:
- Почему ты должен заворачивать свое
brandView
в другоеview
? Если вы это сделаете, то вам нужно убедиться, что он правильно выложен или установлена правильная рамка. Я также рекомендовал бы повторно использовать один экземпляр представления, то есть я бы создал его один раз до сбора данных и перенастроил его с помощью новых данных для создания нового изображения. - Я думаю, вам нужно изменить размер изображения до необходимого размера, чтобы диаграмма могла правильно его нарисовать. Для этого вы можете использовать эти расширения:
extension UIImage {
func scaled(toWidth width: CGFloat) -> UIImage? {
guard width > 0.0, self.size.width > 0.0 else {
return nil
}
return self.redrawnImage(with: self.size.scaled(toWidth: width))
}
func scaled(toHeight height: CGFloat) -> UIImage? {
guard height > 0.0, self.size.height > 0.0 else {
return nil
}
return self.redrawnImage(with: self.size.scaled(toHeight: height))
}
private func redrawnImage(with size: CGSize) -> UIImage {
UIGraphicsImageRenderer(size: size).image { _ in
draw(in: .init(origin: .zero, size: size))
}
}
}
extension CGSize {
func scaled(toWidth width: CGFloat) -> CGSize {
CGSize(width: width, height: (self.height / self.width) * width)
}
func scaled(toHeight height: CGFloat) -> CGSize {
CGSize(width: (self.width / self.height) * height, height: height)
}
}
Комментарии:
1. привет, извините, но код не полностью мой, не уверен, как я мог бы использовать ваши методы, может быть, таким образом? ‘пусть изображение = self.изображение(с: вид)?.масштабировано(ширина: 50)?.масштабировано(высота: 50)’
2. протестировал это решение, но оно не является динамически адаптивным к размерам экрана. есть ли способ установить размеры значков над полосами?
3.
let image = self.image(with: view)?.scaled(toWidth: 50)
вернет вам изображение с шириной и высотой 50pt, которые будут соответствовать соотношению изображения. Вы никогда ничего не говорили о динамической адаптации его к размеру экрана. Загляните в библиотеку диаграмм, может быть, есть способ узнать ширину полосы. А затем в соответствии с этой шириной вы можете масштабировать свое изображение.