0

I am trying to set icons on tabs in my Xamarin app's TabbedView based on the state of the page displayed on the tab. I am able to access a tab individually and setting its icon during rendering on an Android phone emulator, but it does not work on Android tablet emulator.

I am using the DispatchDraw method in a TabbedRenderer based on this post, but I don't have a good understanding though of how that method is called and am having difficulty finding guidance on it.

My code does get called in both devices, but I find that (this.Context as Activity).ActionBar.TabCount is 0 in the tablet every time I check it, while it it is 0 initially but then DispatchDraw is called a second time and its value at that point is 2 (i.e. the tabs have loaded) on the phone, but not on the tablet. That's what allows me to set the icon on the phone, but not the tablet.

Any idea what would differ based only on the change of emulators, to make them render differently in this way?

Here is my TabbedRenderer code:

[assembly: ExportRenderer(typeof(FormTabbedPage), typeof(ExtendedTabbedPageRenderer))]
namespace MyNamespace
{
    public class ExtendedTabbedPageRenderer: TabbedRenderer
    {
        public ExtendedTabbedPageRenderer(Context context) : base(context) { }

        protected override void DispatchDraw(global::Android.Graphics.Canvas canvas)
        {
            base.DispatchDraw(canvas);

            SetTabIcons();
        }

        private void SetTabIcons()
        {

            var element = this.Element;
            if (null == element)
            {
                return;
            }

            Activity activity = this.Context as Activity;
            if ((null != activity && null != activity.ActionBar && activity.ActionBar.TabCount > 0))
            {
                bool hasErrors = false;
                for (int i = 0; i < element.Children.Count; i += 1)
                {
                    hasErrors = ((i % 2) > 0); // This is a placeholder for app specific logic based on page content
                    int resourceID = Resources.GetIdentifier("error", "drawable", Context.PackageName);
                    if (hasErrors)
                    {
                        Drawable icon = Context.GetDrawable(resourceID);
                        Android.App.ActionBar.Tab tab = activity.ActionBar.GetTabAt(i);
                        tab.SetIcon(icon);
                    }
                }


            }
        }

        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
           // do nothing - I have this method for debugging purposes
        }

}

I find that on the tablet, if I initially render the form, I don't get icons, but if I then click on one of the tabs, and if I run the tab logic in OnElementPropertyChanged method instead of DispatchDraw at that point, by then the tabs on the ActionBar ARE populated and I DO get the icons showing.

(Sidenote: one other odd thing is that there is a warning over the ActionBar class saying it's obsolete - not sure what to make of that, since the Activity class contains it as a property and that isn't obsolete.)

Many thanks!

user756366
  • 467
  • 6
  • 24
  • I used your code, my all tabs are hided, If I running your custom renderer code in the Android emulator. Here is compared running screenshot. https://imgur.com/a/FVleTzH – Leon Jun 09 '20 at 06:27
  • @LeonLu-MSFT, Thanks for trying it! One thing that might be different is that it looks like you had icons set by default? My tabs have only text, no icon by default (and when I tried setting IconImageSource on my ContentPage that did not work / no icon showed up), so possibly overwriting an existing icon is what breaks yours? I'm new to Xamarin, working on an existing app, so unfortunately don't know if I can realistically create you a full test app. – user756366 Jun 09 '20 at 15:02
  • Yes, I added the icons by default, If I add the your custom renderer, text and icon are disappear, do you want to change the icon in the runtime? You can create a test demo. – Leon Jun 10 '20 at 09:10
  • @LeonLu-MSFT, I want to change the icon whenever the user either changes tabs or saves using a button at the top. I'm not sure if you'd call that "runtime" or not? Is the "test demo" you reference a different thing (and one more realistic for me to create with my limited Xamarin experience) vs a full test application? – user756366 Jun 10 '20 at 16:22
  • I test your cusom renderer tabbedPage, I found you have a mistake used `TabbedRenderer`, You should use `TabbedPageRenderer` , If I change `TabbedPageRenderer` I can see these tabs. – Leon Jun 12 '20 at 07:03
  • Please see my github link:https://github.com/851265601/Xamarin.Android_ListviewSelect/blob/master/ExtendedTabbedPageRenderer Here is my code. – Leon Jun 12 '20 at 07:15
  • Thank you @LeonLu-MSFT! I think the difference is that you are using AppCompat and we are not - TabbedPageRenderer is in AppCompat. If I use it, then I get the error "Java.Lang.IllegalArgumentException: The style on this component requires your app theme to be Theme.AppCompat (or a descendant)." when I call PushAsync to push the FormTabbedPage to the UI. My reference to TabbedRenderer (not TabbedPageRenderer) was copied from NMackay's code in response to this post: https://forums.xamarin.com/discussion/87756/tabbedpage-icon-next-to-title . Must we switch to AppCompat to get tab icons? – user756366 Jun 12 '20 at 22:49

0 Answers0