ListView not unselecting

无人久伴 提交于 2019-12-19 10:30:28

问题


I am working on a Xamarin.Forms project with a ListView.

The XAML for the ListView is

<render:CustomListView x:Name="listview" ItemSelected="ItemSelected" ItemTapped="ItemTapped"></render:CustomListView>

And the C# is

public void ItemTapped(object sender, ItemTappedEventArgs e)
    {
        var Selected = e.Item as Classes.NavigationItem;
        //Handle clicked
        }
       ((ListView)sender).SelectedItem = null;

    }

    private void ItemSelected(object sender, SelectedItemChangedEventArgs e)
    {
        ((ListView)sender).SelectedItem = null;
    }

My custom renderers are

Android (Custom ListView):

public class NavigationListViewAndroid : ListViewRenderer
{
    #pragma warning disable CS0618 // Type or member is obsolete
    public NavigationListViewAndroid() { }
    #pragma warning restore CS0618 // Type or member is obsolete

    public NavigationListViewAndroid(Context context) : base(context)
    {

    }

    protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.ListView> e)
    {
        base.OnElementChanged(e);
        Control.SetSelector(Android.Resource.Color.DarkerGray);
    }

}

iOS (ViewCell):

public class NavigationViewCelliOS : ViewCellRenderer
{
    public override UITableViewCell GetCell(Cell item, UITableViewCell reusableCell, UITableView tv)
    {
        var cell = base.GetCell(item, reusableCell, tv);
        cell.SelectionStyle = UITableViewCellSelectionStyle.Gray;

        return cell;
    }
}

My problems are :

Android: It selected the row but stays selected until you click another one (for both), I want it to deselect when you let go

iOS: Never highlights gray at all even if held down


回答1:


To apply background color to list view selected item follow these steps:

Make custom control:

using Xamarin.Forms;

namespace xamformsdemo.CustomControls
{
  public class ExtendedViewCell : ViewCell
  {
    public static readonly BindableProperty SelectedBackgroundColorProperty =
    BindableProperty.Create("SelectedBackgroundColor", 
                            typeof(Color), 
                            typeof(ExtendedViewCell), 
                            Color.Default);

    public Color SelectedBackgroundColor
    {
       get { return (Color)GetValue(SelectedBackgroundColorProperty); }
       set { SetValue(SelectedBackgroundColorProperty, value); }
    }
  }
}

Android Renderer:

[assembly: ExportRenderer(typeof(ExtendedViewCell), typeof(ExtendedViewCellRenderer))]
namespace xamformsdemo.Droid.CustomRenderers
{
  public class ExtendedViewCellRenderer : ViewCellRenderer
  {

private Android.Views.View _cellCore;
private Drawable _unselectedBackground;
private bool _selected;

protected override Android.Views.View GetCellCore(Cell item, 
                                                  Android.Views.View convertView, 
                                                  ViewGroup parent, 
                                                  Context context)
{
  _cellCore = base.GetCellCore(item, convertView, parent, context);

  _selected = false;
  _unselectedBackground = _cellCore.Background;

  return _cellCore;
}

protected override void OnCellPropertyChanged(object sender, PropertyChangedEventArgs args)
{
  base.OnCellPropertyChanged(sender, args);

  if (args.PropertyName == "IsSelected")
  {
    _selected = !_selected;

    if (_selected)
    {
      var extendedViewCell = sender as ExtendedViewCell;
      _cellCore.SetBackgroundColor(extendedViewCell.SelectedBackgroundColor.ToAndroid());
    }
    else
    {
      _cellCore.SetBackground(_unselectedBackground);
    }
  }
}
  }

}

iOS Renderer:

[assembly: ExportRenderer(typeof(ExtendedViewCell), typeof(ExtendedViewCellRenderer))]
namespace xamformsdemo.iOS.CustomRenderers
{
  public class ExtendedViewCellRenderer : ViewCellRenderer
  {
    public override UITableViewCell GetCell(Cell item, UITableViewCell reusableCell, UITableView tv)
   {
      var cell = base.GetCell(item, reusableCell, tv);
      var view = item as ExtendedViewCell;
      cell.SelectedBackgroundView = new UIView
       {
         BackgroundColor = view.SelectedBackgroundColor.ToUIColor(),
       };

      return cell;
    }

  }
}

Use in XAML:

<ListView.ItemTemplate>
  <DataTemplate>
    <customControls:ExtendedViewCell SelectedBackgroundColor="Teal">
      <ViewCell.View>
        <StackLayout HorizontalOptions="FillAndExpand" 
                     VerticalOptions="FillAndExpand" Orientation="Vertical" 
                     Padding="4" Spacing="8">
          <Label TextColor="White" Text="{Binding .ItemName}"/>
          <Label TextColor="Yellow" Text="{Binding .LastUpdated, StringFormat='Last seen: {0:HH:mm:ss}'}"/>
        </StackLayout>
      </ViewCell.View>
    </customControls:ExtendedViewCell>
  </DataTemplate>
</ListView.ItemTemplate>

You can refer this link below to solve problem: https://blog.wislon.io/posts/2017/04/11/xamforms-listview-selected-colour




回答2:


I had same problem, I was using ItemSelected, but the selected item wasn't getting deselected unless until I select any other item in the ListView. I replace ItemSelected by ItemTapped. It worked for me.




回答3:


I prefer to use the SelectedItem property to handle simple clicks. This works platform independent and everything can be done in the view model code.

The trick is to set the property null again to deselect the item immediately after evaluating it (in hte sample I use it for initialising another view model).

XAML:

<ListView ItemsSource="{Binding Items}" 
    SelectedItem="{Binding SelectedProduct, Mode=TwoWay}">

ViewModel.cs:

public Command<IProduct> ViewDetailsCommand;
public ViewModel()
{
     ViewDetailsCommand = new Command<IProduct>(async s => await ViewDetails(s));
}

public IProduct SelectedProduct
{
    get { return _selectedProduct; }
    set
    {
        if (value != _selectedProduct)
        {
            SetProperty(ref _selectedProduct, value);
            if (value != null)
            {
                ViewDetailsCommand.Execute(value);
            }
        }
    }
}

private async Task ViewDetails(IProduct product)
{
    var viewModel = AppContainer.Container.Resolve<ProductDetailsViewModel>();
    viewModel.Initialise(this, product as ShoppingListItemViewModel);
    SelectedProduct = null;
    await _pageNavigator.PushModalAsync(viewModel);
}



回答4:


On Android If you only want to change the color when use clicks the ListView's Item. You can modify the style:

Before Api 21, create a xml file in the drawable folder:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:drawable="@color/colorPrimary" android:state_pressed="false"/>  
  <item android:drawable="@color/colorAccent" android:state_pressed="true"/>  
  <item android:drawable="@color/colorPrimary"/>                              
</selector>

On Api 21+, under the drawable-v21 folder create the file with same name:

<?xml version="1.0" encoding="utf-8"?>
<ripple
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="@color/colorAccent">
  <item android:drawable="@color/colorPrimaryDark"/>
</ripple>

Then change the style in the renderer:

// f_selector is the xml file's name
Control.SetSelector(Resource.Drawable.f_selector);

At last change the color in the resource file colors.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <color name="colorPrimary">#3F51B5</color> <!--original background color api21- -->
  <color name="colorPrimaryDark">#FFFFFF</color> <!--original background color api21+ -->
  <color name="colorAccent">#FF313030</color> 
</resources>


来源:https://stackoverflow.com/questions/49685542/listview-not-unselecting

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!