I created Custom TabBar that has middle action button inside. For that, i set up this tabbar with empty space where i can render button:
Appshell
<custom:MiddleViewTabBar x:Name="MiddleViewTabBar" FlyoutItemIsVisible="False">
...
<Tab Title="{Binding SomeTitle}" Icon="icon.png">
<ShellContent Title="{Binding SomeTitle}" ContentTemplate="{DataTemplate something:SomePage}" Route="SomeRoute" />
</Tab>
<Tab>
<ShellContent ContentTemplate="{DataTemplate accountOperations:AccountOperationAddPage}" Route="AddAccountOperation" />
</Tab> // This is where i create empty space for button
<Tab Title="{Binding AccountOperationsTitle}" Icon="ic_operations.png">
...
</Tab>
...
</custom:MiddleViewTabBar>
I created CustomShellRenderer
which looks same for iOS
and Android
handlers:
public class CustomShellHandler : ShellRenderer {
protected override IShellItemRenderer CreateShellItemRenderer(ShellItem shellItem) {
return new MiddleShellItemRenderer(this);
}
ShellItemRenderer
for iOS
handler where i placed rendering item inside Grid
:
public class MiddleShellItemRenderer : ShellItemRenderer {
private UIView? _middleView;
public MiddleShellItemRenderer(IShellContext context) : base(context) { }
public override void ViewDidLoad() {
base.ViewDidLoad();
Shell.Current.PropertyChanged += UpdateMiddleViewVisibility;
}
private void UpdateMiddleViewVisibility(object? sender, System.ComponentModel.PropertyChangedEventArgs e) {
if (_middleView is null || Shell.Current.CurrentPage is null) {
return;
}
var tabBarIsVisible = Shell.GetTabBarIsVisible(Shell.Current.CurrentPage);
_middleView.Hidden = !tabBarIsVisible;
}
public override async void ViewWillLayoutSubviews() {
base.ViewWillLayoutSubviews();
if (View is not null && ShellItem is MiddleViewTabBar tabBar) {
if (_middleView is not null) {
_middleView.RemoveFromSuperview();
}
if (_middleView is null) {
var grid = new Grid() {
ColumnDefinitions = [
new ColumnDefinition { Width = GridLength.Star }
],
RowDefinitions = [
new RowDefinition { Height = GridLength.Star }
]
};
var middleViewSize = 50;
var imageButton = new ImageButton {
Source = tabBar.MiddleViewIconSource,
Command = tabBar.MiddleViewCommand,
Margin = new Thickness(0),
Padding = new Thickness(0),
BackgroundColor = Colors.Green,
Aspect = Aspect.AspectFit
};
grid.Children.Add(imageButton);
_middleView = grid.ToPlatform(App.Current.MainPage.Handler.MauiContext);
_middleView.Frame = new CGRect(CGPoint.Empty, new CGSize(middleViewSize, middleViewSize));
_middleView.AutoresizingMask = UIViewAutoresizing.FlexibleRightMargin | UIViewAutoresizing.FlexibleLeftMargin |
UIViewAutoresizing.FlexibleBottomMargin;
_middleView.Layer.CornerRadius = _middleView.Frame.Width / 2;
_middleView.Layer.MasksToBounds = false;
}
_middleView.Center = new CGPoint(View.Bounds.GetMidX(), TabBar.Frame.Top + 4 + _middleView.Frame.Height / 2);
View.AddSubview(_middleView);
}
}
}
I tested this code in IPhone 15 and it look good:
https://imgur.com/a/W34PZfL
but in IPhone SE i see some clipping because size is not adapting https://imgur.com/a/mUeZhuu
. What im doing wrong?
Same problem is in Android
7