Does the legend limit the number of titles? - swift

I am using iso-charts to try and draw a pie chart in an iOS app.
No matter what I try, I can't seem to get the full number of titles to draw in the legend.
I have my data set up as:
ages = ["18-", "25-", "35-", "45-", "55-", "65-", "75+"]
agePercentages = [10.0, 20.0, 30.0, 5.0, 10.0, 45.0, 120.0]
My code to setup the pieChart as:
func setPieDefaults(myPieChart: PieChartView) -> PieChartView {
myPieChart.frame = CGRectMake(0, 0, UIScreen.mainScreen().bounds.size.width, UIScreen.mainScreen().bounds.size.width*0.5)
myPieChart.usePercentValuesEnabled = true
myPieChart.holeTransparent = true
myPieChart.holeColor = UIColor.darkPurpleColor()
myPieChart.backgroundColor = UIColor.darkPurpleColor()
myPieChart.rotationAngle = 0.0
myPieChart.rotationEnabled = true
myPieChart.centerTextFont = UIFont(name: "HelveticaNeue-Bold", size:20)!
myPieChart.descriptionText = ""
myPieChart.centerText = "%"
myPieChart.centerTextColor = UIColor.whiteColor()
myPieChart.drawHoleEnabled = true
myPieChart.noDataText = "Loading Data ..."
let legend = myPieChart.legend
legend.font = UIFont(name: "Arial", size: 11)!
legend.textColor = UIColor.whiteColor()
legend.position = .RightOfChart
legend.form = .Circle
return myPieChart
}
And ..
func setChart(dataPoints: [String], values: [Double], myPieView: PieChartView) {
var dataEntries: [ChartDataEntry] = []
for i in 0..<dataPoints.count {
let dataEntry = ChartDataEntry(value: values[i], xIndex: i)
dataEntries.append(dataEntry)
}
var colors = [UIColor]()
switch myPieView {
case genderPieChartView:
colors = [UIColor.blueColor(), UIColor.pinkColor()]
default:
colors = ChartColorTemplates.colorful()
}
let pieChartDataSet = PieChartDataSet(yVals: dataEntries, label: nil)
pieChartDataSet.sliceSpace = 3.0
pieChartDataSet.colors = colors
let pieChartData = PieChartData(xVals: dataPoints, dataSet: pieChartDataSet)
myPieView.animate(xAxisDuration: 2, yAxisDuration: 2)
let pFormatter = NSNumberFormatter()
pFormatter.numberStyle = .PercentStyle
pFormatter.maximumFractionDigits = 0
pFormatter.percentSymbol = ""
pFormatter.multiplier = 1
pieChartData.setValueFormatter(pFormatter)
pieChartData.setValueFont(UIFont(name: "HelveticaNeue-Bold", size: 11)!)
pieChartData.setValueTextColor(UIColor.whiteColor())
myPieView.data = pieChartData
myPieView.drawSliceTextEnabled = false
}
But it won't print any more than 5 of the labels. It's returning the pie-slices perfectly. But not the labels in the legend.
Am I doing something wrong? Thanks in advance for letting me know.

Solved.
In reading the framework docs for the Android version a little better:
The number of entries the automatically generated legend contains
depends on the number of different colors (across all DataSet objects)
as well as on the DataSet labels. The labels of the Legend depend on
the labels set for the used DataSet objects in the chart. If no labels
for the DataSet objects have been specified, the chart will
automatically generate them. If multiple colors are used for one
DataSet, those colors are grouped and only described by one label.
I realised I needed to increase the number of colours in the ChartColorTemplate.colorful() definition to match the number of labels I was trying to use. The current example code comes with only 5 colours defined.
public class func colorful () -> [UIColor]
{
return [
UIColor(red: 193/255.0, green: 37/255.0, blue: 82/255.0, alpha: 1.0),
UIColor(red: 255/255.0, green: 102/255.0, blue: 0/255.0, alpha: 1.0),
UIColor(red: 245/255.0, green: 199/255.0, blue: 0/255.0, alpha: 1.0),
UIColor(red: 106/255.0, green: 150/255.0, blue: 31/255.0, alpha: 1.0),
UIColor(red: 179/255.0, green: 100/255.0, blue: 53/255.0, alpha: 1.0),
UIColor(red: 200/255.0, green: 100/255.0, blue: 53/255.0, alpha: 1.0), // added colour
UIColor(red: 150/255.0, green: 150/255.0, blue: 70/255.0, alpha: 1.0), // added colour
UIColor(red: 84/255.0, green: 78/255.0, blue: 53/255.0, alpha: 1.0), // added colour
]
}
If you have the same problem, then define a lot more colours to meet the needs of the maximum number of labels needed. This will also solve a problem if you try and word-wrap the legend (which I was also facing).

