-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Provide a border to the active tab container #13
Comments
Hi @soumya-ventura, I created a temporary work around for this issue on my project, by creating a custom widget for the tabs & children. Here is an example rough code for reference, hope it saves someone else time: Example codeimport 'package:tab_container/tab_container.dart';
enum _TabElementType {
firstTab,
firstChild,
secondTab,
secondChild
}
class _TabElement extends StatelessWidget {
final Widget child;
final _TabElementType tabElementType;
final bool onFirstTab;
const _TabElement({
super.key,
required this.child,
required this.tabElementType,
required this.onFirstTab
});
(Border?, BorderRadius) getBorderInfo(context) {
const radiusDegree = 20.0;
// default border for tab child
Border? border = Border.all(
width: 8.0,
color: Color(0xffa275e3)
);
// default borderRadius for tabs
BorderRadius borderRadius = const BorderRadius.only(
topLeft: Radius.circular(radiusDegree),
topRight: Radius.circular(radiusDegree),
);
switch(tabElementType) {
case(_TabElementType.firstTab):
if (!onFirstTab) {
border = null;
}
break;
case(_TabElementType.secondTab):
if (onFirstTab) {
border = null;
}
break;
case(_TabElementType.firstChild):
borderRadius = const BorderRadius.only(
bottomLeft: Radius.circular(radiusDegree),
bottomRight: Radius.circular(radiusDegree),
topRight: Radius.circular(radiusDegree),
);
break;
case(_TabElementType.secondChild):
borderRadius = const BorderRadius.only(
bottomLeft: Radius.circular(radiusDegree),
bottomRight: Radius.circular(radiusDegree),
topLeft: Radius.circular(radiusDegree),
);
break;
}
return (border, borderRadius);
}
@override
Widget build(BuildContext context) {
var (border, borderRadius) = getBorderInfo(context);
return Container(
decoration: BoxDecoration(
border: border,
borderRadius: borderRadius
),
child: SizedBox.expand(
child: child
),
);
}
class _MainContainer extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _MainContainerState();
}
}
class _MainContainerState extends State<_MainContainer> {
late final TabContainerController _tabController;
bool onFirstTab = true;
int currentTabIndex = 0;
@override
void initState() {
_tabController = TabContainerController(length: 2);
_tabController.addListener(() {
setState(() {
onFirstTab = _tabController.index == 0;
currentTabIndex = _tabController.index;
});
});
super.initState();
}
@override
void dispose() {
_tabController.dispose();
}
@override
Widget build(BuildContext context) {
return TabContainer(
controller: _tabController,
radius: 20,
tabs: [
_TabElement(
tabElementType: _TabElementType.firstTab,
onFirstTab: onFirstTab,
child: Text('Select Item')
),
_TabElement(
tabElementType: _TabElementType.secondTab,
onFirstTab: onFirstTab,
child: Text('History')
),
],
isStringTabs: false,
children: [
_TabElement(
tabElementType: _TabElementType.firstChild,
onFirstTab: onFirstTab,
child: Text('Tab 1 - $onFirstTab - $currentTabIndex')
),
_TabElement(
tabElementType: _TabElementType.secondChild,
onFirstTab: onFirstTab,
child: Text('Tab 2 - $onFirstTab - $currentTabIndex')
),
]
);
}
} |
Hi, I have the same problem in my project. I'm going to look at adding the functionality without going through a custom widget and for all tabs not just 2. If you want to follow the progress of the fix I've created a fork of the project here |
import 'dart:math'; import 'package:flutter/gestures.dart'; /// Specifies which side the tabs will be on. /// Specifies which side the tabs will be on. class TabContainerController extends ValueNotifier { extension on double { class _TabMetrics { final int count; double get length => (range / count).clamp(minLength, maxLength); double get totalLength => count * length; class _TabViewport { final Size parentSize; double get side => (tabEdge == TabEdge.top) ? parentSize.width : parentSize.height; double get start => side * tabsStart; double get end => side * tabsEnd; double get range => end - start; Size get size => (tabEdge == TabEdge.top) ? Size(range, tabExtent) : Size(tabExtent, range); bool contains(double x, double y, double totalLength) { /// Displays [children] in accordance with the tab selection. final TabController? controller; final List? children; final Widget? child; final List tabs; final BorderRadius borderRadius; final BorderRadius tabBorderRadius; final EdgeInsets childPadding; final double tabExtent; final TabEdge tabEdge; final double tabsStart; final double tabsEnd; final double tabMinLength; final double tabMaxLength; final Color? color; final Duration duration; final Curve curve; final Duration? childDuration; final Curve? childCurve; final Widget Function(Widget, Animation)? transitionBuilder; final SemanticsConfiguration? semanticsConfiguration; final bool overrideTextProperties; final TextStyle? selectedTextStyle; final TextStyle? unselectedTextStyle; final TextDirection? textDirection; final bool enabled; final bool enableFeedback; final Color topBorderColor; final double topBorderWidth; final Color rightBorderColor; final double rightBorderWidth; final Color bottomBorderColor; final double bottomBorderWidth; final Color leftBorderColor; final double leftBorderWidth; @OverRide class _TabContainerState extends State with SingleTickerProviderStateMixin { TabController? _defaultController; late ScrollController _scrollController; late Widget _child; List _tabs = []; late TextStyle _selectedTextStyle; late TextStyle _unselectedTextStyle; late TextDirection _textDirection; double _progress = 0; Color? _color; @OverRide
} @OverRide @OverRide @OverRide
} double _animationFraction(double current, int previous, int next) { void _animationListener() { void _tabListener() { void _remountController() {
} TextStyle _calculateTextStyle(int index) {
} double _calculateTextScale(int index) {
} Widget _getTab(int index) {
} void _updateTabs(int previous, int next) { void _buildTabs() {
} void _buildChild() {
} @OverRide class TabFrame extends MultiChildRenderObjectWidget { TabFrame({ @OverRide @OverRide class TabFrameParentData extends ContainerBoxParentData {} class RenderTabFrame extends RenderBox BuildContext get context => _context; TabController get controller => _controller; ScrollController get scrollController => _scrollController; double get scrollOffset => _scrollOffset; double get progress => _progress;
} Curve get curve => _curve; Duration get duration => _duration; List get tabs => _tabs; BorderRadius get borderRadius => _borderRadius; BorderRadius get tabBorderRadius => _tabBorderRadius; double get tabExtent => _tabExtent; TabEdge get tabEdge => _tabEdge; Axis get tabAxis => _tabAxis; double get tabsStart => _tabsStart; double get tabsEnd => _tabsEnd; double get tabMinLength => _tabMinLength; double get tabMaxLength => _tabMaxLength; Color get color => _color; SemanticsConfiguration? get semanticsConfiguration => _semanticsConfiguration; bool get enabled => _enabled; bool get enableFeedback => _enableFeedback; TextDirection get textDirection => _textDirection; double get topBorderWidth => _topBorderWidth; Color get topBorderColor => _topBorderColor; Color get rightBorderColor => _rightBorderColor;
} double get rightBorderWidth => _rightBorderWidth; Color get bottomBorderColor => _bottomBorderColor; double get bottomBorderWidth => _bottomBorderWidth; Color get leftBorderColor => _leftBorderColor; double get leftBorderWidth => _leftBorderWidth; @OverRide @OverRide
} @OverRide
} @OverRide @OverRide @OverRide
} late TapGestureRecognizer _tapGestureRecognizer; @OverRide
} double _alignScrollDelta(PointerScrollEvent event) {
} void _handlePointerScroll(PointerSignalEvent event) { void _onPointerScroll(PointerScrollEvent event) {
} void _onTapDown(TapDownDetails details) {
} void _onDragUpdate(DragUpdateDetails details) {
} void _implicitScroll() {
} @OverRide bool _hasTabOverflow = false; late _TabViewport _tabViewport; @OverRide
} @OverRide @OverRide Path? _clipPath; final LayerHandle _clipPathLayer = LayerHandle(); (double, double) _getIndicatorBounds(double factor) {
} void _paint(PaintingContext context, Offset offset) {
} @OverRide void _drawBorder(Canvas canvas, Size size, Color color, double width, BorderSide side) {
} Path _getPath(Size size) {
} Path _getRightBorderPath(Size size) { Path _getBottomBorderPath(Size size) { Path _getLeftBorderPath(Size size) { Try using this code to add border for all sides or a single side. |
Currently there is no way to provide a custom border to the selected tab and body combined. It would be great if there was a way to provide simple border to the active tab container that isn't heavy on the engine.
The text was updated successfully, but these errors were encountered: