如何在使用区块滚动时隐藏底部小工具



我试图在使用bloc滚动时隐藏Floating Action button,但没有成功。。

这是下面的bloc类:

class AppCubit extends Cubit<AppStates> {
AppCubit() : super(AppInitialState());
static AppCubit get(context) => BlocProvider.of(context);
int currentIndex = 0;
List<Widget> screens = [
FeedsScreen(),
ChatsScreen(),
UsersScreen(),
SettingsScreen(),
];
List<String> titles = [
'Home',
'Chats',
'Users',
'Settings',
];
ScrollController scrollController =
ScrollController(); // set controller on scrolling
bool show = true;
void hideBottomWidget() {
show = false;
}
void showBottomWidget() {
show = true;
}
void handleScroll() async {
scrollController.addListener(() {
if (scrollController.position.userScrollDirection ==
ScrollDirection.reverse) {
hideBottomWidget();
}
if (scrollController.position.userScrollDirection ==
ScrollDirection.forward) {
showBottomWidget();
}
});
}
}

这是下面的布局屏幕我有:

class SocialLayout extends StatelessWidget {
const SocialLayout({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return BlocConsumer<AppCubit, AppStates>(
listener: (context, state) {},
builder: (context, state) {
var cubit = AppCubit.get(context);
return Scaffold(
appBar: AppBar(
title: Text(
cubit.titles[cubit.currentIndex],
),
actions: [
IconButton(
onPressed: () {},
icon: Icon(IconBroken.Notification),
),
IconButton(
onPressed: () {},
icon: Icon(IconBroken.Search),
),
],
),
body: cubit.screens[cubit.currentIndex],
bottomNavigationBar: BottomNavigationBar(
currentIndex: cubit.currentIndex,
onTap: (index) {
cubit.changeBottomNavIndex(index);
},
items: [
BottomNavigationBarItem(
icon: Icon(IconBroken.Home), label: 'Home'),
BottomNavigationBarItem(
icon: Icon(IconBroken.Chat), label: 'Chat'),
BottomNavigationBarItem(
icon: Icon(IconBroken.Location), label: 'Location'),
BottomNavigationBarItem(
icon: Icon(IconBroken.Setting), label: 'Settings'),
],
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
floatingActionButton: Visibility(
visible: cubit.show,
child: FloatingActionButton(
onPressed: () { },
tooltip: 'Post',
child: Icon(IconBroken.Paper_Upload, color: Colors.white,),
elevation: 2.0,
),
),
);
},
);
}
}

在这里,我使用了visibility小部件并添加了visible状态。。

下面对包含ListView.separated():的屏幕进行编码

class FeedsScreen extends StatelessWidget {
const FeedsScreen({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
var responsive = MediaQuery.of(context).size;
return BlocConsumer<AppCubit, AppStates>(
listener: (context, state) {},
builder: (context, state) {
var cubit = AppCubit.get(context);
return SingleChildScrollView(
physics: BouncingScrollPhysics(),
child: Column(
children: [
Card(...),
],
),
),
ListView.separated(
controller: cubit.scrollController,
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemBuilder: (context, index) => buildPostItem(context),
separatorBuilder: (context, index) => SizedBox(height: 10,),
itemCount: 10,
),
SizedBox(
height: 8.0,
),
],
),
);
},
);
}
Widget buildPostItem(context) => Card(....);,
);
}

正如你所看到的,我在ListView中称之为controller: cubit.scrollController,

下面是我在BlocProvider()中称为handleScroll方法的主要代码:

void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
Bloc.observer = MyBlocObserver();
DioHelper.init();
await CacheHelper.init();
Widget widget;
uId = CacheHelper.getData(key: 'uId');
if (uId != null) {
widget = SocialLayout();
} else {
widget = LoginScreen();
}
runApp(MyApp(
startWidget: widget,
));
}
class MyApp extends StatelessWidget {
final Widget startWidget;
MyApp({
this.startWidget,
});
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (BuildContext context) => AppCubit()..getUserData()..handleScroll(),
child: BlocConsumer<AppCubit, AppStates>(
listener: (context, state) {},
builder: (context, state) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: lightTheme,
themeMode: ThemeMode.light,
home: startWidget,
);
},
),
);
}
}

以下是解决方案,我在下面的方法中添加emit,然后将emit添加为下面的代码:

void hideBottomWidget() {
show = false;
emit(AppHideBottomWidgetState());
}
void showBottomWidget() {
show = true;
emit(AppShowBottomWidgetState());
}
void handleScroll() async {
scrollController.addListener(() {
if (scrollController.position.userScrollDirection ==
ScrollDirection.reverse) {
hideBottomWidget();
emit(AppHandleReverseHideBottomWidgetState());
}
if (scrollController.position.userScrollDirection ==
ScrollDirection.forward) {
showBottomWidget();
emit(AppHandleForwardHideBottomWidgetState());
}
});
}