@@ -10,21 +10,19 @@ import dev.icerock.moko.widgets.core.style.background.Direction
1010import dev.icerock.moko.widgets.core.style.background.Fill
1111import dev.icerock.moko.widgets.core.style.state.PressableState
1212import kotlinx.cinterop.useContents
13+ import platform.CoreGraphics.CGFloat
1314import platform.CoreGraphics.CGPointMake
1415import platform.CoreGraphics.CGRectMake
15- import platform.Foundation.NSRunLoop
16- import platform.Foundation.NSRunLoopCommonModes
17- import platform.QuartzCore.CADisplayLink
1816import platform.QuartzCore.CAGradientLayer
1917import platform.QuartzCore.CALayer
2018import platform.QuartzCore.CATransaction
2119import platform.UIKit.UIButton
2220import platform.UIKit.UIColor
21+ import platform.UIKit.UIControl
2322import platform.UIKit.UIView
2423import platform.UIKit.adjustsImageWhenDisabled
2524import platform.UIKit.adjustsImageWhenHighlighted
2625import platform.UIKit.backgroundColor
27- import platform.UIKit.window
2826
2927@Suppress(" MagicNumber" , " ComplexMethod" )
3028fun Background <out Fill >.caLayer (): CALayer {
@@ -35,6 +33,7 @@ fun Background<out Fill>.caLayer(): CALayer {
3533 is Fill .Solid -> backgroundLayer = CALayer ().apply {
3634 backgroundColor = fill.color.toUIColor().CGColor
3735 }
36+
3837 is Fill .Gradient -> {
3938 backgroundLayer = CAGradientLayer ().apply {
4039 colors = cgColors(fill.colors.map {
@@ -58,6 +57,7 @@ fun Background<out Fill>.caLayer(): CALayer {
5857 endPoint = end
5958 }
6059 }
60+
6161 null -> {
6262 backgroundLayer = CALayer ()
6363 }
@@ -84,56 +84,62 @@ fun UIButton.applyStateBackgroundIfNeeded(background: PressableState<Background<
8484 adjustsImageWhenDisabled = false
8585 adjustsImageWhenHighlighted = false
8686
87- val normalBg = background.normal.caLayer().also {
88- layer.addSublayer(it)
89- }
90- val disabledBg = background.disabled.caLayer().also {
91- layer.addSublayer(it)
92- }
93- val pressedBg = background.pressed.caLayer().also {
94- layer.addSublayer(it)
95- }
96-
97- fun updateLayers () {
98- if (! isEnabled()) {
99- disabledBg.opacity = 1.0f
100- normalBg.opacity = 0f
101- pressedBg.opacity = 0f
102- return
87+ val stateLayers = StateLayers (
88+ normal = background.normal.caLayer().also {
89+ layer.addSublayer(it)
90+ },
91+ disabled = background.disabled.caLayer().also {
92+ layer.addSublayer(it)
93+ },
94+ pressed = background.pressed.caLayer().also {
95+ layer.addSublayer(it)
10396 }
97+ )
10498
105- if (isHighlighted()) {
106- pressedBg.opacity = 1.0f
107- normalBg.opacity = 0f
108- } else {
109- normalBg.opacity = 1.0f
110- pressedBg.opacity = 0f
111- }
112- disabledBg.opacity = 0f
113- }
99+ stateLayers.update(this )
114100
115- updateLayers()
101+ this .displayLink(
102+ context = stateLayers,
103+ objectForSkipCheck = { it.layer.bounds }
104+ ) { button, stateLayers ->
105+ val (width: CGFloat , height: CGFloat ) = button.layer.bounds.useContents {
106+ this .size.width to this .size.height
107+ }
116108
117- // FIXME memoryleak, perfomance problem !!!
118- var link : CADisplayLink ? = null
109+ CATransaction .begin()
110+ CATransaction .setDisableActions( true )
119111
120- link = displayLink {
121- if (window != null ) {
122- val (width, height) = layer.bounds.useContents { size. width to size. height }
112+ stateLayers.normal.frame = CGRectMake ( 0.0 , 0.0 , width, height)
113+ stateLayers.disabled.frame = CGRectMake ( 0.0 , 0.0 , width, height)
114+ stateLayers.pressed.frame = CGRectMake ( 0.0 , 0.0 , width, height)
123115
124- CATransaction .begin()
125- CATransaction .setDisableActions(true )
116+ stateLayers.update(button)
126117
127- normalBg.frame = CGRectMake ( 0.0 , 0.0 , width, height )
128- disabledBg.frame = CGRectMake ( 0.0 , 0.0 , width, height)
129- pressedBg.frame = CGRectMake ( 0.0 , 0.0 , width, height)
118+ CATransaction .commit( )
119+ }
120+ }
130121
131- updateLayers()
122+ private data class StateLayers (
123+ val normal : CALayer ,
124+ val disabled : CALayer ,
125+ val pressed : CALayer
126+ ) {
127+ fun update (control : UIControl ) {
128+ if (! control.isEnabled()) {
129+ disabled.opacity = 1.0f
130+ normal.opacity = 0f
131+ pressed.opacity = 0f
132+ return
133+ }
132134
133- CATransaction .commit()
135+ if (control.isHighlighted()) {
136+ pressed.opacity = 1.0f
137+ normal.opacity = 0f
134138 } else {
135- link?.removeFromRunLoop(NSRunLoop .currentRunLoop, NSRunLoopCommonModes )
139+ normal.opacity = 1.0f
140+ pressed.opacity = 0f
136141 }
142+ disabled.opacity = 0f
137143 }
138144}
139145
@@ -156,24 +162,22 @@ fun UIView.applyBackgroundIfNeeded(background: Background<out Fill>?) {
156162
157163 this .backgroundColor = UIColor .clearColor
158164
159- val bgLayer = background.caLayer()
165+ val bgLayer: CALayer = background.caLayer()
160166 layer.insertSublayer(bgLayer, 0U )
161167
162- // FIXME memoryleak, perfomance problem !!!
163- var link: CADisplayLink ? = null
164-
165- link = displayLink {
166- if (window != null ) {
167- val (width, height) = layer.bounds.useContents { size.width to size.height }
168+ this .displayLink(
169+ context = bgLayer,
170+ objectForSkipCheck = { it.layer.bounds }
171+ ) { view, bgLayer ->
172+ val (width: CGFloat , height: CGFloat ) = view.layer.bounds.useContents {
173+ this .size.width to this .size.height
174+ }
168175
169- CATransaction .begin()
170- CATransaction .setDisableActions(true )
176+ CATransaction .begin()
177+ CATransaction .setDisableActions(true )
171178
172- bgLayer.frame = CGRectMake (0.0 , 0.0 , width, height)
179+ bgLayer.frame = CGRectMake (0.0 , 0.0 , width, height)
173180
174- CATransaction .commit()
175- } else {
176- link?.removeFromRunLoop(NSRunLoop .currentRunLoop, NSRunLoopCommonModes )
177- }
181+ CATransaction .commit()
178182 }
179183}
0 commit comments