diff --git a/widget/material/slider.go b/widget/material/slider.go index fca46049..801e19c8 100644 --- a/widget/material/slider.go +++ b/widget/material/slider.go @@ -19,10 +19,11 @@ import ( // Slider is for selecting a value in a range. func Slider(th *Theme, float *widget.Float, min, max float32) SliderStyle { return SliderStyle{ - Min: min, - Max: max, - Color: th.Palette.ContrastBg, - Float: float, + Min: min, + Max: max, + Color: th.Palette.ContrastBg, + Float: float, + FingerSize: th.FingerSize, } } @@ -30,28 +31,39 @@ type SliderStyle struct { Min, Max float32 Color color.NRGBA Float *widget.Float + + FingerSize unit.Value } func (s SliderStyle) Layout(gtx layout.Context) layout.Dimensions { thumbRadiusInt := gtx.Px(unit.Dp(6)) trackWidth := float32(gtx.Px(unit.Dp(2))) thumbRadius := float32(thumbRadiusInt) - halfWidthInt := 2 * thumbRadiusInt - halfWidth := float32(halfWidthInt) size := gtx.Constraints.Min // Keep a minimum length so that the track is always visible. - minLength := halfWidthInt + 3*thumbRadiusInt + halfWidthInt + minLength := thumbRadiusInt + 3*thumbRadiusInt + thumbRadiusInt if size.X < minLength { size.X = minLength } - size.Y = 2 * halfWidthInt + size.Y = 2 * thumbRadiusInt + + // Try to expand to finger size, but only if the constraints + // allow for it. + touchSizePx := gtx.Px(s.FingerSize) + if touchSizePx > gtx.Constraints.Max.Y { + touchSizePx = gtx.Constraints.Max.Y + } + if size.Y < touchSizePx { + size.Y = 2 * (touchSizePx / 2) + } st := op.Push(gtx.Ops) - op.Offset(f32.Pt(halfWidth, 0)).Add(gtx.Ops) - gtx.Constraints.Min = image.Pt(size.X-2*halfWidthInt, size.Y) - s.Float.Layout(gtx, halfWidthInt, s.Min, s.Max) - thumbPos := halfWidth + s.Float.Pos() + op.Offset(f32.Pt(thumbRadius, 0)).Add(gtx.Ops) + gtx.Constraints.Min = image.Pt(size.X-2*thumbRadiusInt, size.Y) + s.Float.Layout(gtx, thumbRadiusInt, s.Min, s.Max) + gtx.Constraints.Min.Y = size.Y + thumbPos := thumbRadius + s.Float.Pos() st.Pop() color := s.Color @@ -63,12 +75,12 @@ func (s SliderStyle) Layout(gtx layout.Context) layout.Dimensions { st = op.Push(gtx.Ops) track := f32.Rectangle{ Min: f32.Point{ - X: halfWidth, - Y: halfWidth - trackWidth/2, + X: thumbRadius, + Y: float32(size.Y/2) - trackWidth/2, }, Max: f32.Point{ X: thumbPos, - Y: halfWidth + trackWidth/2, + Y: float32(size.Y/2) + trackWidth/2, }, } clip.RRect{Rect: track}.Add(gtx.Ops) @@ -79,7 +91,7 @@ func (s SliderStyle) Layout(gtx layout.Context) layout.Dimensions { // Draw track after thumb. st = op.Push(gtx.Ops) track.Min.X = thumbPos - track.Max.X = float32(size.X) - halfWidth + track.Max.X = float32(size.X) - thumbRadius clip.RRect{Rect: track}.Add(gtx.Ops) paint.ColorOp{Color: f32color.MulAlpha(color, 96)}.Add(gtx.Ops) paint.PaintOp{}.Add(gtx.Ops) @@ -90,11 +102,11 @@ func (s SliderStyle) Layout(gtx layout.Context) layout.Dimensions { thumb := f32.Rectangle{ Min: f32.Point{ X: thumbPos - thumbRadius, - Y: halfWidth - thumbRadius, + Y: float32(size.Y/2) - thumbRadius, }, Max: f32.Point{ X: thumbPos + thumbRadius, - Y: halfWidth + thumbRadius, + Y: float32(size.Y/2) + thumbRadius, }, } rr := thumbRadius diff --git a/widget/material/theme.go b/widget/material/theme.go index d37a2331..8cc44c7c 100644 --- a/widget/material/theme.go +++ b/widget/material/theme.go @@ -40,6 +40,9 @@ type Theme struct { RadioChecked *widget.Icon RadioUnchecked *widget.Icon } + + // FingerSize is the minimum touch target size. + FingerSize unit.Value } func NewTheme(fontCollection []text.FontFace) *Theme { @@ -59,6 +62,9 @@ func NewTheme(fontCollection []text.FontFace) *Theme { t.Icon.RadioChecked = mustIcon(widget.NewIcon(icons.ToggleRadioButtonChecked)) t.Icon.RadioUnchecked = mustIcon(widget.NewIcon(icons.ToggleRadioButtonUnchecked)) + // 38dp is on the lower end of possible finger size. + t.FingerSize = unit.Dp(38) + return t }