[Guide + Code] Adding Pull To Refresh to Xamarin.Forms Android apps

JamesMontemagnoJamesMontemagno USForum Administrator, Xamarin Team, Developer Group Leader Xamurai
edited September 2015 in Xamarin.Forms

I already posted about how you can do this on iOS with a custom TableViewRenderer, however last night I finally got it working on Android using the Support v4 SwipeRefreshLayout:

Here is my blog post with code: http://motzcod.es/post/103224921992/pull-swipe-to-refresh-for-xamarin-forms-android-apps

UPDATE
See the new official way here: http://motzcod.es/post/113280718807/official-pull-to-refresh-in-xamarinforms-140

If you need scroll view please check out my new article and code base: http://motzcod.es/post/128274430137/pull-to-refresh-anyish-xamarinforms-view

«1

Posts

  • OnnoJOnnoJ NLUniversity ✭✭

    Awesome work! Been trying to figure this out for a while now.

    Thank you so much for this!

  • DKurkinDKurkin GBMember ✭✭

    Thank you James for great article.

    Any thoughts on why ContentView not contain any data when its added to ContentPage with other elements, eg. as part of stacklayout?

  • JamesMontemagnoJamesMontemagno USForum Administrator, Xamarin Team, Developer Group Leader Xamurai

    @DanilKurkin‌ I will take a look, it is very much concept. I usually just make it the root of the page. I will mess around with it.

  • DKurkinDKurkin GBMember ✭✭
    edited December 2014

    Update - problem solved by figuring out correct references !

  • JamesMontemagnoJamesMontemagno USForum Administrator, Xamarin Team, Developer Group Leader Xamurai

    @DanilKurkin as long as you set

    VerticalOptions = LayoutOptions.FillAndExpand,

    on the pulltorefreshcontentview you can put it in a stacklayout as well. Worked for me well.

  • VincentPoirierVincentPoirier CAMember ✭✭

    This tutorial mentions it's an Android implementation for Xamarin.Forms, does it work only for Android? Or if we implement it the same way you did, it'll compile and work for other platforms as well?

    Forgive my beginner ignorance! :blush:

  • JamesMontemagnoJamesMontemagno USForum Administrator, Xamarin Team, Developer Group Leader Xamurai

    @VincentPoirier‌ this is specific to Android you would need a separate implementation for iOS which I blogged about here: http://motzcod.es/post/87917979362/pull-to-refresh-for-xamarin-forms-ios

  • VincentPoirierVincentPoirier CAMember ✭✭

    Thank you that's great!
    I bet that'll become a Xamarin.Forms control later.

  • DKurkinDKurkin GBMember ✭✭
    edited December 2014

    @VincentPoirier‌ @JamesMontemagno‌

    Ok - that would be my little contribution to the topic: shared code for forms(iOS and android)
    Please note that base of the code comes from James's blogpost - this is just an example of shared code for the view

    var layout = new Grid {your grid}
    
    
     listView2 = new PullToRefreshListView
    
    {
         RefreshCommand = viewModel.RefreshCommand,
                 Message = "loading...",
                 ItemTemplate = new DataTemplate(typeof(SearchCell)),
    };
    
    if (Device.OS == TargetPlatform.iOS)
             {
        listView2.SetBinding<searchViewModel>(PullToRefreshListView.IsRefreshingProperty, vm => vm.IsBusy);
                listView2.SetBinding<searchViewModel>(PullToRefreshListView.ItemsSourceProperty, vm =>          vm.BookingGroupedSearch);
                layout.Children.Add(listView2, 0,1);
                contentView.Content = layout;
             }
    
    if (Device.OS == TargetPlatform.Android)
             {
                listView2.SetBinding<searchViewModel>(ListView.ItemsSourceProperty, vm => vm.BookingGroupedSearch);
        refreshView = new PullToRefreshContentView
                 {
            RefreshCommand = viewModel.RefreshCommand,
                     Content = listView2
                 };
        refreshView.SetBinding<searchViewModel>(PullToRefreshContentView.IsRefreshingProperty, vm => vm.IsBusy);
        layout.Children.Add(refreshView, 0, 1);
                 contentView.Content = layout;
             }
    
     contentView.BindingContext = viewModel;
    
  • ebetzlerebetzler USMember ✭✭

    The Android project in the repository has 2 classes, 'PullToRefreshContentViewRenderer' and 'FormsSwipeRefreshLayout' which seem to be almost the same thing, except, PullToRefreshContentViewRenderer has none of the IVisualElementRenderer overrides implemented. Which is the correct renderer?

  • JamesMontemagnoJamesMontemagno USForum Administrator, Xamarin Team, Developer Group Leader Xamurai

    @ebetzler‌ The "PullToRefreshContentView" is the control that you use in your Shared UI Logic. This is the control itself that has custom bindable properties.

    The "FormsSwipeRefreshLayout" is the actual renderer and has all the implementation to actually get it rendering correct. I hope that helps, the blog should clear it up.

  • ebetzlerebetzler USMember ✭✭

    Thanks James. I have it working, but just FYI.. the source repo I am looking at has a file in the ANDROID project (not the shared project) which is called "PullToRefreshContentViewRenderer.cs", which appears to not be used.

  • JamesMontemagnoJamesMontemagno USForum Administrator, Xamarin Team, Developer Group Leader Xamurai

    Gotcha, it was just a file sitting around in the folder not actually in the project at all. I have deleted it. Thanks.

  • AzucenaFAzucenaF MXMember ✭✭
    edited January 2015

    Hi @JamesMontemagno‌, how would you implement this for a pull from the bottom refresh?

    For viewing older items when they appear ordered from the most recent to the oldest

  • JamesMontemagnoJamesMontemagno USForum Administrator, Xamarin Team, Developer Group Leader Xamurai

    @AzucenaF‌ So a pull from the bottom isn't too standard that I have seen. I haven't really looked into it. Normally you would detect if the list has reached the bottom and if there are more then you would just set refreshing to true and display the load more on top. Swarm does this in their android app.

  • AzucenaFAzucenaF MXMember ✭✭

    Thanks @JamesMontemagno‌ How do you detect if the list has reached the bottom? (I'm using X.Forms for an android and iOS app)

  • JamesMontemagnoJamesMontemagno USForum Administrator, Xamarin Team, Developer Group Leader Xamurai

    @AzucenaF Somewhere in the standard list you can detect when visibility has changed on cells and see when the last one is visible... let me look at some code later and do a post on it. I will report back.

  • AzucenaFAzucenaF MXMember ✭✭

    @JamesMontemagno‌ Thanks! That would be great :smiley:

  • JamesMontemagnoJamesMontemagno USForum Administrator, Xamarin Team, Developer Group Leader Xamurai
  • AzucenaFAzucenaF MXMember ✭✭

    Awesome @JamesMontemagno‌!! it's so easy I can believe it. Thanks!

  • ebetzlerebetzler USMember ✭✭

    Any idea of why this only works with ListView as Content? Android list views with images don't work so great for me, so I am building up a grid (contained in a scrollview) programatically each time I refresh. However, can't add the scrollview as the PullToRefresh content because of the limitation.

  • JamesMontemagnoJamesMontemagno USForum Administrator, Xamarin Team, Developer Group Leader Xamurai

    @ebetzler you might be able to change this by changing the CanChildScrollUp () which currently casts to a ListView and then you would have to detect if the ScrollView is at the top or not.

  • ebetzlerebetzler USMember ✭✭

    Thanks for the reply James. Yeah, I did that. But it still doesn't work. What I get is an empty space (grid does not draw).

  • JamesMontemagnoJamesMontemagno USForum Administrator, Xamarin Team, Developer Group Leader Xamurai
    edited January 2015

    Try setting:

    VerticalOptions = LayoutOptions.FillAndExpand,

    on the pulltorefreshcontentview and your Grid.

    You might also try setting different background colors on all of your items to see what is really being displayed. This is a good way to debug what is actually expanding.

  • anandjitbanerjee.5636anandjitbanerjee.5636 USUniversity ✭✭

    @ebetzler ..Were you able to customize this for scroll view?

  • The pull to refresh content view works only when I place it as a content of a page.But when I am using it as a children in a stack layout it does not work.Any suggestions?

  • VenkataSeshaiahVenkataSeshaiah USMember, University ✭✭
    edited September 2015

    Hi @JamesMontemagno‌!!.

    We are facing problem while adding pulltorefresh content view as a child to Stacklayout . It is not working.

    http://motzcod.es/post/103224921992/pullswipe-to-refresh-for-xamarinforms-android

    Please find below code changes from sample.

    var viewModel = new TestViewModel ();

            var listView = new ListView ();
            listView.SetBinding<TestViewModel> (ListView.ItemsSourceProperty, vm => vm.Items);
    
            var refreshView = new PullToRefreshContentView {
                RefreshCommand = viewModel.RefreshCommand,
                Content = listView
            };
    
            refreshView.SetBinding<TestViewModel> (PullToRefreshContentView.IsRefreshingProperty, vm => vm.IsBusy);
    
            var mainLayout = new StackLayout()
            {
    
                BackgroundColor = Color.FromRgb(6,51,110),
                HorizontalOptions = LayoutOptions.FillAndExpand,
                VerticalOptions = LayoutOptions.FillAndExpand,
                Orientation = StackOrientation.Vertical,
                Padding = new Thickness (0, 0, 0, 0),
                Spacing = 0,
                Children = { refreshView },
            };
    
            var _page = new ContentPage { 
                Content = mainLayout,
                Title = "Pull To Refresh"
            };
    

    Any help ?

  • JamesMontemagnoJamesMontemagno USForum Administrator, Xamarin Team, Developer Group Leader Xamurai

    In the latest versions of Xamarin.Forms something most have changed as it used to work. However it still works just fine setting the Content of the page to the refreshView. This is what I originally only supported and continue to only support at this time. I spent some time trying to figure it out this morning, but couldn't sorry.

  • JamesMontemagnoJamesMontemagno USForum Administrator, Xamarin Team, Developer Group Leader Xamurai

    Ah, actually yes this no longer is valid as Xamarin.Forms ListView actually has a pull to refresh built in which is canceling mine out completely. This control should no longer be used.

    The other purpose that I would need to figure out is a way to make it so the PullToRefreshContentView could have other things inside of it that aren't a ListView such as a scrollview or recycler view or anything else.

  • VenkataSeshaiahVenkataSeshaiah USMember, University ✭✭

    Hi James,

    I have implemented same with RecyclerView with your PullToRefreshContentView. It worked fine If I try to add the same to Contentview. If I try to add this to stacklayout and add this stacklayout to Contentview is not working.

    Please find attached modified files from your sample to make Recycler view work. below code snippet for adding that to content page.

    listView = new CustomListView ();
    TestViewModel viewModel = new TestViewModel (listView);
    listView.SetBinding (CustomListView.ItemsProperty, vm => vm.Items);

    refreshView = new PullToRefreshContentView {
    RefreshCommand = viewModel.RefreshCommand,
    Content = listView
    };

    refreshView.SetBinding (PullToRefreshContentView.IsRefreshingProperty, vm => vm.IsBusy);

    // This implementation is working but not able to add fixed Header view for list
    BindingContext = viewModel;
    Content = refreshView;
    //end

    // This implementation is not working . This is our requirement as we are adding fixed header for listview.
    var HeaderView = new StackLayout()
    {
    BackgroundColor = Color.FromRgb(6,51,110),
    HorizontalOptions = LayoutOptions.CenterAndExpand,
    VerticalOptions = LayoutOptions.Start,
    Orientation = StackOrientation.Horizontal,
    Padding = new Thickness (0, 0, 0, 0),
    Children = { featureTab, latestTab },
    };

    var mainLayout = new StackLayout()
    {
    BackgroundColor = Color.FromRgb(6,51,110),
    HorizontalOptions = LayoutOptions.FillAndExpand,
    VerticalOptions = LayoutOptions.FillAndExpand,
    Orientation = StackOrientation.Vertical,
    Padding = new Thickness (0, 0, 0, 0),
    Spacing = 0,
    Children = { HeaderView,refreshView },
    };
    BindingContext = viewModel;
    Content = mainLayout;
    //end

    It will be great help if you suggest any solution.

  • JamesMontemagnoJamesMontemagno USForum Administrator, Xamarin Team, Developer Group Leader Xamurai

    I also have not gotten the StackLayout to work and spent some time trying. Have you tried perhaps to use a Grid instead to see if that works?

  • VenkataSeshaiahVenkataSeshaiah USMember, University ✭✭

    It doesn't worked for Grid as well. It is working only If i try to add as a content view only.We are struck in this place.

  • JamesMontemagnoJamesMontemagno USForum Administrator, Xamarin Team, Developer Group Leader Xamurai

    I got this all working, please give me a day to get it all together.

  • JamesMontemagnoJamesMontemagno USForum Administrator, Xamarin Team, Developer Group Leader Xamurai
  • AlessandroCaliaroAlessandroCaliaro ITMember ✭✭✭✭✭

    @JamesMontemagno I love, love, love you

  • RanaHossainUKRanaHossainUK LVMember
    edited October 2015

    Hi James,

    first of all, thanks for all your effort;I had previously admired your work with mvvmCross, and now equally impressed with your contribution to xam forms. Thanks again.

    Now, about PullToRefresh: I might be doing something wrong, but even with gitHub project (after I have fixed forms version issue), on iOS project, PullToRefresh actually create a duplicate of the whole layout, which then get's scrolled.

    One easy way to see this is to create a layout with a lot of labels so it would scroll; and then after adding pullToRefresh, and dragging the layout, I see another layer behind with all the labels. Running with SpyTouch to see the elements confirms it.

    I have attached a screeenshot from gitHub example; you would notice behind the animated refresh icon, instead of white, we have a duplicate of the layout being dragged; Your screenshot at gitHub shows white (what it should be). I am pretty sure it was also the case with previous stable Forms release (I am using Xamarin.Forms.1.5.1.6471 now)

    Thanks again.

  • JamesMontemagnoJamesMontemagno USForum Administrator, Xamarin Team, Developer Group Leader Xamurai

    @RanaHossain.5791 I think it just needs to be recompiled. I can try to update tomorrow. Or just bring the code directly into your project.

  • JamesMontemagnoJamesMontemagno USForum Administrator, Xamarin Team, Developer Group Leader Xamurai

    I have a fix, give me the night. On a plane :)

  • JamesMontemagnoJamesMontemagno USForum Administrator, Xamarin Team, Developer Group Leader Xamurai

    annnnnddd fixed in 1.0.3 and pushed to GitHub

  • holy Darwin; that's just too awesome.... thanks man; am downloading to test it now :smile:

«1
Sign In or Register to comment.