Android, Swipe tab layout, sliding tabs

Hi Everyone,

I've been looking for a simple way to have sliding tabs in my Xamarin Android application.
Kind of like Windows Phone Pivots.

I have already tried a few things so far:

  • Actionbar tabs + Gesture listener (worked well but would like an animation between sliding)
  • xamarin.android.support.v4 (Cannot get it working on any of the tests or samples I have tried)
  • FortySevenDeg.SwipeListView (Could not get sample working, possibly because it uses xamarin.android.support.v4)

Any help would be greatly appreciated!

Rohan

Best Answer

Answers

  • YkshLeoYkshLeo USMember ✭✭✭✭

    @RohanWilliams

    Try these Sample, It will work well for you :smile:

  • rzee7rzee7 INUniversity ✭✭✭✭✭

    This library has been deprecated now, but still you can grab code smartly ;)

  • Thanks @rzee7 and @Yksh.Leo !!
    I ended up getting the sample to work from the "Xamarin Android Tutorial 10 Sliding Tab Interface" video when I couldn't before. Problem was with the package xamarin.android.support.v4 giving errors on compile, I fixed it by re-downloading the package in a new project and also changing some of the build options.

  • LearnEverythingLearnEverything USMember ✭✭✭
    edited September 1

    The best in C# is you can create more reusable and cleaner code compared to the Java.

    Reusable SlidingTab

    using System;
    using System.Collections.Generic;
    using Android.OS;
    using Android.Support.V4.App;
    using Android.Support.V4.View;
    using Android.Support.V7.App;
    using com.refractored;
    using XamarinAndroid.Basic.Core;
    using Toolbar = Android.Support.V7.Widget.Toolbar;
    namespace Sample
    {
    
        public abstract class SlidingTabActivity: AppCompatActivity, IOnTabReselectedListener, ViewPager.IOnPageChangeListener
        {
            public Toolbar Toolbar { get; set; }
            protected int ActionBarIcon
            {
                set { Toolbar.SetNavigationIcon(value); }
            }
            public int ToolbarId { get; set; } = 0;
            protected abstract int LayoutResource { get; }
            protected abstract int ViewPagerId { get; }
    
            protected abstract int PagerSlidingTabStripId { get; }
    
            protected abstract int ResourceMenu { get; }
    
            protected abstract List<Fragment> Fragments { get; }
            //Public
            public ViewPager ViewPager { get; private set; }
            public PagerSlidingTabStrip PagerSlidingTabStrip { get; private set; }
    
            public int SelectedIndex { get; set; } = 0;
            //Private
            private GenericFragmentPagerAdapter Adapter { get; set; }
    
            protected override void OnCreate(Bundle bundle)
            {
                base.OnCreate(bundle);
                SetContentView(LayoutResource);
    
                Adapter = new GenericFragmentPagerAdapter(SupportFragmentManager, Fragments);
                this.ViewPager = FindViewById<ViewPager>(ViewPagerId);
                this.PagerSlidingTabStrip = FindViewById<PagerSlidingTabStrip>(PagerSlidingTabStripId);
                this.ViewPager.Adapter = Adapter;
                this.PagerSlidingTabStrip.SetViewPager(this.ViewPager);
                //var pageMargin = (int) TypedValue.ApplyDimension(ComplexUnitType.Dip, 4, Resources.DisplayMetrics);
                //pager.PageMargin = pageMargin;
                this.ViewPager.CurrentItem = SelectedIndex;
                this.PagerSlidingTabStrip.OnTabReselectedListener = this;
                this.PagerSlidingTabStrip.OnPageChangeListener = this;
    
                if (ToolbarId != 0)
                {
                    Toolbar = FindViewById<Toolbar>(ToolbarId);
                    if (Toolbar != null)
                    {
                        SetSupportActionBar(Toolbar);
    
                        SupportActionBar.SetDisplayHomeAsUpEnabled(true);
                        SupportActionBar.SetHomeButtonEnabled(true);
                    }
                }
            }
    
            #region IOnTabReselectedListener implementation
            public event EventHandler<int> TabSelected;
            public void OnTabReselected(int position)
            {
                this.TabSelected?.Invoke(this, position);
            }
    
            public event EventHandler<int> PageScrollStateChanged;
            public void OnPageScrollStateChanged(int state)
            {
                this.PageScrollStateChanged?.Invoke(this, state);
            }
            public event EventHandler PageScrolled;
            public void OnPageScrolled(int position, float positionOffset, int positionOffsetPixels)
            {
                this.PageScrolled?.Invoke(this, new EventArgs());
            }
            public event EventHandler<int> PageSelected;
            public void OnPageSelected(int position)
            {
                this.PageSelected?.Invoke(this, position);
            }
            #endregion
            #region menu
            public override bool OnCreateOptionsMenu(Android.Views.IMenu menu)
            {
                var inflater = MenuInflater;
                inflater.Inflate(ResourceMenu, menu);
                return base.OnCreateOptionsMenu(menu);
            }
            public event EventHandler<Android.Views.IMenuItem> MenuItemSelected;
            public override bool OnOptionsItemSelected(Android.Views.IMenuItem item)
            {
                // Handle presses on the action bar items
                this.MenuItemSelected?.Invoke(this, item);
                return base.OnOptionsItemSelected(item);
            }
            #endregion
        }
    
    
    }
    

    XML Main

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:fitsSystemWindows="true">
        <include
            layout="@layout/toolbar" />
        <com.refractored.PagerSlidingTabStrip
            android:id="@+id/tabs"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:pstsPaddingMiddle="true"
            app:pstsDividerWidth="1dp"
            app:pstsDividerPadding="12dp"
            app:pstsDividerColor="#50FFFFFF"
            android:textColor="#50FFFFFF"
            app:pstsTextColorSelected="@android:color/white"
            app:pstsIndicatorColor="@android:color/white"
            app:pstsUnderlineColor="@android:color/white" />
    <!--Change this to true if you want to center items-->
        <android.support.v4.view.ViewPager
            android:id="@+id/pager"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            tools:context=".MainActivity" />
    
    </LinearLayout>
    

    Generic Adapters

    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Linq;
    using Android.Support.V4.App;
    using Java.Lang;
    using Fragment = Android.Support.V4.App.Fragment;
    
    
    namespace XamarinAndroid.Basic.Core
    {
        public class GenericFragmentPagerAdapter : FragmentPagerAdapter
        {
    
            public ObservableCollection<Fragment> Fragments { get; }
            public string[] Headers { get; set; }
            public GenericFragmentPagerAdapter(FragmentManager fm, IEnumerable<Fragment> fragments) : base(fm)
            {
                Headers = new string[fragments.Count()];
                int counter = 0;
                string header = "";
                foreach (var item in fragments)
                {
                    var name = (item.GetType().Name);
                    header = header == name ? name + counter : name ;               
                    Headers[counter] = header;
                    counter++;
                }
                this.Fragments = new ObservableCollection<Fragment>(fragments);
            }
            public override int Count
            {
                get { return this.Fragments.Count; }
            }
    
            public override Android.Support.V4.App.Fragment GetItem(int position)
            {
                return this.Fragments[position];
            }
            public override ICharSequence GetPageTitleFormatted(int position)
            {
                return new String(Headers[position]);
            }
        }
    }
    

    Result

    Activity

    using System.Collections.Generic;
    using Android.OS;
    using WordNet.Simplified.Standard.Models;
    using XamarinAndroid.Basic.Core;
    using XamarinAndroid.Basic.Helpers;
    using XamarinAndroid.Helpers;
    using Activity = Android.App;
    using Android.App;
    using XamarinAndroid.Basic.Views;
    using com.refractored;
    using XamarinAndroid.Styles;
    using Android.Support.V4.App;
    
    namespace XamarinAndroid.ActivityFragments
    {
        [Activity(Label = "Detail")]
        public class FragmentTabActivity : SlidingTabActivity
        {
    
            protected override int LayoutResource => Resource.Layout.detail_fragment_tab_activity;
    
            protected override int ViewPagerId => Resource.Id.pager;
    
            protected override int PagerSlidingTabStripId => Resource.Id.tabs;
    
            protected override int ResourceMenu => Resource.Menu.detail_menu;
    
    
            protected override List<Android.Support.V4.App.Fragment> Fragments => this.GetFragments();
    
            protected override void OnCreate(Bundle savedInstanceState)
            {
                var background = ThemeHelper.GetMainActivityThemeDrawable();
                Window.SetBackgroundDrawableResource(background);
                this.SetTheme(ThemeHelper.GetApplicationColorStyle());
                base.OnCreate(savedInstanceState);
    
                // Create your application here
            }
    
            private List<Android.Support.V4.App.Fragment> GetFragments()
            {
                var result = NavigationService.Parameter as CollectionResultModel;
                List<Android.Support.V4.App.Fragment> fragments = new List<Android.Support.V4.App.Fragment>();
                GenericFragment fragmentDefinition = new GenericFragment(Resource.Layout.detail_def_fragment);
                fragmentDefinition.ViewCreated += (ss, view) =>
                {
                     DefinitionHelper.CreateDefinition(this, view, result);
                };
                fragments.Add(fragmentDefinition);
    
                GenericFragment fragmentRelation = new GenericFragment(Resource.Layout.detail_relation_carview);
                fragmentRelation.ViewCreated += (ss, view) =>
                {
                    RelationHelper.CreateRelation(this, view, result);
                };
                fragments.Add(fragmentRelation);
                return fragments;
            }
    
        }
    
    }
    

    Generic Fragment Item

    using System;
    using Android.OS;
    using Android.Views;
    using Fragment = Android.Support.V4.App.Fragment;
    
    namespace XamarinAndroid.Basic.Core
    {
        public class GenericFragment : Fragment
        {
    
            private int LayoutId { get; }
            public GenericFragment(int layoutId)
            {
                this.LayoutId = layoutId;
            }
            public event EventHandler<View> ViewCreated;
            public override void OnCreate(Bundle savedInstanceState)
            {
                base.OnCreate(savedInstanceState);
    
                // Create your fragment here
            }
    
    
            public override Android.Views.View OnCreateView(Android.Views.LayoutInflater inflater, Android.Views.ViewGroup container, Bundle savedInstanceState)
            {
                var view = inflater.Inflate(this.LayoutId, container, false);
                this.ViewCreated?.Invoke(this, view);
                return view;
            }
        }
    }
    
Sign In or Register to comment.