Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
1
1weather
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Dmitriy Stepanets
1weather
Commits
4782e52f
Commit
4782e52f
authored
Feb 26, 2021
by
Dmitriy Stepanets
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Working on additional graphic
parent
b8dd6f8e
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
158 additions
and
196 deletions
+158
-196
1Weather.xcworkspace/xcuserdata/dstepanets.xcuserdatad/UserInterfaceState.xcuserstate
+0
-0
1Weather/UI/Helpers/GraphLine.swift
+45
-31
1Weather/UI/Helpers/GraphView.swift
+48
-144
1Weather/UI/View controllers/Today/Cells/CityForecastTimePeriod/CityForecastTimePeriodCell.swift
+41
-19
1Weather/UI/View controllers/Today/Cells/CityForecastTimePeriod/PeriodForecastButton.swift
+24
-2
No files found.
1Weather.xcworkspace/xcuserdata/dstepanets.xcuserdatad/UserInterfaceState.xcuserstate
View file @
4782e52f
No preview for this file type
1Weather/UI/Helpers/GraphLine.swift
View file @
4782e52f
...
@@ -17,23 +17,22 @@ struct GraphLine {
...
@@ -17,23 +17,22 @@ struct GraphLine {
//Private
//Private
private
static
let
cubicCurveAlgorithm
=
CubicCurveAlgorithm
()
private
static
let
cubicCurveAlgorithm
=
CubicCurveAlgorithm
()
private
let
kIntersectAccuracy
:
CGFloat
=
2
private
let
kIntersectAccuracy
:
CGFloat
=
2
private
let
points
:[
CGPoint
]
private
var
points
=
[
CGPoint
]()
private
let
tintColor
:
UIColor
private
let
settings
:
GraphLineSettings
private
let
graphViewRect
:
CGRect
private
let
onGetGraphRect
:
GraphRectClosure
private
var
sections
=
[
CubicCurve
]()
private
var
sections
=
[
CubicCurve
]()
//Public
//Public
let
lineShape
=
CAShapeLayer
()
public
typealias
GraphRectClosure
=
()
->
CGRect
private(set)
var
tintLineShape
=
CAShapeLayer
()
public
private(set)
var
lineShape
=
CAShapeLayer
()
private(set)
var
lineDots
=
[
LineDot
]()
public
private(set)
var
tintLineShape
=
CAShapeLayer
()
public
private(set)
var
lineDots
=
[
LineDot
]()
init
(
graphViewRect
:
CGRect
,
points
:[
CGPoint
],
settings
:
GraphLineSettings
)
{
init
(
settings
:
GraphLineSettings
,
onGetGraphRect
:
@escaping
GraphRectClosure
)
{
self
.
graphViewRect
=
graphViewRect
self
.
onGetGraphRect
=
onGetGraphRect
self
.
points
=
points
self
.
settings
=
settings
self
.
tintColor
=
settings
.
tintColor
//Line
//Line
lineShape
.
path
=
self
.
linePath
(
from
:
points
)
.
cgPath
lineShape
.
fillColor
=
UIColor
.
clear
.
cgColor
lineShape
.
fillColor
=
UIColor
.
clear
.
cgColor
lineShape
.
strokeColor
=
settings
.
color
.
cgColor
lineShape
.
strokeColor
=
settings
.
color
.
cgColor
lineShape
.
lineWidth
=
settings
.
lineWidth
lineShape
.
lineWidth
=
settings
.
lineWidth
...
@@ -53,26 +52,12 @@ struct GraphLine {
...
@@ -53,26 +52,12 @@ struct GraphLine {
tintLineShape
.
lineCap
=
.
round
tintLineShape
.
lineCap
=
.
round
tintLineShape
.
lineJoin
=
.
round
tintLineShape
.
lineJoin
=
.
round
tintLineShape
.
path
=
nil
tintLineShape
.
path
=
nil
//Dots
self
.
points
.
forEach
{
let
dotShape
=
CAShapeLayer
()
dotShape
.
path
=
UIBezierPath
(
arcCenter
:
$0
,
radius
:
settings
.
dotRadius
,
startAngle
:
0
,
endAngle
:
.
pi
*
2
,
clockwise
:
true
)
.
cgPath
dotShape
.
fillColor
=
UIColor
.
white
.
cgColor
dotShape
.
strokeColor
=
settings
.
color
.
cgColor
dotShape
.
lineWidth
=
settings
.
dotLineWidth
lineDots
.
append
(
.
init
(
center
:
$0
,
shape
:
dotShape
))
}
}
}
private
mutating
func
linePath
(
from
points
:[
CGPoint
])
->
UIBezierPath
{
private
mutating
func
linePath
(
from
points
:[
CGPoint
])
->
UIBezierPath
{
let
path
=
UIBezierPath
()
let
path
=
UIBezierPath
()
let
startPoint
=
CGPoint
(
x
:
0
,
y
:
self
.
graphViewRect
.
height
)
let
startPoint
=
CGPoint
(
x
:
0
,
y
:
self
.
onGetGraphRect
()
.
height
)
let
endPoint
=
CGPoint
(
x
:
self
.
graphViewRect
.
width
,
y
:
self
.
graphViewRect
.
height
)
let
endPoint
=
CGPoint
(
x
:
self
.
onGetGraphRect
()
.
width
,
y
:
self
.
onGetGraphRect
()
.
height
)
var
pointsToAdd
=
[
CGPoint
]()
var
pointsToAdd
=
[
CGPoint
]()
pointsToAdd
.
append
(
startPoint
)
pointsToAdd
.
append
(
startPoint
)
...
@@ -119,9 +104,9 @@ struct GraphLine {
...
@@ -119,9 +104,9 @@ struct GraphLine {
}
}
let
leftLine
=
LineSegment
(
p0
:
.
init
(
x
:
startPointX
+
kIntersectAccuracy
,
y
:
0
),
let
leftLine
=
LineSegment
(
p0
:
.
init
(
x
:
startPointX
+
kIntersectAccuracy
,
y
:
0
),
p1
:
.
init
(
x
:
startPointX
+
kIntersectAccuracy
,
y
:
self
.
graphViewRect
.
height
))
p1
:
.
init
(
x
:
startPointX
+
kIntersectAccuracy
,
y
:
self
.
onGetGraphRect
()
.
height
))
let
rightLine
=
LineSegment
(
p0
:
.
init
(
x
:
endPointX
-
kIntersectAccuracy
,
y
:
0
),
let
rightLine
=
LineSegment
(
p0
:
.
init
(
x
:
endPointX
-
kIntersectAccuracy
,
y
:
0
),
p1
:
.
init
(
x
:
endPointX
-
kIntersectAccuracy
,
y
:
self
.
graphViewRect
.
height
))
p1
:
.
init
(
x
:
endPointX
-
kIntersectAccuracy
,
y
:
self
.
onGetGraphRect
()
.
height
))
//Get all sections for the given tint and cut them
//Get all sections for the given tint and cut them
let
tintPath
=
UIBezierPath
()
let
tintPath
=
UIBezierPath
()
...
@@ -131,9 +116,9 @@ struct GraphLine {
...
@@ -131,9 +116,9 @@ struct GraphLine {
let
minRightPointX
=
min
(
section
.
endingPoint
.
x
,
rightLine
.
endingPoint
.
x
)
let
minRightPointX
=
min
(
section
.
endingPoint
.
x
,
rightLine
.
endingPoint
.
x
)
let
leftBoundary
=
LineSegment
(
p0
:
.
init
(
x
:
maxLeftPointX
,
y
:
0
),
let
leftBoundary
=
LineSegment
(
p0
:
.
init
(
x
:
maxLeftPointX
,
y
:
0
),
p1
:
.
init
(
x
:
maxLeftPointX
,
y
:
self
.
graphViewRect
.
height
))
p1
:
.
init
(
x
:
maxLeftPointX
,
y
:
self
.
onGetGraphRect
()
.
height
))
let
rightBoundary
=
LineSegment
(
p0
:
.
init
(
x
:
minRightPointX
,
y
:
0
),
let
rightBoundary
=
LineSegment
(
p0
:
.
init
(
x
:
minRightPointX
,
y
:
0
),
p1
:
.
init
(
x
:
minRightPointX
,
y
:
self
.
graphViewRect
.
height
))
p1
:
.
init
(
x
:
minRightPointX
,
y
:
self
.
onGetGraphRect
()
.
height
))
if
let
subcurve
=
getSubcurvePath
(
baseCurve
:
section
,
if
let
subcurve
=
getSubcurvePath
(
baseCurve
:
section
,
leftBoundary
:
leftBoundary
,
leftBoundary
:
leftBoundary
,
rightBoundary
:
rightBoundary
)
rightBoundary
:
rightBoundary
)
...
@@ -157,4 +142,33 @@ struct GraphLine {
...
@@ -157,4 +142,33 @@ struct GraphLine {
guard
let
dotToTint
=
(
lineDots
.
first
{
$0
.
center
==
point
})
else
{
return
}
guard
let
dotToTint
=
(
lineDots
.
first
{
$0
.
center
==
point
})
else
{
return
}
dotToTint
.
shape
.
strokeColor
=
ThemeManager
.
currentTheme
.
graphTintColor
.
cgColor
dotToTint
.
shape
.
strokeColor
=
ThemeManager
.
currentTheme
.
graphTintColor
.
cgColor
}
}
mutating
func
updateWith
(
points
:[
CGPoint
])
{
self
.
lineDots
.
forEach
{
$0
.
shape
.
removeFromSuperlayer
()
}
self
.
sections
.
removeAll
()
self
.
lineDots
.
removeAll
()
self
.
points
=
points
guard
!
self
.
points
.
isEmpty
else
{
return
}
//Add new dots
self
.
points
.
forEach
{
let
dotShape
=
CAShapeLayer
()
dotShape
.
path
=
UIBezierPath
(
arcCenter
:
$0
,
radius
:
settings
.
dotRadius
,
startAngle
:
0
,
endAngle
:
.
pi
*
2
,
clockwise
:
true
)
.
cgPath
dotShape
.
fillColor
=
UIColor
.
white
.
cgColor
dotShape
.
strokeColor
=
settings
.
color
.
cgColor
dotShape
.
lineWidth
=
settings
.
dotLineWidth
lineDots
.
append
(
.
init
(
center
:
$0
,
shape
:
dotShape
))
}
//Refresh line path
lineShape
.
path
=
self
.
linePath
(
from
:
points
)
.
cgPath
}
}
}
1Weather/UI/Helpers/GraphView.swift
View file @
4782e52f
...
@@ -10,22 +10,43 @@ import BezierKit
...
@@ -10,22 +10,43 @@ import BezierKit
class
GraphView
:
UIView
{
class
GraphView
:
UIView
{
//Private
//Private
private
let
kIntersectAccuracy
:
CGFloat
=
2
private
let
mainLineSettings
=
GraphLineSettings
(
lineWidth
:
3
,
private
let
kDotRadius
:
CGFloat
=
3
dotRadius
:
3
,
private
let
graphColor
:
UIColor
dotLineWidth
:
2
,
private
let
graphTintColor
:
UIColor
color
:
ThemeManager
.
currentTheme
.
graphColor
,
private
let
lineShape
=
CAShapeLayer
()
tintColor
:
ThemeManager
.
currentTheme
.
graphTintColor
)
private
let
tintShape
=
CAShapeLayer
()
private
let
additionalLineSettings
=
GraphLineSettings
(
lineWidth
:
2
,
private
var
lineDots
=
[
LineDot
]()
dotRadius
:
2
,
private
let
cubicCurveAlgorithm
=
CubicCurveAlgorithm
()
dotLineWidth
:
1
/
UIScreen
.
main
.
scale
,
private
var
sections
=
[
CubicCurve
]()
color
:
UIColor
(
hex
:
0xa4a4a4
)
.
withAlphaComponent
(
0.7
),
tintColor
:
UIColor
(
hex
:
0x434343
)
.
withAlphaComponent
(
0.7
))
private
lazy
var
mainLine
:
GraphLine
=
{
let
line
=
GraphLine
(
settings
:
mainLineSettings
,
onGetGraphRect
:
{
return
self
.
frame
})
return
line
}()
private
lazy
var
additionalLine
:
GraphLine
=
{
let
line
=
GraphLine
(
settings
:
additionalLineSettings
,
onGetGraphRect
:
{
return
self
.
frame
})
return
line
}()
//MARK:- View life cycle
//MARK:- View life cycle
init
(
graphColor
:
UIColor
,
tintColor
:
UIColor
)
{
init
()
{
self
.
graphColor
=
graphColor
self
.
graphTintColor
=
tintColor
super
.
init
(
frame
:
.
zero
)
super
.
init
(
frame
:
.
zero
)
self
.
isUserInteractionEnabled
=
false
self
.
isUserInteractionEnabled
=
false
//Adding lines
layer
.
insertSublayer
(
mainLine
.
lineShape
,
at
:
0
)
layer
.
insertSublayer
(
mainLine
.
tintLineShape
,
at
:
1
)
layer
.
insertSublayer
(
additionalLine
.
lineShape
,
at
:
0
)
layer
.
insertSublayer
(
additionalLine
.
tintLineShape
,
at
:
0
)
}
}
required
init
?(
coder
:
NSCoder
)
{
required
init
?(
coder
:
NSCoder
)
{
...
@@ -33,147 +54,30 @@ class GraphView: UIView {
...
@@ -33,147 +54,30 @@ class GraphView: UIView {
}
}
//Public
//Public
public
func
drawGraph
(
with
points
:[
CGPoint
])
{
public
func
drawMainGraph
(
with
points
:[
CGPoint
])
{
//Clean up
mainLine
.
updateWith
(
points
:
points
)
self
.
layer
.
sublayers
?
.
forEach
{
mainLine
.
lineDots
.
forEach
{
$0
.
removeFromSuperlayer
()
layer
.
addSublayer
(
$0
.
shape
)
}
sections
.
removeAll
()
lineDots
.
removeAll
()
guard
!
points
.
isEmpty
else
{
return
}
//Add points
points
.
forEach
{
self
.
addDot
(
point
:
$0
)
}
}
//Add line
lineShape
.
frame
=
self
.
bounds
lineShape
.
path
=
self
.
linePath
(
from
:
points
)
.
cgPath
lineShape
.
fillColor
=
UIColor
.
clear
.
cgColor
lineShape
.
strokeColor
=
graphColor
.
cgColor
lineShape
.
lineWidth
=
3
lineShape
.
lineCap
=
.
round
lineShape
.
lineJoin
=
.
round
//Shadow
lineShape
.
shadowColor
=
UIColor
.
black
.
cgColor
lineShape
.
shadowOffset
=
.
init
(
width
:
0
,
height
:
6
)
lineShape
.
shadowRadius
=
3
lineShape
.
shadowOpacity
=
0.1
layer
.
insertSublayer
(
lineShape
,
at
:
0
)
}
}
public
func
tintGraphFrom
(
startPointX
:
CGFloat
,
endPointX
:
CGFloat
)
{
public
func
drawAdditionalGraph
(
with
points
:[
CGPoint
])
{
func
getSubcurvePath
(
baseCurve
:
CubicCurve
,
leftBoundary
:
LineSegment
,
rightBoundary
:
LineSegment
)
->
UIBezierPath
?
{
additionalLine
.
updateWith
(
points
:
points
)
guard
additionalLine
.
lineDots
.
forEach
{
let
leftIntersection
=
baseCurve
.
intersections
(
with
:
leftBoundary
)
.
first
,
layer
.
addSublayer
(
$0
.
shape
)
let
rightIntersection
=
baseCurve
.
intersections
(
with
:
rightBoundary
)
.
first
else
{
return
nil
}
let
subcurve
=
baseCurve
.
split
(
from
:
leftIntersection
.
t1
,
to
:
rightIntersection
.
t1
)
let
path
=
UIBezierPath
()
path
.
move
(
to
:
subcurve
.
startingPoint
)
path
.
addCurve
(
to
:
subcurve
.
endingPoint
,
controlPoint1
:
subcurve
.
p1
,
controlPoint2
:
subcurve
.
p2
)
return
path
}
let
leftLine
=
LineSegment
(
p0
:
.
init
(
x
:
startPointX
+
kIntersectAccuracy
,
y
:
0
),
p1
:
.
init
(
x
:
startPointX
+
kIntersectAccuracy
,
y
:
self
.
bounds
.
height
))
let
rightLine
=
LineSegment
(
p0
:
.
init
(
x
:
endPointX
-
kIntersectAccuracy
,
y
:
0
),
p1
:
.
init
(
x
:
endPointX
-
kIntersectAccuracy
,
y
:
self
.
bounds
.
height
))
//Get all sections for the given tint and cut them
let
tintPath
=
UIBezierPath
()
for
section
in
sections
{
if
section
.
startingPoint
.
x
>=
leftLine
.
p0
.
x
||
section
.
endingPoint
.
x
<=
rightLine
.
p0
.
x
{
let
maxLeftPointX
=
max
(
section
.
startingPoint
.
x
,
leftLine
.
startingPoint
.
x
)
let
minRightPointX
=
min
(
section
.
endingPoint
.
x
,
rightLine
.
endingPoint
.
x
)
let
leftBoundary
=
LineSegment
(
p0
:
.
init
(
x
:
maxLeftPointX
,
y
:
0
),
p1
:
.
init
(
x
:
maxLeftPointX
,
y
:
self
.
bounds
.
height
))
let
rightBoundary
=
LineSegment
(
p0
:
.
init
(
x
:
minRightPointX
,
y
:
0
),
p1
:
.
init
(
x
:
minRightPointX
,
y
:
self
.
bounds
.
height
))
if
let
subcurve
=
getSubcurvePath
(
baseCurve
:
section
,
leftBoundary
:
leftBoundary
,
rightBoundary
:
rightBoundary
)
{
tintPath
.
append
(
subcurve
)
}
}
}
//Check for empty path
if
tintPath
.
isEmpty
{
return
}
tintShape
.
path
=
tintPath
.
cgPath
if
tintShape
.
superlayer
==
nil
{
tintShape
.
fillColor
=
UIColor
.
clear
.
cgColor
tintShape
.
strokeColor
=
ThemeManager
.
currentTheme
.
graphTintColor
.
cgColor
tintShape
.
lineWidth
=
3
tintShape
.
lineCap
=
.
round
tintShape
.
lineJoin
=
.
round
layer
.
insertSublayer
(
tintShape
,
at
:
1
)
}
}
}
}
public
func
tintDot
(
at
:
CGPoint
)
{
public
func
tintGraphFrom
(
startPointX
:
CGFloat
,
endPointX
:
CGFloat
)
{
lineDots
.
forEach
{
mainLine
.
tintLineFrom
(
startPointX
:
startPointX
,
to
:
endPointX
)
$0
.
shape
.
strokeColor
=
ThemeManager
.
currentTheme
.
graphColor
.
cgColor
additionalLine
.
tintLineFrom
(
startPointX
:
startPointX
,
to
:
endPointX
)
}
guard
let
dotToTint
=
(
lineDots
.
first
{
$0
.
center
==
at
})
else
{
return
}
dotToTint
.
shape
.
strokeColor
=
ThemeManager
.
currentTheme
.
graphTintColor
.
cgColor
}
}
//Private
public
func
tintMainDotAt
(
point
:
CGPoint
)
{
private
func
linePath
(
from
points
:[
CGPoint
])
->
UIBezierPath
{
mainLine
.
tintDotAt
(
point
:
point
)
let
path
=
UIBezierPath
()
let
startPoint
=
CGPoint
(
x
:
0
,
y
:
self
.
frame
.
height
)
let
endPoint
=
CGPoint
(
x
:
self
.
frame
.
width
,
y
:
self
.
frame
.
height
)
var
pointsToAdd
=
[
CGPoint
]()
pointsToAdd
.
append
(
startPoint
)
pointsToAdd
.
append
(
contentsOf
:
points
)
pointsToAdd
.
append
(
endPoint
)
path
.
move
(
to
:
pointsToAdd
.
first
!
)
if
pointsToAdd
.
count
==
2
{
path
.
addLine
(
to
:
points
[
1
])
return
path
}
let
controlPoints
=
cubicCurveAlgorithm
.
controlPointsFromPoints
(
dataPoints
:
pointsToAdd
)
for
index
in
1
..<
pointsToAdd
.
count
{
sections
.
append
(
.
init
(
p0
:
pointsToAdd
[
index
-
1
],
p1
:
controlPoints
[
index
-
1
]
.
controlPoint1
,
p2
:
controlPoints
[
index
-
1
]
.
controlPoint2
,
p3
:
pointsToAdd
[
index
]))
path
.
addCurve
(
to
:
pointsToAdd
[
index
],
controlPoint1
:
controlPoints
[
index
-
1
]
.
controlPoint1
,
controlPoint2
:
controlPoints
[
index
-
1
]
.
controlPoint2
)
}
return
path
}
}
private
func
addDot
(
point
:
CGPoint
)
{
public
func
tintAdditionalDotAt
(
point
:
CGPoint
)
{
let
dotShape
=
CAShapeLayer
()
additionalLine
.
tintDotAt
(
point
:
point
)
dotShape
.
path
=
UIBezierPath
(
arcCenter
:
point
,
radius
:
kDotRadius
,
startAngle
:
0
,
endAngle
:
.
pi
*
2
,
clockwise
:
true
)
.
cgPath
dotShape
.
fillColor
=
UIColor
.
white
.
cgColor
dotShape
.
strokeColor
=
self
.
graphColor
.
cgColor
dotShape
.
lineWidth
=
2
lineDots
.
append
(
.
init
(
center
:
point
,
shape
:
dotShape
))
layer
.
addSublayer
(
dotShape
)
}
}
}
}
1Weather/UI/View controllers/Today/Cells/CityForecastTimePeriod/CityForecastTimePeriodCell.swift
View file @
4782e52f
...
@@ -7,22 +7,34 @@
...
@@ -7,22 +7,34 @@
import
UIKit
import
UIKit
struct
DayTemp
{
let
min
:
CGFloat
let
max
:
CGFloat
}
class
CityForecastTimePeriodCell
:
UITableViewCell
{
class
CityForecastTimePeriodCell
:
UITableViewCell
{
static
let
kIdentifier
=
"cityForecastTimePeriodCell"
static
let
kIdentifier
=
"cityForecastTimePeriodCell"
//Private
//Private
private
let
periodSegmentedControl
=
ForecastTimePeriodControl
(
items
:
[
"forecast.timePeriod.daily"
.
localized
(),
private
let
periodSegmentedControl
=
ForecastTimePeriodControl
(
items
:
[
"forecast.timePeriod.daily"
.
localized
(),
"forecast.timePeriod.hourly"
.
localized
()])
"forecast.timePeriod.hourly"
.
localized
()])
private
let
kMinGraphHeight
:
CGFloat
=
5
0
private
let
kMinGraphHeight
:
CGFloat
=
2
0
private
let
scrollView
=
UIScrollView
()
private
let
scrollView
=
UIScrollView
()
private
let
stackView
=
UIStackView
()
private
let
stackView
=
UIStackView
()
private
let
summaryView
=
UIView
()
private
let
summaryView
=
UIView
()
private
let
summaryImageView
=
UIImageView
()
private
let
summaryImageView
=
UIImageView
()
private
let
summaryLabel
=
UILabel
()
private
let
summaryLabel
=
UILabel
()
private
var
graphPoints
=
[
CGPoint
]()
private
var
maxTempGraphPoints
=
[
CGPoint
]()
private
let
graphView
=
GraphView
(
graphColor
:
ThemeManager
.
currentTheme
.
graphColor
,
private
var
minTempGraphPoints
=
[
CGPoint
]()
tintColor
:
ThemeManager
.
currentTheme
.
graphTintColor
)
private
let
graphView
=
GraphView
()
private
let
tempsArray
=
[
20
,
18
,
25
,
24
,
22
,
20
,
23
,
25
,
27
,
26
,
23
,
20
]
private
let
dayTemps
=
[
DayTemp
(
min
:
8
,
max
:
17
),
DayTemp
(
min
:
9
,
max
:
17
),
DayTemp
(
min
:
7
,
max
:
18
),
DayTemp
(
min
:
7
,
max
:
17
),
DayTemp
(
min
:
8
,
max
:
17
),
DayTemp
(
min
:
8
,
max
:
18
),
DayTemp
(
min
:
9
,
max
:
18
),
DayTemp
(
min
:
8
,
max
:
16
)]
private
var
graphIsDrawn
=
false
private
var
graphIsDrawn
=
false
override
init
(
style
:
UITableViewCell
.
CellStyle
,
reuseIdentifier
:
String
?)
{
override
init
(
style
:
UITableViewCell
.
CellStyle
,
reuseIdentifier
:
String
?)
{
...
@@ -57,7 +69,7 @@ class CityForecastTimePeriodCell: UITableViewCell {
...
@@ -57,7 +69,7 @@ class CityForecastTimePeriodCell: UITableViewCell {
width
:
scrollView
.
contentSize
.
width
,
width
:
scrollView
.
contentSize
.
width
,
height
:
periodButton
.
graphRect
.
height
)
height
:
periodButton
.
graphRect
.
height
)
graphPoints
=
get
GraphPoints
()
update
GraphPoints
()
drawGraph
()
drawGraph
()
graphIsDrawn
=
true
graphIsDrawn
=
true
}
}
...
@@ -71,7 +83,8 @@ class CityForecastTimePeriodCell: UITableViewCell {
...
@@ -71,7 +83,8 @@ class CityForecastTimePeriodCell: UITableViewCell {
return
return
}
}
self
.
graphView
.
drawGraph
(
with
:
graphPoints
)
self
.
graphView
.
drawMainGraph
(
with
:
maxTempGraphPoints
)
self
.
graphView
.
drawAdditionalGraph
(
with
:
minTempGraphPoints
)
self
.
tintGraphAt
(
button
:
selectedButton
)
self
.
tintGraphAt
(
button
:
selectedButton
)
print
(
"Draw graph!"
)
print
(
"Draw graph!"
)
}
}
...
@@ -79,31 +92,39 @@ class CityForecastTimePeriodCell: UITableViewCell {
...
@@ -79,31 +92,39 @@ class CityForecastTimePeriodCell: UITableViewCell {
private
func
tintGraphAt
(
button
:
PeriodForecastButton
)
{
private
func
tintGraphAt
(
button
:
PeriodForecastButton
)
{
self
.
graphView
.
tintGraphFrom
(
startPointX
:
button
.
frame
.
origin
.
x
,
self
.
graphView
.
tintGraphFrom
(
startPointX
:
button
.
frame
.
origin
.
x
,
endPointX
:
button
.
frame
.
origin
.
x
+
button
.
bounds
.
width
)
endPointX
:
button
.
frame
.
origin
.
x
+
button
.
bounds
.
width
)
self
.
graphView
.
tintDot
(
at
:
graphPoints
[
button
.
index
])
self
.
graphView
.
tintMainDotAt
(
point
:
maxTempGraphPoints
[
button
.
index
])
self
.
graphView
.
tintAdditionalDotAt
(
point
:
minTempGraphPoints
[
button
.
index
])
}
}
private
func
getGraphPoints
()
->
[
CGPoint
]
{
private
func
updateGraphPoints
(){
var
points
=
[
CGPoint
]()
self
.
maxTempGraphPoints
.
removeAll
()
let
maxTemp
=
CGFloat
(
tempsArray
.
max
()
??
0
)
self
.
minTempGraphPoints
.
removeAll
()
let
minTemp
=
CGFloat
(
tempsArray
.
min
()
??
0
)
for
index
in
0
..<
stackView
.
arrangedSubviews
.
count
{
let
maxTemp
=
CGFloat
(
dayTemps
.
map
{
$0
.
max
}
.
max
()
??
0
)
let
minTemp
=
CGFloat
(
dayTemps
.
map
{
$0
.
min
}
.
min
()
??
0
)
for
index
in
0
..<
dayTemps
.
count
{
guard
let
stackButton
=
stackView
.
arrangedSubviews
[
index
]
as?
PeriodForecastButton
else
{
continue
}
guard
let
stackButton
=
stackView
.
arrangedSubviews
[
index
]
as?
PeriodForecastButton
else
{
continue
}
let
buttonRightSide
=
stackButton
.
frame
.
origin
.
x
+
stackButton
.
bounds
.
width
let
buttonRightSide
=
stackButton
.
frame
.
origin
.
x
+
stackButton
.
bounds
.
width
let
buttonCenterX
=
(
buttonRightSide
+
stackButton
.
frame
.
origin
.
x
)
/
2
let
buttonCenterX
=
(
buttonRightSide
+
stackButton
.
frame
.
origin
.
x
)
/
2
let
numberOfLevels
=
maxTemp
-
minTemp
let
numberOfLevels
=
maxTemp
-
minTemp
let
levelHeight
=
(
graphView
.
frame
.
height
/
numberOfLevels
)
.
rounded
(
.
down
)
let
levelHeight
=
(
graphView
.
frame
.
height
/
numberOfLevels
)
.
rounded
(
.
down
)
var
pointLevel
=
(
maxTemp
-
CGFloat
(
tempsArray
[
index
]))
*
levelHeight
var
maxPointLevel
=
(
maxTemp
-
dayTemps
[
index
]
.
max
)
*
levelHeight
var
minPointLevel
=
(
minTemp
+
dayTemps
[
index
]
.
min
)
*
levelHeight
//Add points offset at cirle radius if needed
//Add points offset at cirle radius if needed
pointLevel
=
max
(
pointLevel
,
5
)
maxPointLevel
=
max
(
maxPointLevel
,
5
)
pointLevel
=
min
(
pointLevel
,
graphView
.
frame
.
height
-
5
)
maxPointLevel
=
min
(
maxPointLevel
,
graphView
.
frame
.
height
-
5
)
minPointLevel
=
min
(
minPointLevel
,
5
)
minPointLevel
=
max
(
minPointLevel
,
graphView
.
frame
.
height
-
5
)
points
.
append
(
.
init
(
x
:
buttonCenterX
,
y
:
pointLevel
))
maxTempGraphPoints
.
append
(
.
init
(
x
:
buttonCenterX
,
y
:
maxPointLevel
))
minTempGraphPoints
.
append
(
.
init
(
x
:
buttonCenterX
,
y
:
minPointLevel
))
}
}
return
points
print
(
"break"
)
}
}
@objc
private
func
handleConditionButton
(
button
:
PeriodForecastButton
)
{
@objc
private
func
handleConditionButton
(
button
:
PeriodForecastButton
)
{
...
@@ -164,8 +185,9 @@ private extension CityForecastTimePeriodCell {
...
@@ -164,8 +185,9 @@ private extension CityForecastTimePeriodCell {
make
.
edges
.
height
.
equalToSuperview
()
make
.
edges
.
height
.
equalToSuperview
()
}
}
for
index
in
0
..<
12
{
for
index
in
0
..<
dayTemps
.
count
{
let
conditionButton
=
PeriodForecastButton
()
let
conditionButton
=
PeriodForecastButton
()
conditionButton
.
configure
(
dayTemp
:
dayTemps
[
index
])
conditionButton
.
index
=
index
conditionButton
.
index
=
index
conditionButton
.
addTarget
(
self
,
action
:
#selector(
handleConditionButton(button:)
)
,
for
:
.
touchUpInside
)
conditionButton
.
addTarget
(
self
,
action
:
#selector(
handleConditionButton(button:)
)
,
for
:
.
touchUpInside
)
conditionButton
.
isSelected
=
index
==
1
conditionButton
.
isSelected
=
index
==
1
...
...
1Weather/UI/View controllers/Today/Cells/CityForecastTimePeriod/PeriodForecastButton.swift
View file @
4782e52f
...
@@ -13,6 +13,7 @@ class PeriodForecastButton: UIControl {
...
@@ -13,6 +13,7 @@ class PeriodForecastButton: UIControl {
private
let
forecastImageView
=
UIImageView
()
private
let
forecastImageView
=
UIImageView
()
private
let
tempLabel
=
UILabel
()
private
let
tempLabel
=
UILabel
()
private
let
indicatorImageView
=
UIImageView
()
private
let
indicatorImageView
=
UIImageView
()
private
let
minTempLabel
=
UILabel
()
private
let
timeLabel
=
UILabel
()
private
let
timeLabel
=
UILabel
()
//Public
//Public
...
@@ -23,7 +24,7 @@ class PeriodForecastButton: UIControl {
...
@@ -23,7 +24,7 @@ class PeriodForecastButton: UIControl {
return
.
init
(
x
:
0
,
return
.
init
(
x
:
0
,
y
:
topInset
,
y
:
topInset
,
width
:
self
.
bounds
.
width
,
width
:
self
.
bounds
.
width
,
height
:
self
.
indicatorImageView
.
frame
.
origin
.
y
-
topInset
-
kGraphInset
)
height
:
self
.
minTempLabel
.
frame
.
origin
.
y
-
topInset
-
kGraphInset
)
}
}
override
init
(
frame
:
CGRect
)
{
override
init
(
frame
:
CGRect
)
{
...
@@ -32,6 +33,7 @@ class PeriodForecastButton: UIControl {
...
@@ -32,6 +33,7 @@ class PeriodForecastButton: UIControl {
prepareButton
()
prepareButton
()
prepareForecastImage
()
prepareForecastImage
()
prepareTempLabel
()
prepareTempLabel
()
prepareMinTempLabel
()
preparePeriodIndicator
()
preparePeriodIndicator
()
prepareTimeLabel
()
prepareTimeLabel
()
}
}
...
@@ -45,6 +47,7 @@ class PeriodForecastButton: UIControl {
...
@@ -45,6 +47,7 @@ class PeriodForecastButton: UIControl {
if
isSelected
{
if
isSelected
{
self
.
backgroundColor
=
UIColor
.
white
self
.
backgroundColor
=
UIColor
.
white
self
.
tempLabel
.
font
=
AppFont
.
SFPro
.
bold
(
size
:
16
)
self
.
tempLabel
.
font
=
AppFont
.
SFPro
.
bold
(
size
:
16
)
self
.
minTempLabel
.
font
=
AppFont
.
SFPro
.
bold
(
size
:
12
)
self
.
timeLabel
.
font
=
AppFont
.
SFPro
.
bold
(
size
:
12
)
self
.
timeLabel
.
font
=
AppFont
.
SFPro
.
bold
(
size
:
12
)
self
.
indicatorImageView
.
alpha
=
1.0
self
.
indicatorImageView
.
alpha
=
1.0
self
.
layer
.
shadowColor
=
UIColor
(
hex
:
0xe5e6f4
)
.
cgColor
self
.
layer
.
shadowColor
=
UIColor
(
hex
:
0xe5e6f4
)
.
cgColor
...
@@ -55,6 +58,7 @@ class PeriodForecastButton: UIControl {
...
@@ -55,6 +58,7 @@ class PeriodForecastButton: UIControl {
else
{
else
{
self
.
backgroundColor
=
UIColor
.
white
.
withAlphaComponent
(
0.5
)
self
.
backgroundColor
=
UIColor
.
white
.
withAlphaComponent
(
0.5
)
self
.
tempLabel
.
font
=
AppFont
.
SFPro
.
regular
(
size
:
16
)
self
.
tempLabel
.
font
=
AppFont
.
SFPro
.
regular
(
size
:
16
)
self
.
minTempLabel
.
font
=
AppFont
.
SFPro
.
regular
(
size
:
12
)
self
.
timeLabel
.
font
=
AppFont
.
SFPro
.
regular
(
size
:
12
)
self
.
timeLabel
.
font
=
AppFont
.
SFPro
.
regular
(
size
:
12
)
self
.
indicatorImageView
.
alpha
=
0.5
self
.
indicatorImageView
.
alpha
=
0.5
self
.
layer
.
shadowColor
=
UIColor
.
clear
.
cgColor
self
.
layer
.
shadowColor
=
UIColor
.
clear
.
cgColor
...
@@ -64,6 +68,12 @@ class PeriodForecastButton: UIControl {
...
@@ -64,6 +68,12 @@ class PeriodForecastButton: UIControl {
}
}
}
}
}
}
//Public
public
func
configure
(
dayTemp
:
DayTemp
)
{
self
.
tempLabel
.
text
=
"
\(
Int
(
dayTemp
.
max
)
)
°"
self
.
minTempLabel
.
text
=
"
\(
Int
(
dayTemp
.
min
)
)
°"
}
}
}
private
extension
PeriodForecastButton
{
private
extension
PeriodForecastButton
{
...
@@ -101,6 +111,18 @@ private extension PeriodForecastButton {
...
@@ -101,6 +111,18 @@ private extension PeriodForecastButton {
}
}
}
}
func
prepareMinTempLabel
()
{
minTempLabel
.
isUserInteractionEnabled
=
false
minTempLabel
.
font
=
AppFont
.
SFPro
.
regular
(
size
:
12
)
minTempLabel
.
textColor
=
ThemeManager
.
currentTheme
.
secondaryTextColor
addSubview
(
minTempLabel
)
minTempLabel
.
snp
.
makeConstraints
{
(
make
)
in
make
.
centerX
.
equalToSuperview
()
make
.
top
.
greaterThanOrEqualTo
(
tempLabel
.
snp
.
bottom
)
.
offset
(
55
)
}
}
func
preparePeriodIndicator
()
{
func
preparePeriodIndicator
()
{
indicatorImageView
.
isUserInteractionEnabled
=
false
indicatorImageView
.
isUserInteractionEnabled
=
false
indicatorImageView
.
contentMode
=
.
scaleAspectFit
indicatorImageView
.
contentMode
=
.
scaleAspectFit
...
@@ -110,7 +132,7 @@ private extension PeriodForecastButton {
...
@@ -110,7 +132,7 @@ private extension PeriodForecastButton {
indicatorImageView
.
snp
.
makeConstraints
{
(
make
)
in
indicatorImageView
.
snp
.
makeConstraints
{
(
make
)
in
make
.
width
.
height
.
equalTo
(
12
)
make
.
width
.
height
.
equalTo
(
12
)
make
.
centerX
.
equalToSuperview
()
make
.
centerX
.
equalToSuperview
()
make
.
top
.
greaterThanOrEqualTo
(
tempLabel
.
snp
.
bottom
)
.
offset
(
10
0
)
make
.
top
.
equalTo
(
minTempLabel
.
snp
.
bottom
)
.
offset
(
1
0
)
}
}
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment