Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I change the background color in ListView cells without losing haptic (touch) feedback?

(I asked on the Xamarin forums but didn't get a response, so I'm trying here)

In Xamarin Forms, setting BackgroundColor in a ListView ItemTemplate causes haptic-feedback to be disabled.

Is there any way around this? I'd like to customize the colors of my list-items, but not having haptic feedback looks like garbage.

Example XAML:

 <ListView x:Name="list"
           ItemTapped="OnItemSelected"
           IsGroupingEnabled="True"
           GroupDisplayBinding="{Binding Key}"
           GroupShortNameBinding="{Binding Key}"
           HasUnevenRows="True"
           ItemsSource="{Binding .}">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
              <StackLayout VerticalOptions="FillAndExpand"
                           Padding="5, 20"
                           BackgroundColor="#CCCCCC"> <!--This line causes haptic feedback to fail -->
                <Label Text="{Binding Name}"
                       TextColor="Black"
                       VerticalOptions="Center"
                       FontSize="Large"/>
              </StackLayout>
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

The closest I've gotten is changing the BackgroundColor in ViewCell.Tapped, then changing it back in View.OnAppearing() (ViewCell.Appearing is broken), but that changes the background when the finger is lifted, rather than when it's pressed.

I'm testing on Android but would prefer a cross-platform solution.

like image 485
BlueRaja - Danny Pflughoeft Avatar asked Aug 22 '16 15:08

BlueRaja - Danny Pflughoeft


2 Answers

Check your post on the Xamarin forum for my feedback. I have an easy drop-in solution for you called XFGloss. Its a free open source add-on for Xamarin.Forms. The source is available on GitHub. There is also a NuGet package available. It allows you to assign a BackgroundColor value to the standard XF cell controls (TextCell, EntryCell, etc.). There are several other new properties also added by XFGloss.

If you prefer to fix your existing implementation, you can review the changes I made to support the visual feedback in this code commit.

like image 99
Tommy Baggett Avatar answered Nov 16 '22 13:11

Tommy Baggett


Once you set the Background color then you won't get to see the selected item color or Haptic feedback unless you create a custom render on each platform.

Here is the work around you can implement which is cross platform and MVVM based using Bindings for setting the color of selected item:

  1. Bind a property to the SelectedItem of ListView.
  2. Bind the Background color of your StackLayout to an auto property and set the value of "#CCCCCC" if its not selected item else some other color.
  3. You need to subscribe to the SelectedMyItem property in the MyItem class and invoke OnPropertyChanged of BackgroundColor property. For this you can raise an event and subscribe or anything that you feel comfortable.(this is not implemented in the sample pseudo code provided below)

ViewModel :

public class MyViewModel : IMyViewModel
{
    public ObserveableCollection<MyItem> Items { get; set; }
    public MyItem SelectedMyItem { get; set; }
}

List item class :

public class MyItem 
{
    private readonly IMyViewModel _myViewModel;

    public MyItem(IMyViewModel myViewModel)
    {
        _myViewModel = myViewModel;
    }

    public string Name { get; set; }
    public Color BackgroundColor => _myViewModel.SelectedMyItem == this 
                                    ? Color.Red : Color.FromHex("CCCCCC");        
}

XAML :

<ListView x:Name="list"
           IsGroupingEnabled="True"
           GroupDisplayBinding="{Binding Key}"
           GroupShortNameBinding="{Binding Key}"
           HasUnevenRows="True"
           ItemsSource="{Binding Items}"
           SelectedItem="{Binding SelectedMyItem}">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
              <StackLayout VerticalOptions="FillAndExpand"
                           Padding="5, 20"
                           BackgroundColor="{Binding BackgroundColor}">
                   <StackLayout.GestureRecognizers>
                       <TapGestureRecognizer Tapped="OnItemTapped" />
                   </StackLayout.GestureRecognizers>
                <Label Text="{Binding Name}"
                       TextColor="Black"
                       VerticalOptions="Center"
                       FontSize="Large"/>
              </StackLayout>
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

Haptic feedback work around :

Usually a touch is 200-300ms. Once an item is tapped you can change the color of the background for that much duration and then set to the original color.

public async void OnItemTapped(object sender, EventArgs args) 
{
   BackgroundColor = Color.Orange; //touch color
   await Task.Delay(250);          //time to show new color
   BackgroundColor = Color.Red;    //original color
}

You can even improve this further by trying to incorporate animations, maybe the FadeTo for changing colors.

like image 40
Rohit Vipin Mathews Avatar answered Nov 16 '22 12:11

Rohit Vipin Mathews