1. 使用flutter_svg引入svg报错
该svg是从figma导出的。
翻阅 Out of order defs/references #102将defs
放到svg
标签的顶部,可以解决这个报错,且修正了该svg内部小图标的颜色问题,从而让页面上的svg跟figma上看起来一致。
2. 使用GridView滚动的时候报错
*The following assertion was thrown while notifying status listeners for AnimationController:
The provided ScrollController is currently attached to more than one ScrollPosition.*
class GridList extends StatelessWidget {
const GridList({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {\
return GridView.count(
crossAxisCount: 3,
crossAxisSpacing: 32,
mainAxisSpacing: 32,
scrollDirection: Axis.vertical,
childAspectRatio: (1 / .75),
shrinkWrap: true,
children: const [
GridCard(),
GridCard(),
GridCard(),
GridCard(),
GridCard(),
GridCard(),
],
);
}
}
参考Flutter错误The provided ScrollController is attached to more than one ScrollPosition需要给GridView添加个controller。
3. OutlinedButton 默认是disabled状态
OutlinedButton 默认是disabled状态,需要传递onPressed或者onLongPress才是可用状态,ButtonStyleButton做了解释
/// Whether the button is enabled or disabled.
///
/// Buttons are disabled by default. To enable a button, set its [onPressed]
/// or [onLongPress] properties to a non-null value.
bool get enabled => onPressed != null || onLongPress != null;
4. hydrated_bloc 持久化数据如何重新同步到客户端
需求:
不同的用户登录同一个客户端需要保留之前的操作记录(比如之前通过trtc设置的麦克风音量)。
直接上代码
class SettingBloc extends HydratedBloc {
final String uid;
SettingBloc({required this.uid}) : super(SettingInitial()) {
on(_onVolumeUpdate);
on(_onSettingInitialize);
add(const SettingInitialize()); // 初始化数据
}
final TRTC trtc = TRTC();
void _onSettingInitialize(
SettingInitialize event,
Emitter emit,
) async {
// 在这里可以拿到原始的state或从fromJson中返回的state
add(SettingVolumeUpdate(state.headsetVolume, false));
add(SettingVolumeUpdate(state.microphoneVolume, true));
}
void _onVolumeUpdate(
SettingVolumeUpdate event,
Emitter emit,
) async {
if (event.isMicrophone) {
await trtc.setCurrentMicDeviceVolume(event.volume.toInt()); // 设置麦克风音量
} else {
await trtc.setCurrentSpeakerDeviceVolume(event.volume.toInt());
}
emit(event.isMicrophone
? state.copyWith(microphoneVolume: event.volume)
: state.copyWith(headsetVolume: event.volume));
}
@override
String get id => uid; // 缓存不同用户的数据
@override
SettingState? fromJson(Map json) { // 从缓存中读取数据
final headsetVolume = json['headsetVolume'];
final microphoneVolume = json['microphoneVolume'];
// 在这里不能直接通过add(SettingVolumeUpdate(state.microphoneVolume, true))触发事件,
// 因为fromJson在SettingBloc构造函数之前执行,事件还没注册,
// 但是下面返回的结果会在_onSettingInitialize中拿到
// 从而在_onSettingInitialize中触发SettingVolumeUpdate
return SettingState(
headsetVolume: headsetVolume ?? 100,
microphoneVolume: microphoneVolume ?? 100,
);
}
@override
Map? toJson(SettingState state) { // 将bloc的数据缓存起来
return {
"microphoneVolume": state.microphoneVolume,
"headsetVolume": state.headsetVolume,
};
}
}
5. 空容器怎么触发onSecondaryTapDown事件
class Separator extends StatelessWidget {
Separator({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return GestureDetector(
behavior: HitTestBehavior.translucent, // 需要加这行才能触发onSecondaryTapDown事件
onSecondaryTapDown: (TapDownDetails details) {
},
child: const SizedBox( // child为空无法触发onSecondaryTapDown事件
height: 28,
),
);
}
}
6. [email protected] customButton 点击menu没法弹出
customButton 是我自定义的一个svg icon 用了GestureDetector注册了onTap事件
GestureDetector(
onTapDown: (details) {
setState(() {
isPressed = true;
});
widget.onTapDown?.call(details);
},
onTapUp: (details) {
setState(() {
isPressed = false;
});
},
onTapCancel: () {
setState(() {
isPressed = false;
});
},
onTap: () {
widget.onTap?.call();
},
behavior: widget.behavior,
child: SizedBox.square(
dimension: widget.size,
child: SvgPicture.asset(
svgStatusSrc,
),
),
),
customButton的注释:
/// Uses custom widget like icon,image,etc.. instead of the default button
final Widget? customButton;
我直接用SvgPicture.asset作为customButton是没问题的,所以怀疑是我的图标控件注册了onTap事件的问题,果然去掉了GestureDetector就没问题了。但是这个是通用控件,不能把GestureDetector去掉,有什么好办法去触发dropdownbutton的onTap事件呢?
Does this widget allow you to open the button programmatically?给出了答案
final dropdownKey = GlobalKey();
GestureDetector(
onTap: () {
dropdownKey.currentState!.callTap();
},
child: Container(
height: 100,
width: 100,
color: Colors.red,
)
DropdownButton2(key: dropdownKey,)