Search code examples
androidxamarinxamarin.androidandroid-tablayout

Intercept TabSelected if condition is not valid - Android TabLayout


I am trying to intercept TabSelected EventHandler in the TabLayout, to display a Dialog if some data is not saved. If the user clicks "yes", the new tab selected is displayed. If not, the old tab is displayed (stays the same).

How can I display the previous Tab (if the condition is not valid)?:

MyActivity.cs

private int previousTabPosition =-1;
private TabLayout tabLayout;

...
OnCreate(){
tabLayout = FindViewById<TabLayout>(Resource.Id.tabbar);
tabLayout.SetupWithViewPager(pager);
tabLayout.TabSelected += TabLayout_TabSelected;
...
}
private void TabLayout_TabSelected(object sender, TabLayout.TabSelectedEventArgs e)
    {
        int selectedTab = e.Tab.Position;
    }

My FragmentAdapter:

public class MFragmentAdapter : FragmentStatePagerAdapter
{
    private const int BasePagesCount = 7;

    private FragmentManager fragmentManager;
    private Context context;
    private ItemViewModel Vm;
    private bool canSelect;
    private int pagesCount = BasePagesCount;
    private CustomViewPager viewPager;

    public InterventionFragmentAdapter(ItemViewModel Vm, bool canSelect, Context context, FragmentManager fm, CustomViewPager viewPager) : base(fm)
    {
        this.fragmentManager = fm;
        this.context = context;
        this.Vm = Vm;
        this.canSelect = canSelect;
        this.viewPager = viewPager;
        if (Vm.Troubleshooting())
        {
            pagesCount--;
        }
    }

    public override int Count
    {
        get { return pagesCount; }
    }

    public override Fragment GetItem(int position)
    {
        switch (position)
        {
            case 1:
                return FirstFragment.GetInstance(this.Vm);
            case 2:

                return SecondFragment.GetInstance(this.Vm);
            case 3:
               ....
            default:
                return DefaultFragment.GetInstance(this.Vm, this.canSelect);
        }
    }

    public override ICharSequence GetPageTitleFormatted(int position)
    {
        switch (position)
        {
            case 0:
                return new String(context.GetString(Resource.String.first_tab));
            case 1:
                return new String(context.GetString(Resource.second_tab));
            ....
            default:
                return new String("-");
        }
    }

    public void UpdateFragments(ItemViewModel Vm)
    {
        this.Vm = Vm;
        foreach (Fragment fragment in fragmentManager.Fragments)
        {
            if (fragment is IChangeListener)
            {
                (fragment as IChangeListener).OnObjectChanged(Vm);
            }
        }
    }


    public int GetFirstPageIndex()
    {
        if (pagesCount == BasePagesCount)
        {
            return 4;
        }
        else
        {
            return 3;
        }
    }


    public int GetSecondPageIndex()
    {
        if (pagesCount == BasePagesCount)
        {
            return 3;
        }
        return -1;
    }
...
    }

MyActivity.axml:

        <android.support.design.widget.TabLayout
        android:id="@+id/tabbar"
        android:layout_width="match_parent"
        android:layout_height="48dp"
        android:layout_gravity="bottom"
        android:background="?attr/colorPrimary"
        app:tabContentStart="30dp"
        app:tabGravity="center"
        app:tabIndicatorColor="?attr/colorAccent"
        app:tabMode="scrollable"
        app:tabSelectedTextColor="?attr/colorAccent"
        app:tabTextAppearance="@style/TabLayoutTextAppearance"
        app:tabTextColor="@android:color/white"/>
        <Project.Views.Droid.CustomViewPager
        android:id="@+id/pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

Thank you for your help.


Solution

  • Dont use tabLayout.TabSelected event and intercept the tabLayout.Clicked event

    create a SimpleFragmentPagerAdapter :

      public class SimpleFragmentPagerAdapter : FragmentPagerAdapter
        {
    
            private static string[] mTitles = { "tab1", "tab2", "tab3" };
            private TablayoutActivity tablayoutActivity;
    
            public SimpleFragmentPagerAdapter(Android.Support.V4.App.FragmentManager fm, TablayoutActivity tablayoutActivity) : base(fm)
            {
                this.tablayoutActivity = tablayoutActivity;
            }
    
            public override int Count => mTitles.Length;
    
            public override Android.Support.V4.App.Fragment GetItem(int position)
            {
                return PageFragment.newInstance(position + 1);
            }
            //custom Tab's style
            public View GetTabView(int position)
            {
                View tabView = LayoutInflater.From(tablayoutActivity).Inflate(Resource.Layout.tabitem, null);
                TextView textView = tabView.FindViewById<TextView>(Resource.Id.tv);
                textView.Text = mTitles[position];
                return tabView;
            }
        }
    

    then in OnCreate method :

    protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
            SetContentView(Resource.Layout.tablayout);
            // Create your application here
            pagerAdapter = new SimpleFragmentPagerAdapter(SupportFragmentManager, this);
            viewPager = (ViewPager)FindViewById(Resource.Id.viewpager);
            tabLayout = (TabLayout)FindViewById(Resource.Id.tabs);
            pagerAdapter = new SimpleFragmentPagerAdapter(SupportFragmentManager, this);
            viewPager.Adapter=pagerAdapter;
            tabLayout.SetupWithViewPager(viewPager);
    
            //Set the tablayout.Tab's style and intercept the tabLayout.Clicked event by use "tabView.SetOnTouchListener"
            for (int i = 0; i < tabLayout.TabCount; i++)
            {
                TabLayout.Tab tab = tabLayout.GetTabAt(i);
                if (tab != null)
                {
                    tab.SetCustomView(pagerAdapter.GetTabView(i));
                    if (tab.CustomView != null)
                    {
                        View tabView = (View)tab.CustomView.Parent;
                        tabView.Tag=i;
                        tabView.SetOnTouchListener(this);
                    }
                }
            }
        }
    

    finally,in the OnTouch method:

    public bool OnTouch(View v, MotionEvent e)
        {
           if(e.Action == MotionEventActions.Down) { 
            int pos = (int)v.Tag;
            AlertDialog alertDialog = new AlertDialog.Builder(this)
                    .SetTitle("notice")
                    .SetMessage("Have you saved data?")
                    //if no will stay current tab
                    .SetNegativeButton("No", delegate
                    {
                        return;
                    })
                    //if yes will display new tab
                    .SetPositiveButton("Yes", delegate
                    {
                        TabLayout.Tab tab = tabLayout.GetTabAt(pos);
                        if (tab != null)
                        {
                            tab.Select();
                        }
                    })
    
                    .Create();
    
            alertDialog.Show();
            }
            return true;
        }