Skip to content

Commit 08f6d18

Browse files
authored
feat(slider): add linear-gradient support for track background (#11015)
1 parent 0e4628d commit 08f6d18

File tree

9 files changed

+375
-48
lines changed

9 files changed

+375
-48
lines changed

apps/automated/src/ui/slider/slider-tests.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import { BindingOptions, View, Page, Observable, EventData, PropertyChangeData,
66
import { Slider } from '@nativescript/core/ui/slider';
77
// << article-require-slider
88

9+
import { LinearGradient } from '@nativescript/core/ui/styling/linear-gradient';
10+
911
// ### Binding the Progress and Slider value properties to a observable view-model property.
1012

1113
// >> article-binding-slider-properties
@@ -121,6 +123,67 @@ export function test_set_backgroundColor() {
121123
}
122124
}
123125

126+
export function test_set_linear_gradient_background() {
127+
const slider = new Slider();
128+
129+
// Create a linear gradient programmatically
130+
const gradient = new LinearGradient();
131+
gradient.angle = Math.PI / 2; // 90 degrees (left to right)
132+
gradient.colorStops = [{ color: new Color('red') }, { color: new Color('green') }, { color: new Color('blue') }];
133+
134+
function testAction(views: Array<View>) {
135+
// Set the gradient via the style's backgroundImage
136+
slider.style.backgroundImage = gradient;
137+
138+
// Verify the slider was created and the gradient was applied
139+
TKUnit.assertNotNull(slider, 'slider should not be null');
140+
141+
if (__APPLE__) {
142+
// On iOS, verify that track images were set
143+
const minTrackImage = slider.ios.minimumTrackImageForState(UIControlState.Normal);
144+
const maxTrackImage = slider.ios.maximumTrackImageForState(UIControlState.Normal);
145+
TKUnit.assertNotNull(minTrackImage, 'minimumTrackImage should be set after applying gradient');
146+
TKUnit.assertNotNull(maxTrackImage, 'maximumTrackImage should be set after applying gradient');
147+
} else if (__ANDROID__) {
148+
// On Android, verify the progress drawable was modified
149+
const progressDrawable = slider.android.getProgressDrawable();
150+
TKUnit.assertNotNull(progressDrawable, 'progressDrawable should not be null');
151+
}
152+
}
153+
154+
helper.buildUIAndRunTest(slider, testAction);
155+
}
156+
157+
export function test_set_linear_gradient_with_stops() {
158+
const slider = new Slider();
159+
160+
// Create a linear gradient with explicit color stops
161+
const gradient = new LinearGradient();
162+
gradient.angle = 0; // 0 degrees (bottom to top)
163+
gradient.colorStops = [
164+
{ color: new Color('orangered'), offset: { unit: '%', value: 0 } },
165+
{ color: new Color('green'), offset: { unit: '%', value: 0.5 } },
166+
{ color: new Color('lightblue'), offset: { unit: '%', value: 1 } },
167+
];
168+
169+
function testAction(views: Array<View>) {
170+
slider.style.backgroundImage = gradient;
171+
172+
// Verify the slider was created
173+
TKUnit.assertNotNull(slider, 'slider should not be null');
174+
175+
if (__APPLE__) {
176+
const minTrackImage = slider.ios.minimumTrackImageForState(UIControlState.Normal);
177+
TKUnit.assertNotNull(minTrackImage, 'minimumTrackImage should be set after applying gradient with stops');
178+
} else if (__ANDROID__) {
179+
const progressDrawable = slider.android.getProgressDrawable();
180+
TKUnit.assertNotNull(progressDrawable, 'progressDrawable should not be null');
181+
}
182+
}
183+
184+
helper.buildUIAndRunTest(slider, testAction);
185+
}
186+
124187
export function test_default_TNS_values() {
125188
const slider = new Slider();
126189
TKUnit.assertEqual(slider.value, 0, 'Default slider.value');

apps/toolbox/nativescript.config.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@ export default {
1212
packageManager: 'npm',
1313
additionalPathsToClean: ['.ns-vite-build'],
1414
},
15-
bundler: 'vite',
16-
bundlerConfigPath: 'vite.config.ts',
15+
// bundler: 'vite',
16+
// bundlerConfigPath: 'vite.config.ts',
1717
} as NativeScriptConfig;

apps/toolbox/src/app.css

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,3 +339,32 @@ Button {
339339
.text-center {
340340
text-align: center;
341341
}
342+
343+
/* Sliders Demo Page Styles */
344+
.sliders-demo-page Slider.gradient-slider {
345+
background: linear-gradient(to right, orangered, green, lightblue);
346+
}
347+
348+
.sliders-demo-page Slider.rainbow-slider {
349+
background: linear-gradient(to right, red, orange, yellow, green, blue, indigo, violet);
350+
}
351+
352+
.sliders-demo-page Slider.two-color-slider {
353+
background: linear-gradient(to right, #ff6b6b, #4ecdc4);
354+
}
355+
356+
.sliders-demo-page Slider.sunset-slider {
357+
background: linear-gradient(to right, #f12711, #f5af19);
358+
}
359+
360+
.sliders-demo-page Slider.ocean-slider {
361+
background: linear-gradient(to right, #2193b0, #6dd5ed);
362+
}
363+
364+
.sliders-demo-page Slider.purple-slider {
365+
background: linear-gradient(to right, #8e2de2, #4a00e0);
366+
}
367+
368+
.sliders-demo-page Slider.stops-slider {
369+
background: linear-gradient(to right, red 0%, yellow 50%, green 100%);
370+
}

apps/toolbox/src/main-page.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
<Button text="multiple-scenes" tap="{{ viewDemo }}" class="btn btn-primary btn-view-demo" />
2323
<Button text="root-layout" tap="{{ viewDemo }}" class="btn btn-primary btn-view-demo" />
2424
<Button text="scroll-view" tap="{{ viewDemo }}" class="btn btn-primary btn-view-demo" />
25+
<Button text="sliders" tap="{{ viewDemo }}" class="btn btn-primary btn-view-demo" />
2526
<Button text="status-bar" tap="{{ viewDemo }}" class="btn btn-primary btn-view-demo" />
2627
<Button text="switch" tap="{{ viewDemo }}" class="btn btn-primary btn-view-demo" />
2728
<Button text="tabview" tap="{{ viewDemo }}" class="btn btn-primary btn-view-demo" />

apps/toolbox/src/pages/sliders.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { Observable, EventData, Page } from '@nativescript/core';
2+
3+
let page: Page;
4+
5+
export function navigatingTo(args: EventData) {
6+
page = <Page>args.object;
7+
page.bindingContext = new SlidersModel();
8+
}
9+
10+
export class SlidersModel extends Observable {
11+
constructor() {
12+
super();
13+
}
14+
}

apps/toolbox/src/pages/sliders.xml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<Page xmlns="http://schemas.nativescript.org/tns.xsd" navigatingTo="navigatingTo" class="page">
2+
<Page.actionBar>
3+
<ActionBar title="Sliders" icon="" class="action-bar">
4+
</ActionBar>
5+
</Page.actionBar>
6+
7+
<GridLayout class="sliders-demo-page">
8+
<ScrollView>
9+
<StackLayout padding="20" visionos:padding="40">
10+
11+
<Label text="Default Slider" class="h3" marginTop="24" />
12+
<Slider minValue="0" maxValue="100" value="50" marginTop="12" />
13+
14+
<Label text="Gradient Slider (CSS)" class="h3" marginTop="24" />
15+
<Label text="background: linear-gradient(to right, orangered, green, lightblue)" class="caption" />
16+
<Slider class="gradient-slider" minValue="0" maxValue="100" value="50" marginTop="12" />
17+
18+
<Label text="Rainbow Gradient" class="h3" marginTop="24" />
19+
<Label text="background: linear-gradient(to right, red, orange, yellow, green, blue, indigo, violet)" class="caption" />
20+
<Slider class="rainbow-slider" minValue="0" maxValue="100" value="70" marginTop="12" />
21+
22+
<Label text="Two-Color Gradient" class="h3" marginTop="24" />
23+
<Label text="background: linear-gradient(to right, #ff6b6b, #4ecdc4)" class="caption" />
24+
<Slider class="two-color-slider" minValue="0" maxValue="100" value="30" marginTop="12" />
25+
26+
<Label text="Sunset Gradient" class="h3" marginTop="24" />
27+
<Label text="background: linear-gradient(to right, #f12711, #f5af19)" class="caption" />
28+
<Slider class="sunset-slider" minValue="0" maxValue="100" value="60" marginTop="12" />
29+
30+
<Label text="Ocean Gradient" class="h3" marginTop="24" />
31+
<Label text="background: linear-gradient(to right, #2193b0, #6dd5ed)" class="caption" />
32+
<Slider class="ocean-slider" minValue="0" maxValue="100" value="40" marginTop="12" />
33+
34+
<Label text="Purple Gradient" class="h3" marginTop="24" />
35+
<Label text="background: linear-gradient(to right, #8e2de2, #4a00e0)" class="caption" />
36+
<Slider class="purple-slider" minValue="0" maxValue="100" value="80" marginTop="12" />
37+
38+
<Label text="Gradient with Color Stops" class="h3" marginTop="24" />
39+
<Label text="background: linear-gradient(to right, red 0%, yellow 50%, green 100%)" class="caption" />
40+
<Slider class="stops-slider" minValue="0" maxValue="100" value="50" marginTop="12" />
41+
42+
<Label text="Disabled Gradient Slider" class="h3" marginTop="24" />
43+
<Slider class="gradient-slider" minValue="0" maxValue="100" value="50" isEnabled="false" marginTop="12" />
44+
45+
</StackLayout>
46+
</ScrollView>
47+
</GridLayout>
48+
</Page>

0 commit comments

Comments
 (0)