Related

How to set alpha for an Assets Color in Swift

I just wanted to know how to change the opacity (alpha) of an asset color I have. When I try this UIColor(named: "something", alpha: 0.4), Xcode complains: Extra argument 'alpha' in call.
Is there any way I can modify the opacity of an asset color programmatically?
UIColor, as mentioned by Jasur S., has the withAlphaComponent(_:).
It can be used with any UIColor objects to modify its alpha:
let color = UIColor(named: "something")?.withAlphaComponent(0.5)
Creating custom extensions to cover existing functionality is an arguable good.
You can add this extension for UIColor and easy to use.
extension UIColor {
convenience init?(named: String, alpha: CGFloat) {
if let rgbComponents = UIColor(named: named)?.cgColor.components {
self.init(red: rgbComponents[0], green: rgbComponents[1], blue: rgbComponents[2], alpha: alpha)
} else {
self.init(named: named)
}
}
}
Usage:
let colorWithAlpha = UIColor(named: "Assets Color", alpha: 0.5)
You can set color alpha component when you assign color as follows:
button.backgroundColor = .black.withAlphaComponent(0.5)
You can modify asset color from here
Select that particular asset color and
Drag that opacity indicator in left or right or directly set some values
Use this extension to get the rgb value from the UIColor
extension UIColor {
var rgba: (red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) {
var red: CGFloat = 0
var green: CGFloat = 0
var blue: CGFloat = 0
var alpha: CGFloat = 0
getRed(&red, green: &green, blue: &blue, alpha: &alpha)
return (red, green, blue, alpha)
}
}
Then you can create a new color
let assetColor = UIColor(named: "something")
let (r,g,b,_) = assetColor.rgba
let newColor = UIColor(red:r, green:g, blue:b, alpha: 0.4)

Can i use 'for' loop on this?

I'm wondering if i may use 'for' loop for this code. Please forgive me, I know that is kind of a lame question, but I'm new to swift. Hope that you can help me here, guys!
Thanks a lot everyone!
Code:
override func viewDidLoad() {
super.viewDidLoad()
// Background color
let kolorTla = UIColor(red: 0/255.0, green: 66/255.0, blue: 132/255.0, alpha: 1.0)
view.backgroundColor = kolorTla
// Icons border
ramka.layer.borderColor = UIColor(red: 255, green: 255, blue: 255, alpha: 1.0).cgColor
ramka.layer.cornerRadius = 5.0
ramka.layer.borderWidth = 3
// Image
skill1.image = UIImage(named: "english")
// Image border
skill1.layer.borderColor = UIColor(red: 255, green: 255, blue: 255, alpha: 1.0).cgColor
skill1.layer.cornerRadius = 5.0
skill1.layer.borderWidth = 3
skill1.contentMode = .scaleAspectFit
// Image
skill2.image = UIImage(named: "literature")
// Image border
skill2.layer.borderColor = UIColor(red: 255, green: 255, blue: 255, alpha: 1.0).cgColor
skill2.layer.cornerRadius = 5.0
skill2.layer.borderWidth = 3
skill2.contentMode = .scaleAspectFit
// Image
skill3.image = UIImage(named: "idea1")
// Image border
skill3.layer.borderColor = UIColor(red: 255, green: 255, blue: 255, alpha: 1.0).cgColor
skill3.layer.cornerRadius = 5.0
skill3.layer.borderWidth = 3
skill3.contentMode = .scaleAspectFit
You can to some extent. You would just need to define an array of your items and loop over them. Not sure if it saves you much code wise but does make it a little more understandable.
override func viewDidLoad() {
super.viewDidLoad()
// Background color
let kolorTla = UIColor(red: 0/255.0, green: 66/255.0, blue: 132/255.0, alpha: 1.0)
view.backgroundColor = kolorTla
// Icons border
ramka.layer.borderColor = UIColor(red: 255, green: 255, blue: 255, alpha: 1.0).cgColor
ramka.layer.cornerRadius = 5.0
ramka.layer.borderWidth = 3
// Set Image
skill1.image = UIImage(named: "english")
skill2.image = UIImage(named: "literature")
skill3.image = UIImage(named: "idea1")
// Set Image border
for skill in [skill1, skill2, skill3] {
skill.layer.borderColor = UIColor(red: 255, green: 255, blue: 255, alpha: 1.0).cgColor
skill.layer.cornerRadius = 5.0
skill.layer.borderWidth = 3
skill.contentMode = .scaleAspectFit
}
}
Better approach at least in my opinion would be to create a simple function to handle this instead.
override func viewDidLoad() {
super.viewDidLoad()
// Background color
let kolorTla = UIColor(red: 0/255.0, green: 66/255.0, blue: 132/255.0, alpha: 1.0)
view.backgroundColor = kolorTla
// Icons border
ramka.layer.borderColor = UIColor(red: 255, green: 255, blue: 255, alpha: 1.0).cgColor
ramka.layer.cornerRadius = 5.0
ramka.layer.borderWidth = 3
// Set Images
setupImageView(imageView: skill1, imageName: "english")
setupImageView(imageView: skill2, imageName: "literature")
setupImageView(imageView: skill3, imageName: "idea1")
}
func setupImageView(imageView: UIImageView, imageName: String) {
// Set Image
imageView.image = UIImage(named: imageName)
// Set Image border
imageView.layer.borderColor = UIColor(red: 255, green: 255, blue: 255, alpha: 1.0).cgColor
imageView.layer.cornerRadius = 5.0
imageView.layer.borderWidth = 3
imageView.contentMode = .scaleAspectFit
}
While you're not able to use a for loop to modify the variable names and loop through them, you could put your skill instances in an array and loop through them that way.
...
skill1.image = UIImage(named: "english")
skill2.image = UIImage(named: "literature")
skill3.image = UIImage(named: "idea1")
let skills = [skill1, skill2, skill3]
for skill in skills {
skill.layer.borderColor = UIColor(red: 255, green: 255, blue: 255, alpha: 1.0).cgColor
skill.layer.cornerRadius = 5.0
skill.layer.borderWidth = 3
skill.contentMode = .scaleAspectFit
}
Yes, you can. Place skill1,skill2, and skill3 in an array and iterate over it like this:
var objectArray = [skill1,skill2,skill3]
for object in objectArray
{
object.layer = ....
}
You could just extend your ImageView
extension UIImageView {
func addCustomLayer() { // add arguments to function if you wish to change the value assigned
self.layer.borderColor = UIColor(red: 255, green: 255, blue: 255, alpha: 1.0).cgColor
self.layer.cornerRadius = 5.0
self.layer.borderWidth = 3
self.contentMode = .scaleAspectFit
}
}
}
Then you call that method on each UIImageView
for each in [skill1, skill2, skill3] {
each.addCustomLayer()
}

Cannot change color of SCNCone - Scenekit

I have an 'attach node' that has 2 child nodes that are Blender models. I have added a third node to this attach node that is a SCNCone. For some reason, I can't change the color of the cone node, only the transparency. I can't seem to see anything wrong with the code, but during runtime the cone is always a black color no matter what color I set it to.
let coneGeo = SCNCone(topRadius: 0.1, bottomRadius: 0.7, height: 4)
let coneMaterial = SCNMaterial()
coneMaterial.diffuse.contents = UIColor(red: 255.0/255.0, green: 108.0/255.0, blue: 91.0/255.0, alpha: 0.2)
coneGeo.materials = [coneMaterial]
let coneNode = SCNNode(geometry: coneGeo)
coneNode.position = SCNVector3(0, -1.5, 0)
coneNode.name = "coneNode"
AttachNode.addChildNode(coneNode)
Replace coneMaterial.diffuse.contents = UIColor(red: 255.0/255.0, green: 108.0/255.0, blue: 91.0/255.0, alpha: 0.2) with coneGeo.geometry?.firstMaterial?.diffuse.contents.diffuse.contents = UIColor(red: 255.0/255.0, green: 108.0/255.0, blue: 91.0/255.0, alpha: 0.2). Instead of changing the cone's material color without geometry, you have to access it's material color through it's geometry parameter.
coneGeo.materials = [coneMaterial]
This will also work. I tested your code by adding the cone node to an empty scene.
I just get a black screen.
But if I change the alpha value to say 0.5, this is what I get.
The code.
override func viewDidLoad()
{
super.viewDidLoad()
// create a new scene
let scene = SCNScene()
let coneGeo = SCNCone(topRadius: 0.1, bottomRadius: 0.7, height: 4)
let coneMaterial = SCNMaterial()
coneMaterial.diffuse.contents = UIColor(red: 255.0 / 255.0,
green: 108.0 / 255.0,
blue: 91.0 / 255.0, alpha: 0.5)
coneGeo.materials = [coneMaterial]
let coneNode = SCNNode(geometry
: coneGeo)
coneNode.position = SCNVector3(0, -1.5, 0)
coneNode.name = "coneNode"
scene.rootNode.addChildNode(coneNode)
// retrieve the SCNView
let scnView = self.view as! SCNView
// set the scene to the view
scnView.scene = scene
// allows the user to manipulate the camera
scnView.allowsCameraControl = true
// show statistics such as fps and timing information
scnView.showsStatistics = true
// configure the view
scnView.backgroundColor = UIColor.black
}
So I would say, check your alpha value in UIColor(red: 255.0/255.0, green: 108.0/255.0, blue: 91.0/255.0, alpha: 0.2)

