我正在使用基本滑块,我发现如何仅更新我想要更改的滑块主题数据部分,例如 trackHeight,但不幸的是,我不确定如何更新“trackShape”字段。这是我在主应用程序中更新轨道高度的操作,例如:
final SliderThemeData tweakedSliderTheme = Theme.of(context).sliderTheme.copyWith(
trackHeight: 22.0,
//trackShape: RectangularSliderTrackShape(), // How do I update this??
);
Run Code Online (Sandbox Code Playgroud)
我确实尝试在滑块小部件周围使用ClipRRect(),但没有效果。
这是一个滑块的简单页面:
import 'package:flutter/material.dart';
class RoomControl extends StatefulWidget {
@override
_RoomControlState createState() => _RoomControlState();
}
class _RoomControlState extends State<RoomControl> {
double _value = 0.0;
void _setvalue(double value) => setState(() => _value = value);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Name here'),
),
//hit Ctrl+space in intellij to know what are the options you can use in flutter widgets
body: Container(
padding: EdgeInsets.all(32.0),
child: Center(
child: Column(
children: <Widget>[
Text('Value: ${(_value * 100).round()}'),
ClipRRect(
borderRadius: BorderRadius.circular(5.0),
child:Slider(
value: _value,
onChanged: _setvalue,
divisions: 10,
)
)
],
),
),
),
);
}
}
Run Code Online (Sandbox Code Playgroud)
这是滑块的样子:
更新:得到答案后,我可以通过更新刻度线形状和拇指形状轻松创建这样的东西:
final SliderThemeData tweakedSliderTheme = Theme.of(context).sliderTheme.copyWith(
trackHeight: 20.0,
thumbShape: MyRoundSliderThumbShape(enabledThumbRadius: 13.0, disabledThumbRadius: 13.0),
trackShape: MyRoundSliderTrackShape(), // TODO: this is hard coded right now for 20 track height
inactiveTrackColor: lightGreySliderColor,
activeTickMarkColor: Color(blackPrimaryValue),
inactiveTickMarkColor: colorizedMenuColor,
tickMarkShape: MyRectSliderTickMarkShape(tickMarkRadius: 4.0),
);
Run Code Online (Sandbox Code Playgroud)
刻度线形状有一些技巧。如果你让它太大,它只会跳过绘画!可能有道理,但我对绘画/渲染知之甚少,所以我花了一段时间来学习如何让刻度线(矩形)正确显示
我已将基本代码复制RectangularSliderTrackShape到一个名为 的新类中RoundSliderTrackShape。
round_slider_track_shape.dart
import 'dart:math';
import 'package:flutter/material.dart';
class RoundSliderTrackShape extends SliderTrackShape {
/// Create a slider track that draws 2 rectangles.
const RoundSliderTrackShape({ this.disabledThumbGapWidth = 2.0 });
/// Horizontal spacing, or gap, between the disabled thumb and the track.
///
/// This is only used when the slider is disabled. There is no gap around
/// the thumb and any part of the track when the slider is enabled. The
/// Material spec defaults this gap width 2, which is half of the disabled
/// thumb radius.
final double disabledThumbGapWidth;
@override
Rect getPreferredRect({
RenderBox parentBox,
Offset offset = Offset.zero,
SliderThemeData sliderTheme,
bool isEnabled,
bool isDiscrete,
}) {
final double overlayWidth = sliderTheme.overlayShape.getPreferredSize(isEnabled, isDiscrete).width;
final double trackHeight = sliderTheme.trackHeight;
assert(overlayWidth >= 0);
assert(trackHeight >= 0);
assert(parentBox.size.width >= overlayWidth);
assert(parentBox.size.height >= trackHeight);
final double trackLeft = offset.dx + overlayWidth / 2;
final double trackTop = offset.dy + (parentBox.size.height - trackHeight) / 2;
// TODO(clocksmith): Although this works for a material, perhaps the default
// rectangular track should be padded not just by the overlay, but by the
// max of the thumb and the overlay, in case there is no overlay.
final double trackWidth = parentBox.size.width - overlayWidth;
return Rect.fromLTWH(trackLeft, trackTop, trackWidth, trackHeight);
}
@override
void paint(
PaintingContext context,
Offset offset, {
RenderBox parentBox,
SliderThemeData sliderTheme,
Animation<double> enableAnimation,
TextDirection textDirection,
Offset thumbCenter,
bool isDiscrete,
bool isEnabled,
}) {
// If the slider track height is 0, then it makes no difference whether the
// track is painted or not, therefore the painting can be a no-op.
if (sliderTheme.trackHeight == 0) {
return;
}
// Assign the track segment paints, which are left: active, right: inactive,
// but reversed for right to left text.
final ColorTween activeTrackColorTween = ColorTween(begin: sliderTheme.disabledActiveTrackColor , end: sliderTheme.activeTrackColor);
final ColorTween inactiveTrackColorTween = ColorTween(begin: sliderTheme.disabledInactiveTrackColor , end: sliderTheme.inactiveTrackColor);
final Paint activePaint = Paint()..color = activeTrackColorTween.evaluate(enableAnimation);
final Paint inactivePaint = Paint()..color = inactiveTrackColorTween.evaluate(enableAnimation);
Paint leftTrackPaint;
Paint rightTrackPaint;
switch (textDirection) {
case TextDirection.ltr:
leftTrackPaint = activePaint;
rightTrackPaint = inactivePaint;
break;
case TextDirection.rtl:
leftTrackPaint = inactivePaint;
rightTrackPaint = activePaint;
break;
}
// Used to create a gap around the thumb iff the slider is disabled.
// If the slider is enabled, the track can be drawn beneath the thumb
// without a gap. But when the slider is disabled, the track is shortened
// and this gap helps determine how much shorter it should be.
// TODO(clocksmith): The new Material spec has a gray circle in place of this gap.
double horizontalAdjustment = 0.0;
if (!isEnabled) {
final double disabledThumbRadius = sliderTheme.thumbShape.getPreferredSize(false, isDiscrete).width / 2.0;
final double gap = disabledThumbGapWidth * (1.0 - enableAnimation.value);
horizontalAdjustment = disabledThumbRadius + gap;
}
final Rect trackRect = getPreferredRect(
parentBox: parentBox,
offset: offset,
sliderTheme: sliderTheme,
isEnabled: isEnabled,
isDiscrete: isDiscrete,
);
final Rect leftTrackSegment = Rect.fromLTRB(trackRect.left, trackRect.top, thumbCenter.dx - horizontalAdjustment, trackRect.bottom);
// Left Arc
context.canvas.drawArc(
Rect.fromCircle(center: Offset(trackRect.left, trackRect.top + 11.0), radius: 11.0),
-pi * 3 / 2, // -270 degrees
pi, // 180 degrees
false,
trackRect.left - thumbCenter.dx == 0.0 ? rightTrackPaint : leftTrackPaint
);
// Right Arc
context.canvas.drawArc(
Rect.fromCircle(center: Offset(trackRect.right, trackRect.top + 11.0), radius: 11.0),
-pi / 2, // -90 degrees
pi, // 180 degrees
false,
trackRect.right - thumbCenter.dx == 0.0 ? leftTrackPaint : rightTrackPaint
);
context.canvas.drawRect(leftTrackSegment, leftTrackPaint);
final Rect rightTrackSegment = Rect.fromLTRB(thumbCenter.dx + horizontalAdjustment, trackRect.top, trackRect.right, trackRect.bottom);
context.canvas.drawRect(rightTrackSegment, rightTrackPaint);
}
}
Run Code Online (Sandbox Code Playgroud)
以下是 SliderTheme 的设置方式。
import 'package:flutter_stackoverflow/round_slider_track_shape.dart';
...
sliderTheme: Theme.of(context).sliderTheme.copyWith(
trackHeight: 22.0,
trackShape: RoundSliderTrackShape(),
activeTrackColor: Colors.green,
// trackShape: RectangularSliderTrackShape(),
),
Run Code Online (Sandbox Code Playgroud)
添加的是 SliderTrack 侧面的两个圆弧
// Left Arc
context.canvas.drawArc(
Rect.fromCircle(center: Offset(trackRect.left, trackRect.top + 11.0), radius: 11.0),
-pi * 3 / 2, // -270 degrees
pi, // 180 degrees
false,
trackRect.left - thumbCenter.dx == 0.0 ? rightTrackPaint : leftTrackPaint
);
// Right Arc
context.canvas.drawArc(
Rect.fromCircle(center: Offset(trackRect.right, trackRect.top + 11.0), radius: 11.0),
-pi / 2, // -90 degrees
pi, // 180 degrees
false,
trackRect.right - thumbCenter.dx == 0.0 ? leftTrackPaint : rightTrackPaint
);
Run Code Online (Sandbox Code Playgroud)
小智 5
@Jun Xiang 的回答似乎有效,但我对以下代码做了一些小改动:
// Left Arc
context.canvas.drawArc(
Rect.fromCircle(center: Offset(trackRect.left, trackRect.top + 11.0), radius: 11.0),
-pi * 3 / 2, // -270 degrees
pi, // 180 degrees
false,
trackRect.left - thumbCenter.dx == 0.0 ? rightTrackPaint : leftTrackPaint
);
// Right Arc
context.canvas.drawArc(
Rect.fromCircle(center: Offset(trackRect.right, trackRect.top + 11.0), radius: 11.0),
-pi / 2, // -90 degrees
pi, // 180 degrees
false,
trackRect.right - thumbCenter.dx == 0.0 ? leftTrackPaint : rightTrackPaint
);
Run Code Online (Sandbox Code Playgroud)
我没有使用11.0,而是使用sliderTheme.trackHeight * 1/2,并且似乎适用于输入的所有轨道高度(不仅是 22)。
PS:我无法发表评论,所以我发布了答案。
| 归档时间: |
|
| 查看次数: |
9682 次 |
| 最近记录: |