Renderer - Horizontal ListView in Android with RecyclerView

veryhumbleveryhumble USMember ✭✭
edited May 2017 in Xamarin.Forms

Hi,

I have almost successfully created a Renderer in Android for a Horizontal ListView, because, as you know, is currently hacky with the built in ListView.

I am looking for Help with Layout Rendering of the ViewCells.

You'll find the Renderer Code here : https://gist.github.com/veryhumble/0648d7f367a5a808633361ed2e31260e
I would also be happy to share the CollectionViewRenderer on iOS using the GridCollectionView from iOS. The iOS Implementation works fine.

While the views are mostly correctly displayed (defined in XAML), i have the issue that a GestureRecognizer on a CachedImage does not have the correct Touch Area.

This is the ItemTemplate:

 <controls1:CollectionView.ItemTemplate>
              <DataTemplate>
                <ViewCell>
                  <ContentView>
                    <Grid>
                      <forms2:CachedImage Margin="5, 5, 5, 0"
                                          Aspect="Fill"
                                          BackgroundColor="#E7E9E9"
                                          Source="{Binding Url}" >
                        <forms2:CachedImage.Transformations>
                          <transformations:RoundedTransformation Radius="8" CropWidthRatio="1.43" CropHeightRatio="1" />
                        </forms2:CachedImage.Transformations>
                         <forms2:CachedImage.GestureRecognizers>
                            <TapGestureRecognizer Tapped="TapGestureRecognizer_OnTapped" />
                        </forms2:CachedImage.GestureRecognizers>
                      </forms2:CachedImage>

                      <BoxView Margin="5, 5, 5, 0"
                               Color="#E7E9E9"
                               VerticalOptions="FillAndExpand"
                               HorizontalOptions="FillAndExpand"
                               IsVisible="{Binding IsUploading}" />

                      <controls:GifImage HeightRequest="6"
                                         WidthRequest="24"
                                         Source="loader_green.gif"
                                         HorizontalOptions="Center"
                                         VerticalOptions="Center"
                                         IsVisible="{Binding IsUploading}" />

                      <controls:ButtonEx VerticalOptions="Start"
                         HorizontalOptions="End"
                         HeightRequest="20"
                         WidthRequest="20"
                         forms:Message.Attach="RemovePicture($dataContext)"
                         Image="icon_delete.png" />

                    </Grid>
                  </ContentView>
                </ViewCell>
              </DataTemplate>
            </controls1:CollectionView.ItemTemplate>

See the following Screenshot:

Notice the small Rectangle to the Left Upper side of the Images, this is the only Area which triggers the TapGesture on the Image. Altough the Delete Button also has an Event attachted to it (via Caliburn Micro) It does not Work.

Does anyone have any Idea why the Tap region is so small and why I am not able to click on the Image as well as the delete button?

Thank you very much for any Help.

If anyone is interested in creating a OSS Repo with the HorizontalListView Renderers and distribute to NuGet, feel Free to Contact me for Code or Help.

Cheers

Best Answer

  • veryhumbleveryhumble US ✭✭
    Accepted Answer

    Found the Issue. In the ViewHolder for the Items I changed the way the sizes are calculated. The touch Area is now correct.

    var contentLayout = (FrameLayout)ItemView;
    
    viewCell.BindingContext = dataContext;
    viewCell.Parent = collectionView;
    
                var metrics = Resources.System.DisplayMetrics;
    // Layout and Measure Xamarin Forms View
    var elementSizeRequest = viewCell.View.Measure(double.PositiveInfinity, double.PositiveInfinity, MeasureFlags.IncludeMargins);
    
                var height = (int)((collectionView.ItemHeight + viewCell.View.Margin.Top + viewCell.View.Margin.Bottom) * metrics.Density);
                var width = (int)((collectionView.ItemWidth + viewCell.View.Margin.Left + viewCell.View.Margin.Right) * metrics.Density);
    
    viewCell.View.Layout(new Rectangle(0, 0, collectionView.ItemWidth, collectionView.ItemHeight));
    
    // Layout Android View
    var layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.MatchParent) {
        Height = height,
        Width = width
    };
    
    if (Platform.GetRenderer(viewCell.View) == null) {
        Platform.SetRenderer(viewCell.View, Platform.CreateRenderer(viewCell.View));
    }
    var renderer = Platform.GetRenderer(viewCell.View);
    
    
    var viewGroup = renderer.ViewGroup;
    viewGroup.LayoutParameters = layoutParams;
    viewGroup.Layout(0, 0, width, height);
    
    contentLayout.RemoveAllViews();
    contentLayout.AddView(viewGroup);
    

Answers

  • JulienRosenJulienRosen CAMember ✭✭✭✭
    edited May 2017

    try wrapping your image in a grid, and putting the gesture recognizer on the grid itself

  • veryhumbleveryhumble USMember ✭✭

    That seems to have no effect. It's not recognized at all.

    My guess is that something with the rendering and layouting in the RecyclerViewHolder is not quite right.

    I am currently trying to figure this layouting process out by using https://github.com/twintechs/TwinTechsFormsLib . Maybe I get it working.

  • veryhumbleveryhumble USMember ✭✭
    Accepted Answer

    Found the Issue. In the ViewHolder for the Items I changed the way the sizes are calculated. The touch Area is now correct.

    var contentLayout = (FrameLayout)ItemView;
    
    viewCell.BindingContext = dataContext;
    viewCell.Parent = collectionView;
    
                var metrics = Resources.System.DisplayMetrics;
    // Layout and Measure Xamarin Forms View
    var elementSizeRequest = viewCell.View.Measure(double.PositiveInfinity, double.PositiveInfinity, MeasureFlags.IncludeMargins);
    
                var height = (int)((collectionView.ItemHeight + viewCell.View.Margin.Top + viewCell.View.Margin.Bottom) * metrics.Density);
                var width = (int)((collectionView.ItemWidth + viewCell.View.Margin.Left + viewCell.View.Margin.Right) * metrics.Density);
    
    viewCell.View.Layout(new Rectangle(0, 0, collectionView.ItemWidth, collectionView.ItemHeight));
    
    // Layout Android View
    var layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.MatchParent) {
        Height = height,
        Width = width
    };
    
    if (Platform.GetRenderer(viewCell.View) == null) {
        Platform.SetRenderer(viewCell.View, Platform.CreateRenderer(viewCell.View));
    }
    var renderer = Platform.GetRenderer(viewCell.View);
    
    
    var viewGroup = renderer.ViewGroup;
    viewGroup.LayoutParameters = layoutParams;
    viewGroup.Layout(0, 0, width, height);
    
    contentLayout.RemoveAllViews();
    contentLayout.AddView(viewGroup);
    
  • nagarjunareddy.kattasnagarjunareddy.kattas USMember ✭✭

    @veryhumble Can you please share the collection view code and iOS renderer of collectionview.

Sign In or Register to comment.