Gradient color effect on UIView in iOS 10 Swift 2.3 Xcode 8

I am trying to achieve a gradient color on a UIView or button with two color black which fades out to clear color or white color (please see image).
I have tried using different combinations of white color, clear color; experimenting with alpha as well. I have also set the locations property as can be seen in below code but I am not able to achieve desired results.
Can anyone tell me where I am wrong. :)
let colorClear = UIColor.clearColor().CGColor
let colorLeft = UIColor(red: 255.0/255.0, green: 255.0/255.0, blue: 255.0/255.0, alpha: 0.9).CGColor
let colorRight = UIColor(red: 0.0/255.0, green: 0.0/255.0, blue: 0.0/255.0, alpha: 1.0).CGColor
let gradientLayer = CAGradientLayer()
gradientLayer.colors = [colorLeft, colorRight]
gradientLayer.locations = [ 0.1, 0.9]
gradientLayer.frame = self.createAccountView.bounds
gradientLayer.startPoint = CGPoint(x:0.0, y:0.5)
gradientLayer.endPoint = CGPoint(x:1.0, y:0.5)
createAccountView.layer.addSublayer(gradientLayer)
createAccountView.layer.masksToBounds = true
The desired result is the one in which black color transitions to a faded one.
I have already tried setting both colors as black and the color1 with an alpha.
I have already tried commenting locations property.
you should set gradientLayer.frame in viewDidLayoutSubviews().
Like this:
class ViewController: UIViewController {
let gradientLayer = CAGradientLayer()
override func viewDidLoad() {
let colorClear = UIColor.clearColor().CGColor
let colorLeft = UIColor(red: 255.0/255.0, green: 255.0/255.0, blue: 255.0/255.0, alpha: 0.9).CGColor
let colorRight = UIColor(red: 0.0/255.0, green: 0.0/255.0, blue: 0.0/255.0, alpha: 1.0).CGColor
self.gradientLayer.colors = [colorLeft, colorRight]
self.gradientLayer.locations = [ 0.1, 0.9]
self.gradientLayer.startPoint = CGPoint(x:0.0, y:0.5)
self.gradientLayer.endPoint = CGPoint(x:1.0, y:0.5)
createAccountView.layer.addSublayer(self.gradientLayer)
createAccountView.layer.masksToBounds = true
}
override viewDidLayoutSubviews() {
super.viewDidLayoutSubViews()
self.gradientLayer.frame = self.createAccountView.bounds
}

Setting tintColor for Apple Watch complication

I am trying to set the header text color for a Modular Large complication.
I have already customized the watch face to use Multicolor.
However, when I build and run this code, the header text color is still white (which is the default).
Why isn't the color updating?
private func templateForClassModularLarge(className: Schedule) -> CLKComplicationTemplateModularLargeStandardBody {
let template = CLKComplicationTemplateModularLargeStandardBody()
let headerTextProvider = CLKSimpleTextProvider(text: "My Schedule", shortText: "Schedule")
headerTextProvider.tintColor = UIColor(red: 101, green: 153, blue: 255, alpha: 1)
template.headerTextProvider = headerTextProvider
template.body1TextProvider = CLKTimeIntervalTextProvider(startDate: className.start, endDate: className.end)
template.body2TextProvider = CLKSimpleTextProvider(text: className.description, shortText: className.shortDescription)
return template
}
UIColor parameter types are CGFloat, specified as a value from 0.0 to 1.0.
Because your RGB parameters are greater than 1, the color ends up being white, which would be:
UIColor(red: 1, green: 1, blue: 1, alpha: 1)
To fix this issue, simply change your tintColor to
headerTextProvider.tintColor = UIColor(red: 101/255, green: 153/255, blue: 255/255, alpha: 1)