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
ad821a19
Commit
ad821a19
authored
Apr 01, 2021
by
Dmitriy Stepanets
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added AirQuality UI
parent
ce7fd2d1
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
225 additions
and
32 deletions
+225
-32
1Weather.xcodeproj/project.pbxproj
+4
-0
1Weather.xcworkspace/xcuserdata/dstepanets.xcuserdatad/UserInterfaceState.xcuserstate
+0
-0
1Weather/UI/View controllers/Today/Cells/TodayAirQualityCell/AirQualityView.swift
+78
-0
1Weather/UI/View controllers/Today/Cells/TodayAirQualityCell/PollutantView.swift
+102
-0
1Weather/UI/View controllers/Today/Cells/TodayAirQualityCell/TodayAirQualityCell.swift
+28
-30
1Weather/UI/View controllers/Today/Cells/TodayCellFactory.swift
+13
-2
No files found.
1Weather.xcodeproj/project.pbxproj
View file @
ad821a19
...
...
@@ -59,6 +59,7 @@
CD3F6E6925FA59D4002DB99B
/* ForecastDetailPeriodButton.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD3F6E6825FA59D4002DB99B
/* ForecastDetailPeriodButton.swift */
;
};
CD3F6E6C25FA5A90002DB99B
/* PeriodButtonProtocol.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD3F6E6B25FA5A90002DB99B
/* PeriodButtonProtocol.swift */
;
};
CD4742D0261200500061AC95
/* TodayAlertCell.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD4742CF261200500061AC95
/* TodayAlertCell.swift */
;
};
CD55E0BB2615EE2400CC4DC7
/* PollutantView.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD55E0BA2615EE2400CC4DC7
/* PollutantView.swift */
;
};
CD593BC226088A5900C93428
/* TimePeriodOffsetHolder.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD593BC126088A5900C93428
/* TimePeriodOffsetHolder.swift */
;
};
CD593BC926089FC100C93428
/* UITableView+HeaderSize.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD593BC826089FC100C93428
/* UITableView+HeaderSize.swift */
;
};
CD593BCC2608A4F200C93428
/* ForecastDailyCell.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD593BCB2608A4F200C93428
/* ForecastDailyCell.swift */
;
};
...
...
@@ -215,6 +216,7 @@
CD3F6E6825FA59D4002DB99B
/* ForecastDetailPeriodButton.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
ForecastDetailPeriodButton.swift
;
sourceTree
=
"<group>"
;
};
CD3F6E6B25FA5A90002DB99B
/* PeriodButtonProtocol.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
PeriodButtonProtocol.swift
;
sourceTree
=
"<group>"
;
};
CD4742CF261200500061AC95
/* TodayAlertCell.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
TodayAlertCell.swift
;
sourceTree
=
"<group>"
;
};
CD55E0BA2615EE2400CC4DC7
/* PollutantView.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
PollutantView.swift
;
sourceTree
=
"<group>"
;
};
CD593BC126088A5900C93428
/* TimePeriodOffsetHolder.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
TimePeriodOffsetHolder.swift
;
sourceTree
=
"<group>"
;
};
CD593BC826089FC100C93428
/* UITableView+HeaderSize.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
"UITableView+HeaderSize.swift"
;
sourceTree
=
"<group>"
;
};
CD593BCB2608A4F200C93428
/* ForecastDailyCell.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
ForecastDailyCell.swift
;
sourceTree
=
"<group>"
;
};
...
...
@@ -669,6 +671,7 @@
isa
=
PBXGroup
;
children
=
(
CDC6125625E7AB1A00188DA7
/* TodayAirQualityCell.swift */
,
CD55E0BA2615EE2400CC4DC7
/* PollutantView.swift */
,
);
path
=
TodayAirQualityCell
;
sourceTree
=
"<group>"
;
...
...
@@ -1146,6 +1149,7 @@
CDF9BF8E26133D050037847D
/* LocationSearchCoordinator.swift in Sources */
,
CD86246125E662BC0097F3FB
/* SunUvLineView.swift in Sources */
,
CD32CE0B260C744A00235081
/* MenuCoordinator.swift in Sources */
,
CD55E0BB2615EE2400CC4DC7
/* PollutantView.swift in Sources */
,
CEC526FA25E7959A00DA58A5
/* WeatherSource.swift in Sources */
,
CD37D3DE260C9E37002669D6
/* MenuCell.swift in Sources */
,
CD822FFE25D6976F00A05501
/* TodayAdCell.swift in Sources */
,
...
...
1Weather.xcworkspace/xcuserdata/dstepanets.xcuserdatad/UserInterfaceState.xcuserstate
View file @
ad821a19
No preview for this file type
1Weather/UI/View controllers/Today/Cells/TodayAirQualityCell/AirQualityView.swift
0 → 100644
View file @
ad821a19
//
// PollutionView.swift
// 1Weather
//
// Created by Dmitry Stepanets on 01.04.2021.
//
import
UIKit
class
PollutionView
:
UIView
{
//Private
private
let
typeLabel
=
UILabel
()
private
let
valueLabel
=
UILabel
()
private
let
statusLabel
=
UILabel
()
private
let
progressContainer
=
UIView
()
private
let
progressGradient
=
CAGradientLayer
()
init
()
{
super
.
init
(
frame
:
.
zero
)
prepareLabels
()
prepareProgress
()
}
func
configure
(
pollutant
:
Pollutant
)
{
typeLabel
.
text
=
pollutant
.
name
.
localized
valueLabel
.
text
=
"
\(
pollutant
.
value
)
"
statusLabel
.
text
=
pollutant
.
status
.
localized
}
required
init
?(
coder
:
NSCoder
)
{
fatalError
(
"init(coder:) has not been implemented"
)
}
}
//MRAK:- Prepare
private
extension
PollutionView
{
func
prepareLabels
()
{
typeLabel
.
font
=
AppFont
.
SFPro
.
bold
(
size
:
18
)
addSubview
(
typeLabel
)
valueLabel
.
font
=
AppFont
.
SFPro
.
bold
(
size
:
18
)
addSubview
(
valueLabel
)
statusLabel
.
textAlignment
=
.
right
statusLabel
.
font
=
AppFont
.
SFPro
.
bold
(
size
:
14
)
addSubview
(
statusLabel
)
//Constraints
typeLabel
.
snp
.
makeConstraints
{
(
make
)
in
make
.
left
.
equalToSuperview
()
make
.
top
.
equalToSuperview
()
.
inset
(
15
)
}
valueLabel
.
snp
.
makeConstraints
{
(
make
)
in
make
.
left
.
equalTo
(
typeLabel
.
snp
.
right
)
.
offset
(
30
)
make
.
centerY
.
equalTo
(
typeLabel
)
}
statusLabel
.
snp
.
makeConstraints
{
(
make
)
in
make
.
right
.
equalToSuperview
()
make
.
centerY
.
equalTo
(
typeLabel
)
}
}
func
prepareProgress
()
{
progressContainer
.
layer
.
cornerRadius
=
2
progressContainer
.
backgroundColor
=
UIColor
(
hex
:
0xe9ebfc
)
addSubview
(
progressContainer
)
progressContainer
.
snp
.
makeConstraints
{
(
make
)
in
make
.
height
.
equalTo
(
4
)
make
.
left
.
right
.
equalToSuperview
()
make
.
top
.
equalTo
(
typeLabel
.
snp
.
bottom
)
.
offset
(
18
)
make
.
bottom
.
equalToSuperview
()
.
inset
(
15
)
}
}
}
1Weather/UI/View controllers/Today/Cells/TodayAirQualityCell/PollutantView.swift
0 → 100644
View file @
ad821a19
//
// PollutantView.swift
// 1Weather
//
// Created by Dmitry Stepanets on 01.04.2021.
//
import
UIKit
class
PollutantView
:
UIView
{
//Private
private
let
typeLabel
=
UILabel
()
private
let
valueLabel
=
UILabel
()
private
let
statusLabel
=
UILabel
()
private
let
progressContainer
=
UIView
()
private
let
progressGradient
=
CAGradientLayer
()
init
()
{
super
.
init
(
frame
:
.
zero
)
prepareLabels
()
prepareProgress
()
updateUI
()
}
required
init
?(
coder
:
NSCoder
)
{
fatalError
(
"init(coder:) has not been implemented"
)
}
override
func
traitCollectionDidChange
(
_
previousTraitCollection
:
UITraitCollection
?)
{
super
.
traitCollectionDidChange
(
previousTraitCollection
)
updateUI
()
}
func
configure
(
pollutant
:
Pollutant
)
{
typeLabel
.
text
=
pollutant
.
name
.
localized
valueLabel
.
text
=
"
\(
Int
(
pollutant
.
value
)
)
"
statusLabel
.
text
=
pollutant
.
status
.
localized
}
private
func
updateUI
()
{
switch
interfaceStyle
{
case
.
light
:
typeLabel
.
textColor
=
ThemeManager
.
currentTheme
.
secondaryTextColor
valueLabel
.
textColor
=
ThemeManager
.
currentTheme
.
secondaryTextColor
statusLabel
.
textColor
=
ThemeManager
.
currentTheme
.
secondaryTextColor
case
.
dark
:
typeLabel
.
textColor
=
ThemeManager
.
currentTheme
.
primaryTextColor
valueLabel
.
textColor
=
ThemeManager
.
currentTheme
.
primaryTextColor
statusLabel
.
textColor
=
ThemeManager
.
currentTheme
.
primaryTextColor
}
}
}
//MRAK:- Prepare
private
extension
PollutantView
{
func
prepareLabels
()
{
typeLabel
.
font
=
AppFont
.
SFPro
.
bold
(
size
:
18
)
typeLabel
.
setContentHuggingPriority
(
.
fittingSizeLevel
,
for
:
.
vertical
)
addSubview
(
typeLabel
)
valueLabel
.
font
=
AppFont
.
SFPro
.
bold
(
size
:
18
)
addSubview
(
valueLabel
)
statusLabel
.
lineBreakMode
=
.
byWordWrapping
statusLabel
.
numberOfLines
=
2
statusLabel
.
textAlignment
=
.
right
statusLabel
.
font
=
AppFont
.
SFPro
.
bold
(
size
:
14
)
addSubview
(
statusLabel
)
//Constraints
typeLabel
.
snp
.
makeConstraints
{
(
make
)
in
make
.
left
.
equalToSuperview
()
make
.
top
.
equalToSuperview
()
.
inset
(
15
)
}
valueLabel
.
snp
.
makeConstraints
{
(
make
)
in
make
.
left
.
equalToSuperview
()
.
inset
(
100
)
make
.
centerY
.
equalTo
(
typeLabel
)
}
}
func
prepareProgress
()
{
progressContainer
.
layer
.
cornerRadius
=
2
progressContainer
.
backgroundColor
=
UIColor
(
hex
:
0xe9ebfc
)
addSubview
(
progressContainer
)
progressContainer
.
snp
.
makeConstraints
{
(
make
)
in
make
.
height
.
equalTo
(
4
)
make
.
left
.
right
.
equalToSuperview
()
make
.
top
.
equalTo
(
typeLabel
.
snp
.
bottom
)
.
offset
(
18
)
make
.
bottom
.
equalToSuperview
()
.
inset
(
15
)
}
statusLabel
.
snp
.
makeConstraints
{
(
make
)
in
make
.
right
.
equalToSuperview
()
make
.
centerY
.
equalTo
(
typeLabel
)
make
.
width
.
equalTo
(
progressContainer
)
.
multipliedBy
(
0.4
)
}
}
}
1Weather/UI/View controllers/Today/Cells/TodayAirQualityCell/TodayAirQualityCell.swift
View file @
ad821a19
...
...
@@ -11,7 +11,6 @@ class TodayAirQualityCell: UITableViewCell {
//Private
private
let
headingLabel
=
UILabel
()
private
let
valueCircle
=
CAShapeLayer
()
private
let
valueProgressGradient
=
CAGradientLayer
()
private
let
airQualityValueLabel
=
UILabel
()
private
let
airQualityLabel
=
UILabel
()
private
let
airDescLabel
=
UILabel
()
...
...
@@ -24,8 +23,7 @@ class TodayAirQualityCell: UITableViewCell {
prepareHeading
()
prepareAirLabels
()
prepareValueProgress
()
setAirQuality
(
value
:
48
)
prepareStackView
()
}
override
func
layoutSubviews
()
{
...
...
@@ -36,33 +34,16 @@ class TodayAirQualityCell: UITableViewCell {
startAngle
:
0
,
endAngle
:
2
*
.
pi
,
clockwise
:
false
)
.
cgPath
let
mask
=
CAShapeLayer
()
mask
.
lineWidth
=
6
mask
.
lineCap
=
.
round
mask
.
strokeColor
=
UIColor
.
red
.
cgColor
mask
.
fillColor
=
UIColor
.
clear
.
cgColor
mask
.
path
=
UIBezierPath
(
arcCenter
:
airQualityValueLabel
.
center
,
radius
:
36
,
startAngle
:
-.
pi
/
2
,
endAngle
:
0
,
clockwise
:
true
)
.
cgPath
valueProgressGradient
.
frame
=
.
init
(
x
:
0
,
y
:
0
,
width
:
100
,
height
:
100
)
// valueProgressGradient.mask = valueProgressShape
}
required
init
?(
coder
:
NSCoder
)
{
fatalError
(
"init(coder:) has not been implemented"
)
}
private
func
setAirQuality
(
value
:
CGFloat
)
{
airQualityValueLabel
.
text
=
"
\(
Int
(
value
)
)
"
public
func
configure
(
health
:
Health
)
{
airQualityValueLabel
.
text
=
"
\(
Int
(
health
.
airQuality
?
.
index
??
0
)
)
"
let
aqiText
=
"air.quality.is"
.
localized
()
let
aqiConditionText
=
"air.quality.good"
.
localized
()
.
uppercased
()
let
aqiConditionText
=
health
.
airQuality
?
.
status
.
localized
??
""
let
attrString
=
NSMutableAttributedString
(
string
:
"
\(
aqiText
)\n\(
aqiConditionText
)
"
,
attributes
:
[
.
font
:
AppFont
.
SFPro
.
regular
(
size
:
24
),
.
foregroundColor
:
ThemeManager
.
currentTheme
.
secondaryTextColor
])
...
...
@@ -70,6 +51,15 @@ class TodayAirQualityCell: UITableViewCell {
range
:
NSRange
(
location
:
aqiText
.
count
+
1
,
length
:
aqiConditionText
.
count
))
airQualityLabel
.
attributedText
=
attrString
//Fill pollutions
stackView
.
removeAll
()
health
.
pollutants
.
map
{
$1
}
.
forEach
{
let
pollutionView
=
PollutantView
()
pollutionView
.
configure
(
pollutant
:
$0
)
stackView
.
addArrangedSubview
(
pollutionView
)
}
stackView
.
layoutIfNeeded
()
}
}
...
...
@@ -93,6 +83,8 @@ private extension TodayAirQualityCell {
}
func
prepareAirLabels
()
{
airQualityLabel
.
lineBreakMode
=
.
byWordWrapping
airQualityLabel
.
numberOfLines
=
0
airQualityValueLabel
.
font
=
AppFont
.
SFPro
.
bold
(
size
:
18
)
airQualityValueLabel
.
textColor
=
ThemeManager
.
currentTheme
.
secondaryTextColor
contentView
.
addSubview
(
airQualityValueLabel
)
...
...
@@ -113,7 +105,7 @@ private extension TodayAirQualityCell {
//Constraints
airQualityValueLabel
.
snp
.
makeConstraints
{
(
make
)
in
make
.
left
.
equalToSuperview
()
.
inset
(
72
)
make
.
top
.
equalTo
(
headingLabel
.
snp
.
bottom
)
.
offset
(
72
)
make
.
top
.
equalTo
(
headingLabel
.
snp
.
bottom
)
.
offset
(
72
)
.
priority
(
999
)
}
airQualityLabel
.
snp
.
makeConstraints
{
(
make
)
in
...
...
@@ -124,7 +116,6 @@ private extension TodayAirQualityCell {
airDescLabel
.
snp
.
makeConstraints
{
(
make
)
in
make
.
left
.
right
.
equalToSuperview
()
.
inset
(
50
)
make
.
top
.
equalTo
(
airQualityLabel
.
snp
.
bottom
)
.
offset
(
9
)
make
.
bottom
.
equalToSuperview
()
.
inset
(
30
)
}
}
...
...
@@ -133,11 +124,18 @@ private extension TodayAirQualityCell {
valueCircle
.
fillColor
=
UIColor
.
clear
.
cgColor
valueCircle
.
lineWidth
=
2
contentView
.
layer
.
addSublayer
(
valueCircle
)
}
valueProgressGradient
.
type
=
.
radial
valueProgressGradient
.
startPoint
=
.
init
(
x
:
0.5
,
y
:
0.5
)
valueProgressGradient
.
endPoint
=
.
init
(
x
:
0
,
y
:
0
)
valueProgressGradient
.
colors
=
[
UIColor
.
red
.
cgColor
,
UIColor
.
yellow
.
cgColor
]
contentView
.
layer
.
addSublayer
(
valueProgressGradient
)
func
prepareStackView
()
{
stackView
.
axis
=
.
vertical
stackView
.
distribution
=
.
fillProportionally
stackView
.
clipsToBounds
=
false
contentView
.
addSubview
(
stackView
)
stackView
.
snp
.
makeConstraints
{
(
make
)
in
make
.
left
.
right
.
equalToSuperview
()
.
inset
(
50
)
make
.
top
.
equalTo
(
airDescLabel
.
snp
.
bottom
)
.
offset
(
15
)
make
.
bottom
.
equalToSuperview
()
.
inset
(
15
)
}
}
}
1Weather/UI/View controllers/Today/Cells/TodayCellFactory.swift
View file @
ad821a19
...
...
@@ -14,6 +14,7 @@ private enum TodayCellType:Int {
case
conditions
case
forecastPeriod
case
precipitation
case
airQuality
case
dayTime
case
sun
case
moon
...
...
@@ -26,9 +27,15 @@ private struct TodaySection {
class
TodayCellFactory
:
CellFactoryProtocol
{
//Private
private
let
todayViewModel
:
TodayViewModel
private
var
todaySection
=
TodaySection
(
rows
:
[
/*.alert,*/
.
forecast
,
.
ad
,
private
var
todaySection
=
TodaySection
(
rows
:
[
.
alert
,
.
forecast
,
.
ad
,
.
conditions
,
.
forecastPeriod
,
.
precipitation
,
.
dayTime
,
.
sun
,
.
moon
])
.
airQuality
,
.
dayTime
,
.
sun
,
.
moon
])
private
let
health
=
Health
(
lastUpdateTime
:
Date
(),
airQuality
:
.
init
(
index
:
48
,
advice
:
"some"
),
pollutants
:
[
"pm25"
:
.
init
(
name
:
"PM 2.5"
,
value
:
48
),
"pm10"
:
.
init
(
name
:
"PM 10"
,
value
:
42
),
"no2"
:
.
init
(
name
:
"NO2"
,
value
:
74
),
"so2"
:
.
init
(
name
:
"SO2"
,
value
:
135
)])
//Public
init
(
viewModel
:
TodayViewModel
)
{
...
...
@@ -84,6 +91,10 @@ class TodayCellFactory: CellFactoryProtocol {
let
cell
=
dequeueReusableCell
(
type
:
PrecipitationCell
.
self
,
tableView
:
tableView
,
indexPath
:
indexPath
)
cell
.
configure
(
with
:
loc
.
daily
)
return
cell
case
.
airQuality
:
let
cell
=
dequeueReusableCell
(
type
:
TodayAirQualityCell
.
self
,
tableView
:
tableView
,
indexPath
:
indexPath
)
cell
.
configure
(
health
:
self
.
health
)
return
cell
case
.
dayTime
:
let
cell
=
dequeueReusableCell
(
type
:
TodayDayTimesCell
.
self
,
tableView
:
tableView
,
indexPath
:
indexPath
)
cell
.
configure
(
with
:
loc
)
...
...
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