mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2025-04-24 14:47:13 -04:00
fix: hover color highlight with custom widget
This commit is contained in:
parent
5d520d7217
commit
56ced4a76f
8 changed files with 150 additions and 90 deletions
|
@ -1,7 +1,6 @@
|
|||
import 'package:app_flowy/workspace/presentation/view/view_widget.dart';
|
||||
import 'package:flowy_infra/flowy_logger.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/styled_hover.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
|
@ -17,22 +16,18 @@ class ViewList extends StatelessWidget {
|
|||
() => const SizedBox(),
|
||||
(views) {
|
||||
return Column(
|
||||
children: _renderViewWidgets(views),
|
||||
children: _renderViews(views),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
List<Widget> _renderViewWidgets(List<View> views) {
|
||||
List<Widget> _renderViews(List<View> views) {
|
||||
var targetViews = views.map((view) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 6),
|
||||
child: StyledHover(
|
||||
color: Colors.red,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
child: ViewWidget(
|
||||
view: view,
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 4),
|
||||
child: ViewWidget(
|
||||
view: view,
|
||||
),
|
||||
);
|
||||
}).toList(growable: false);
|
||||
|
|
|
@ -5,6 +5,8 @@ import 'package:app_flowy/workspace/presentation/app/app_widget.dart';
|
|||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/styled_more.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/styled_hover.dart';
|
||||
|
||||
class ViewWidget extends StatelessWidget {
|
||||
final View view;
|
||||
|
@ -12,32 +14,56 @@ class ViewWidget extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final contentPadding = EdgeInsets.only(
|
||||
left: AppWidgetSize.expandedPadding, top: 5, bottom: 5, right: 5);
|
||||
return InkWell(
|
||||
onTap: _openView(context),
|
||||
child: Padding(
|
||||
padding: contentPadding,
|
||||
child: buildContent(),
|
||||
child: StyledHover(
|
||||
color: Colors.grey.shade300,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
builder: (context, onHover) => _render(context, onHover),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Row buildContent() {
|
||||
return Row(
|
||||
children: [
|
||||
Image(
|
||||
fit: BoxFit.cover,
|
||||
width: 20,
|
||||
height: 20,
|
||||
image: assetImageForViewType(view.viewType)),
|
||||
const HSpace(6),
|
||||
Text(
|
||||
view.name,
|
||||
textAlign: TextAlign.start,
|
||||
style: const TextStyle(fontSize: 15),
|
||||
)
|
||||
],
|
||||
Widget _render(BuildContext context, bool onHover) {
|
||||
const double width = 20;
|
||||
List<Widget> children = [
|
||||
Image(
|
||||
fit: BoxFit.cover,
|
||||
width: width,
|
||||
height: width,
|
||||
image: assetImageForViewType(view.viewType)),
|
||||
const HSpace(6),
|
||||
Text(
|
||||
view.name,
|
||||
textAlign: TextAlign.start,
|
||||
style: const TextStyle(fontSize: 15),
|
||||
),
|
||||
];
|
||||
|
||||
if (onHover) {
|
||||
children.add(const Spacer());
|
||||
|
||||
children.add(Align(
|
||||
alignment: Alignment.center,
|
||||
child: StyledMore(
|
||||
width: width,
|
||||
onPressed: () {},
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
final padding = EdgeInsets.only(
|
||||
left: AppWidgetSize.expandedPadding,
|
||||
top: 5,
|
||||
bottom: 5,
|
||||
right: 5,
|
||||
);
|
||||
|
||||
return Padding(
|
||||
padding: padding,
|
||||
child: Flexible(
|
||||
child: Row(children: children),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,8 @@ import 'package:flowy_infra_ui/widget/rounded_button.dart';
|
|||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pbenum.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/styled_more.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/styled_text.dart';
|
||||
|
||||
class HomeTopBar extends StatelessWidget {
|
||||
final HomeStackView view;
|
||||
|
@ -50,14 +52,9 @@ class HomeTopBar extends StatelessWidget {
|
|||
}
|
||||
|
||||
Widget _renderMoreButton() {
|
||||
return SizedBox(
|
||||
return StyledMore(
|
||||
width: 24,
|
||||
child: IconButton(
|
||||
icon: const Icon(Icons.more_vert),
|
||||
iconSize: 12,
|
||||
alignment: Alignment.center,
|
||||
onPressed: () {},
|
||||
),
|
||||
onPressed: () {},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -83,12 +80,7 @@ class HomeTitle extends StatelessWidget {
|
|||
height: 15,
|
||||
image: assetImageForViewType(type)),
|
||||
const HSpace(6),
|
||||
Text(
|
||||
title,
|
||||
overflow: TextOverflow.fade,
|
||||
softWrap: false,
|
||||
style: const TextStyle(fontSize: 16),
|
||||
),
|
||||
StyledText(title, fontSize: 16),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
|
|
@ -5,6 +5,7 @@ import 'package:flowy_infra_ui/widget/spacing.dart';
|
|||
import 'package:flowy_sdk/protobuf/flowy-user/user_detail.pb.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/styled_text.dart';
|
||||
|
||||
class MenuUser extends MenuItem {
|
||||
final UserDetail user;
|
||||
|
@ -44,12 +45,7 @@ class MenuUser extends MenuItem {
|
|||
name = context.read<MenuUserBloc>().state.user.email;
|
||||
}
|
||||
return Flexible(
|
||||
child: Text(
|
||||
name,
|
||||
overflow: TextOverflow.fade,
|
||||
softWrap: false,
|
||||
style: const TextStyle(fontSize: 18),
|
||||
),
|
||||
child: StyledText(name, fontSize: 18),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,59 +1,58 @@
|
|||
import 'package:flowy_infra_ui/widget/mouse_hover_builder.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flowy_infra/time/duration.dart';
|
||||
|
||||
class StyledHover extends StatelessWidget {
|
||||
typedef HoverBuilder = Widget Function(BuildContext context, bool onHover);
|
||||
|
||||
class StyledHover extends StatefulWidget {
|
||||
final Color color;
|
||||
final Color borderColor;
|
||||
final double borderWidth;
|
||||
final Widget child;
|
||||
final BorderRadius borderRadius;
|
||||
final HoverBuilder builder;
|
||||
|
||||
const StyledHover({
|
||||
Key? key,
|
||||
required this.color,
|
||||
required this.child,
|
||||
this.borderColor = Colors.transparent,
|
||||
this.borderWidth = 0,
|
||||
this.borderRadius = BorderRadius.zero,
|
||||
required this.builder,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<StyledHover> createState() => _StyledHoverState();
|
||||
}
|
||||
|
||||
class _StyledHoverState extends State<StyledHover> {
|
||||
bool _onHover = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MouseHoverBuilder(
|
||||
builder: (_, isHovered) => AnimatedContainer(
|
||||
final hoverColor =
|
||||
_onHover ? widget.color : Theme.of(context).colorScheme.background;
|
||||
|
||||
final hoverBorder = Border.all(
|
||||
color: widget.borderColor,
|
||||
width: widget.borderWidth,
|
||||
);
|
||||
|
||||
final animatedDuration = .1.seconds;
|
||||
|
||||
return MouseRegion(
|
||||
cursor: SystemMouseCursors.click,
|
||||
onEnter: (p) => setOnHover(true),
|
||||
onExit: (p) => setOnHover(false),
|
||||
child: AnimatedContainer(
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: borderColor, width: borderWidth),
|
||||
color: isHovered ? color : Colors.transparent,
|
||||
borderRadius: borderRadius,
|
||||
border: hoverBorder,
|
||||
color: hoverColor,
|
||||
borderRadius: widget.borderRadius,
|
||||
),
|
||||
duration: .1.seconds,
|
||||
child: child,
|
||||
duration: animatedDuration,
|
||||
child: widget.builder(context, _onHover),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void setOnHover(bool value) => setState(() => _onHover = value);
|
||||
}
|
||||
|
||||
|
||||
// @override
|
||||
// Widget build(BuildContext context) {
|
||||
// return GestureDetector(
|
||||
// behavior: HitTestBehavior.translucent,
|
||||
// onTap: () {
|
||||
// context
|
||||
// .read<HomeBloc>()
|
||||
// .add(HomeEvent.setEditPannel(CellEditPannelContext()));
|
||||
// },
|
||||
// child: MouseHoverBuilder(
|
||||
// builder: (_, isHovered) => Container(
|
||||
// width: width,
|
||||
// decoration: CellDecoration.box(
|
||||
// color: isHovered ? Colors.red.withOpacity(.1) : Colors.transparent,
|
||||
// ),
|
||||
// padding: EdgeInsets.symmetric(
|
||||
// vertical: GridInsets.vertical, horizontal: GridInsets.horizontal),
|
||||
// child: child,
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
// }
|
|
@ -0,0 +1,29 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class StyledMore extends StatelessWidget {
|
||||
final double width;
|
||||
final double? height;
|
||||
final VoidCallback? onPressed;
|
||||
|
||||
const StyledMore({
|
||||
Key? key,
|
||||
required this.width,
|
||||
this.height,
|
||||
this.onPressed,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox(
|
||||
width: width,
|
||||
height: height ?? width,
|
||||
child: IconButton(
|
||||
icon: const Icon(Icons.more_vert),
|
||||
padding: EdgeInsets.zero,
|
||||
iconSize: width / 2,
|
||||
alignment: Alignment.center,
|
||||
onPressed: onPressed,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
import 'package:flutter/widgets.dart';
|
||||
|
||||
class StyledText extends StatelessWidget {
|
||||
final String title;
|
||||
final TextOverflow overflow;
|
||||
final double fontSize;
|
||||
const StyledText(
|
||||
this.title, {
|
||||
Key? key,
|
||||
this.overflow = TextOverflow.fade,
|
||||
this.fontSize = 16,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Text(
|
||||
title,
|
||||
overflow: overflow,
|
||||
softWrap: false,
|
||||
style: TextStyle(fontSize: fontSize),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
|
||||
typedef HoverBuilder = Widget Function(BuildContext context, bool isHovering);
|
||||
typedef HoverBuilder = Widget Function(BuildContext context, bool onHover);
|
||||
|
||||
class MouseHoverBuilder extends StatefulWidget {
|
||||
final bool isClickable;
|
||||
|
@ -17,7 +17,7 @@ class MouseHoverBuilder extends StatefulWidget {
|
|||
}
|
||||
|
||||
class _MouseHoverBuilderState extends State<MouseHoverBuilder> {
|
||||
bool isOver = false;
|
||||
bool _onHover = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -25,11 +25,11 @@ class _MouseHoverBuilderState extends State<MouseHoverBuilder> {
|
|||
cursor: widget.isClickable
|
||||
? SystemMouseCursors.click
|
||||
: SystemMouseCursors.basic,
|
||||
onEnter: (p) => setOver(true),
|
||||
onExit: (p) => setOver(false),
|
||||
child: widget.builder(context, isOver),
|
||||
onEnter: (p) => setOnHover(true),
|
||||
onExit: (p) => setOnHover(false),
|
||||
child: widget.builder(context, _onHover),
|
||||
);
|
||||
}
|
||||
|
||||
void setOver(bool value) => setState(() => isOver = value);
|
||||
void setOnHover(bool value) => setState(() => _onHover = value);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue