Quantcast
Channel: Recent Threads — Xamarin Community Forums
Viewing all articles
Browse latest Browse all 204402

Shell bottom Navigation How to implent to shell renderer for android and ios?

$
0
0

//BottomTabbedPageExtensions.cs

using Xamarin.Forms;

namespace SchedulingTool.Helpers
{
public class BottomTabbedPageExtensions
{
public static readonly BindableProperty TabColorProperty = BindableProperty.CreateAttached(
"TabColor",
typeof(Color),
typeof(BottomTabbedPageExtensions),
Color.Transparent);

    public static readonly BindableProperty BadgeCountProperty = BindableProperty.CreateAttached(
        "BadgeCount",
        typeof(int),
        typeof(BottomTabbedPageExtensions),
        0);

    public static readonly BindableProperty BadgeColorProperty = BindableProperty.CreateAttached(
        "BadgeColor",
        typeof(Color),
        typeof(BottomTabbedPageExtensions),
        Colors.OrangeColor);

    public static readonly BindableProperty IsTabVisibleProperty = BindableProperty.CreateAttached(
        "IsTabVisible", typeof(bool), typeof(BottomTabbedPageExtensions), true);

    public static void SetIsTabVisible(BindableObject bindable, bool visible)
    {
        bindable.SetValue(IsTabVisibleProperty, visible);
    }

    public static bool GetIsTabVisible(BindableObject bindable)
    {
        return (bool)bindable.GetValue(IsTabVisibleProperty);
    }

    public static void SetTabColor(BindableObject bindable, Color color)
    {
        bindable.SetValue(TabColorProperty, color);
    }

    public static Color GetTabColor(BindableObject bindable)
    {
        return (Color)bindable.GetValue(TabColorProperty);
    }

    public static void SetBadgeCount(BindableObject bindable, int badgeCount)
    {
        bindable.SetValue(BadgeCountProperty, badgeCount);
    }

    public static int GetBadgeCount(BindableObject bindable)
    {
        return (int)bindable.GetValue(BadgeCountProperty);
    }

    public static void IncreaseBadgeCountBy(BindableObject bindable, int increaseBy)
    {
        int currentValue = GetBadgeCount(bindable);
        if(currentValue == 0 && increaseBy < 0)
        {
            bindable.SetValue(BadgeCountProperty, 0);
        }

        if(increaseBy < 0 && (increaseBy > currentValue))
        {
            bindable.SetValue(BadgeCountProperty, 0);
        }

        bindable.SetValue(BadgeCountProperty, currentValue + increaseBy);
    }

    public static void SetBadgeColor(BindableObject bindable, Color color)
    {
        bindable.SetValue(BadgeColorProperty, color);
    }

    public static Color GetBadgeColor(BindableObject bindable)
    {
        return (Color)bindable.GetValue(BadgeColorProperty);
    }
}

}

//DroidBottomTabbedPageRenderer.cs

using System;
using System.Collections.Generic;
using System.Linq;

using Android.Content;
using Android.Support.Design.Widget;
using Android.Views;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android.AppCompat;
using View = Android.Views.View;
using AndroidRelativeLayout = Android.Widget.RelativeLayout;
using RelativeLayoutParams = Android.Widget.RelativeLayout.LayoutParams;

using Android.Support.Design.Internal;
using Xamarin.Forms.Platform.Android;
using System.ComponentModel;
using Android.Widget;
using Android.Graphics.Drawables;
using Android.Graphics.Drawables.Shapes;
using Android.Util;
using Android.Support.V4.View;

[assembly: ExportRenderer(typeof(ExtendedBottomTabbedPage), typeof(DroidBottomTabbedPageRenderer))]
namespace SchedulingTool.Droid.Renderers
{
public class DroidBottomTabbedPageRenderer : TabbedPageRenderer, BottomNavigationView.IOnNavigationItemReselectedListener
{
IDictionary<Page, string> _formsBadges;
List _androidBadges;

    bool _isShiftModeSet;
    int _l, _t, _r, _b, _width, _height, _tabsHeight;
    bool _firstTime;
    int _bottomBarHeight;
    Context _context;
    TabLayout _topBar;
    TabbedPage _tabbedPage;
    BottomNavigationView _bottomBar;
    AndroidRelativeLayout _container;
    RelativeLayoutParams _layoutParams;
    List<BottomNavigationItemView> _tabBarItems;
    ExtendedBottomTabbedPage _extendedTabbedPage;

    public DroidBottomTabbedPageRenderer(Context context) : base(context)
    {
        _context = context;
    }

    protected override void OnElementChanged(ElementChangedEventArgs<TabbedPage> e)
    {
        base.OnElementChanged(e);

        if (e.NewElement != null)
        {
            _tabbedPage = e.NewElement;
            _extendedTabbedPage = (ExtendedBottomTabbedPage)_tabbedPage;
            _firstTime = true;
            _tabBarItems = new List<BottomNavigationItemView>();
            _androidBadges = new List<TextView>();

            var children = GetAllChildViews(ViewGroup);

            foreach (var bottomNavItemView in children)
            {
                if (bottomNavItemView is BottomNavigationItemView)
                {
                    var tab = (BottomNavigationItemView)bottomNavItemView;
                    _tabBarItems.Add(tab);
                    AddBadge(tab);
                }
            }
            if (children.SingleOrDefault(x => x is BottomNavigationView) is BottomNavigationView bottomNav)
            {
                _bottomBar = bottomNav;
                _bottomBar.SetOnNavigationItemReselectedListener(this);
            }
            if(children.SingleOrDefault(x => x is AndroidRelativeLayout) is AndroidRelativeLayout container)
            {
                _container = container;
            }
            if (children.SingleOrDefault(x => x is TabLayout) is TabLayout topNav)
            {
                _topBar = topNav;
            }

            SetTabBadges();
            AddPropertyChangedHandlersForPages();
        }
    }

    protected override void OnLayout(bool changed, int l, int t, int r, int b)
    {
        try
        {
            base.OnLayout(changed, l, t, r, b);

            _width = r - l;
            _height = b - t;
            _tabsHeight = Math.Min(_height, Math.Max(_bottomBar.MeasuredHeight, _bottomBar.MinimumHeight));

            _l = l;
            _t = t;
            _r = r;
            _b = b;

            if (!_isShiftModeSet)
            {
                _bottomBar.SetShiftMode(false, false);
                _isShiftModeSet = true;
            }
        }
        catch (Exception ex)
        {
            ExceptionHandler.LogException(this, nameof(OnLayout), ex);
        }
    }

    protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        base.OnElementPropertyChanged(sender, e);
        if (e.PropertyName == nameof(ExtendedBottomTabbedPage.BottomTabBarHidden))
        {
            HideTabbedPage();
        }
    }

    public async void OnNavigationItemReselected(IMenuItem item)
    {
        await _extendedTabbedPage.CurrentPage.Navigation.PopToRootAsync();
    }

    List<View> GetAllChildViews(View view)
    {
        if (!(view is ViewGroup group))
        {
            return new List<View> { view };
        }

        var result = new List<View>();

        for (int i = 0; i < group.ChildCount; i++)
        {
            var child = group.GetChildAt(i);

            var childList = new List<View> { child };
            childList.AddRange(GetAllChildViews(child));

            result.AddRange(childList);
        }

        return result.Distinct().ToList();
    }

    void AddPropertyChangedHandlersForPages()
    {
        foreach (var page in _extendedTabbedPage.Children)
        {
            page.PropertyChanged += OnPagePropertyChanged;
        }
    }

    void OnPagePropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == BottomTabbedPageExtensions.BadgeCountProperty.PropertyName)
        {
            var page = (Page)sender;
            UpdateBadgeForPage(page);
        }
    }

    void SetTabBadges()
    {
        var tabCount = _tabbedPage.Children.Count();
        _formsBadges = new Dictionary<Page, string>(tabCount);

        for (var i = 0; i < tabCount; i++)
        {
            var page = _tabbedPage.Children[i];
        }
    }

    void AddBadge(BottomNavigationItemView frame)
    {
        View badge = LayoutInflater.From(_context).Inflate(Resource.Layout.NotificationBadge, frame, false);
        frame.AddView(badge);
        TextView textViewBadge = (TextView)badge.FindViewById(Resource.Id.notifications_badge);

        var backgroundShape = CreateBackgroundShape();
        backgroundShape.Paint.Color = Colors.OrangeColor.ToAndroid();
        ViewCompat.SetBackground(textViewBadge, backgroundShape);

        _androidBadges.Add(textViewBadge);
    }

    void UpdateBadgeForPage(Page page)
    {
        if (_tabbedPage == null) return;

        var pageIndex = _tabbedPage.Children.IndexOf(page);
        var badgeCount = BottomTabbedPageExtensions.GetBadgeCount(page);

        if (!_formsBadges.ContainsKey(page))
        {
            _formsBadges.Add(page, page.Title);
        }

        var badge = _androidBadges[pageIndex];
        var tab = _tabBarItems[pageIndex];

        if (badgeCount <= 0)
        {
            badge.Visibility = ViewStates.Gone;
            return;
        }

        badge.Visibility = ViewStates.Visible;
        badge.Text = badgeCount > 99 ? "99+" : badgeCount.ToString();

    }

    void HideTabbedPage()
    {
        if (_firstTime)
        {
            _layoutParams = (RelativeLayoutParams)_bottomBar.LayoutParameters;
            _l = _layoutParams.LeftMargin;
            _t = _layoutParams.TopMargin;
            _r = _layoutParams.RightMargin;
            _b = _layoutParams.BottomMargin;
            _bottomBarHeight = _layoutParams.Height;
            _firstTime = false;
        }

        if (_extendedTabbedPage.BottomTabBarHidden)
        {
            _layoutParams.Height = 0;
            _bottomBar.LayoutParameters = _layoutParams;
            //_topBar.Visibility = ViewStates.Gone;
            //_bottomBar.LayoutParameters = new global::Android.Widget.RelativeLayout.LayoutParams(0,0);
            //_container.Invalidate();
            //_bottomBar.Visibility = ViewStates.Gone;
            //Measure(MeasureSpecFactory.MakeMeasureSpec(_width, MeasureSpecMode.Exactly), MeasureSpecFactory.MakeMeasureSpec(_tabsHeight, MeasureSpecMode.Exactly));
            //Layout(_l, _t, _r, _b);
        }
        else
        {
            _layoutParams.Height = _bottomBarHeight;
            _bottomBar.LayoutParameters = _layoutParams;
            //_topBar.Visibility = ViewStates.Visible;
            //_container.Invalidate();
            //_bottomBar.Visibility = ViewStates.Visible;
            //Measure(MeasureSpecFactory.MakeMeasureSpec(_width, MeasureSpecMode.Exactly), MeasureSpecFactory.MakeMeasureSpec(_tabsHeight, MeasureSpecMode.Exactly));
            //Layout(_l, _t, _r, _b);
        }
    }

    ShapeDrawable CreateBackgroundShape()
    {
        var radius = DpToPixels(12);
        var outerR = new float[] { radius, radius, radius, radius, radius, radius, radius, radius };
        return new ShapeDrawable(new RoundRectShape(outerR, null, null));
    }

    int DpToPixels(float dip)
    {
        return (int)TypedValue.ApplyDimension(ComplexUnitType.Dip, dip, Resources.DisplayMetrics);
    }

}

public static class AndroidHelpers
{
    public static void SetShiftMode(this BottomNavigationView bottomNavigationView, bool enableShiftMode, bool enableItemShiftMode)
    {
        try
        {
            var menuView = bottomNavigationView.GetChildAt(0) as BottomNavigationMenuView;
            if (menuView == null)
            {
                System.Diagnostics.Debug.WriteLine("Unable to find BottomNavigationMenuView");
                return;
            }


            var shiftMode = menuView.Class.GetDeclaredField("mShiftingMode");

            shiftMode.Accessible = true;
            shiftMode.SetBoolean(menuView, enableShiftMode);
            shiftMode.Accessible = false;
            shiftMode.Dispose();


            for (int i = 0; i < menuView.ChildCount; i++)
            {
                var item = menuView.GetChildAt(i) as BottomNavigationItemView;
                if (item == null)
                    continue;

                item.SetShiftingMode(enableItemShiftMode);
                item.SetChecked(item.ItemData.IsChecked);

            }

            menuView.UpdateMenuView();
        }
        catch (Exception ex)
        {
            System.Diagnostics.Debug.WriteLine($"Unable to set shift mode: {ex}");
        }
    }
}

}

//ExtendedBottomTabbedPage.cs

using Xamarin.Forms;

namespace SchedulingTool.Renderers
{
public class ExtendedBottomTabbedPage : TabbedPage
{
#region Properties & Commands

    public static readonly BindableProperty TabBarHiddenProperty =
        BindableProperty.Create(nameof(BottomTabBarHidden), typeof(bool), typeof(ExtendedBottomTabbedPage), false);

    public bool BottomTabBarHidden
    {
        get { return (bool)GetValue(TabBarHiddenProperty); }
        set { SetValue(TabBarHiddenProperty, value); }
    }

    public enum BarThemeTypes { Light, DarkWithAlpha, DarkWithoutAlpha }

    public BarThemeTypes BarTheme { get; set; }

    public bool FixedMode { get; set; }

    #endregion

    #region Methods

    public void RaiseCurrentPageChanged()
    {
        OnCurrentPageChanged();
    }

    #endregion
}

}


Viewing all articles
Browse latest Browse all 204402

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>