我有这个XAML代码:
<TableView x:Name="tableView" Intent="Settings" HasUnevenRows="True">
<TableSection>
<TableSection.Title>
Card Selection
</TableSection.Title>
<ViewCell Height="50">
<Grid>
<Grid x:Name="deselectGridLink" VerticalOptions="CenterAndExpand" Padding="20, 0">
<Label TextColor="Blue" Style="{DynamicResource ListItemTextStyle}" x:Name="deselectLink" HorizontalOptions="StartAndExpand" VerticalOptions="Center" Text="Deselect All" />
</Grid>
<Grid x:Name="deselectGridLabel" VerticalOptions="CenterAndExpand" Padding="20, 0">
<Label TextColor="Silver" Style="{DynamicResource ListItemTextStyle}" x:Name="deselectLabel" HorizontalOptions="StartAndExpand" VerticalOptions="Center" Text="Deselect All" />
</Grid>
</Grid>
</ViewCell>
<ViewCell Height="50">
<Grid x:Name="selectGridLink" VerticalOptions="CenterAndExpand" Padding="20, 0">
<Label TextColor="Blue" Style="{DynamicResource ListItemTextStyle}" x:Name="selectLink" HorizontalOptions="StartAndExpand" VerticalOptions="Center" Text="Select All" />
</Grid>
</ViewCell>
</TableSection>
</TableView>
当我的代码的其他部分调用:SetPageDetails()
时,网格中的标签将更改为链接或链接更改为标签。所以对于这个,当它是一个标签时,我希望没有背景flash事件,也没有任何动作。
我附上了这样的轻拍手势识别器。注意它全部在一行但是包含两行,因此在SO问题中更加明显:
deselectGridLink.GestureRecognizers
.Add(NewTapGestureForUpdateCategories(false));
private TapGestureRecognizer NewTapGestureForUpdateCategories(bool val)
{
return new TapGestureRecognizer()
{
Command = new Command(() =>
{
App.DB.UpdateAllCategoryGroups(val);
App.DB.UpdateAllCategories(val);
GetPageData();
RemoveTableViewClickSection();
tableView.Root.Add(CreateTableSection());
})
};
}
当用户在deselectGridLink网格可见时单击该行,然后:
deselectGridLabel可见性设置为true
private void SetPageDetails()
{
Title = App.cardCountForSelectedCategories + (App.cardCountForSelectedCategories == 1 ? " Card Selected" : " Cards Selected");
if (App.cardCountForSelectedCategories == 0)
{
deselectGridLink.IsVisible = false;
deselectGridLabel.IsVisible = true;
}
else
{
deselectGridLink.IsVisible = true;
deselectGridLabel.IsVisible = false;
}
}
这样做的结果是网格链接文本将变为银色,链接将成为标签。
然而,即使单击标签时它是灰色标签,单击标签时仍然会有短暂的背景行颜色从白色变为深色。我认为它只是视图单元的工作方式。
有没有办法抑制这种情况发生?
答案 0 :(得分:12)
编辑1 - 根据问题更新更新了答案。即添加支持在高亮启用/禁用模式之间切换。
编辑2 - 重组答案并添加更多详情。
IsEnabled
最简单的选择是使用IsEnabled属性,该属性反过来启用/禁用后台闪存行为。这种方法的唯一缺点是它还将禁用子控件上的点击,即如果父视图单元IsEnabled
为false
,则不会触发点击事件/手势识别器。 }。
例如:
XAML
<!-- Add name attribute to view-cell -->
<ViewCell x:Name="deselectCell" ..>
<Grid>
<Grid x:Name="deselectGridLink" ..
....
</ViewCell>
代码隐藏
private void SetPageDetails()
{
if (App.cardCountForSelectedCategories == 0)
{
deselectCell.IsEnabled = false; //disable background flash
...
}
else
{
deselectCell.IsEnabled = true;
...
}
}
建议1 - 使用数据绑定和触发器
您可以使用触发器和数据绑定,而不是控制代码隐藏中每个标签的可见性(视图模型将具有IsDeselectEnabled
属性):
<ViewCell IsEnabled="{Binding IsDeselectEnabled}" Height="50">
<Label Margin="20,0,20,0" Style="{DynamicResource ListItemTextStyle}" HorizontalOptions="StartAndExpand" VerticalOptions="Center" Text="Deselect All">
<Label.Triggers>
<DataTrigger TargetType="Label" Binding="{Binding IsDeselectEnabled}" Value="true">
<Setter Property="TextColor" Value="Blue" />
</DataTrigger>
<DataTrigger TargetType="Label" Binding="{Binding IsDeselectEnabled}" Value="false">
<Setter Property="TextColor" Value="Silver" />
</DataTrigger>
</Label.Triggers>
</Label>
</ViewCell>
建议2 - 使用视图作为源的触发器
<ViewCell x:Name="deselectCell" Height="50">
<Label Margin="20,0,20,0" Style="{DynamicResource ListItemTextStyle}" HorizontalOptions="StartAndExpand" VerticalOptions="Center" Text="Deselect All">
<Label.Triggers>
<DataTrigger TargetType="Label" Binding="{Binding IsEnabled, Source={x:Reference deselectCell}}" Value="true">
<Setter Property="TextColor" Value="Blue" />
</DataTrigger>
<DataTrigger TargetType="Label" Binding="{Binding IsEnabled, Source={x:Reference deselectCell}}" Value="false">
<Setter Property="TextColor" Value="Silver" />
</DataTrigger>
</Label.Triggers>
</Label>
</ViewCell>
要在切换ViewCell
背景突出显示行为时允许点击,我们需要实现平台渲染器。
对于iOS,我们可以使用SelectionStyle切换此行为,而在Android的情况下,我们可以使用Clickable属性。
共享控制:
public class CustomViewCell : ViewCell
{
public static readonly BindableProperty AllowHighlightProperty =
BindableProperty.Create(
"AllowHighlight", typeof(bool), typeof(CustomViewCell),
defaultValue: true);
public bool AllowHighlight
{
get { return (bool)GetValue(AllowHighlightProperty); }
set { SetValue(AllowHighlightProperty, value); }
}
}
iOS渲染器:
[assembly: ExportRenderer(typeof(CustomViewCell), typeof(CustomViewCellRenderer))]
namespace SampleApp.iOS
{
public class CustomViewCellRenderer : ViewCellRenderer
{
UITableViewCell _nativeCell;
//get access to the associated forms-element and subscribe to property-changed
public override UITableViewCell GetCell(Cell item, UITableViewCell reusableCell, UITableView tv)
{
_nativeCell = base.GetCell(item, reusableCell, tv);
var formsCell = item as CustomViewCell;
if (formsCell != null)
{
formsCell.PropertyChanged -= OnPropertyChanged;
formsCell.PropertyChanged += OnPropertyChanged;
}
//and, update the style
SetStyle(formsCell);
return _nativeCell;
}
void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
var formsCell = sender as CustomViewCell;
if (formsCell == null)
return;
//TODO: Trying to find a nicer and more robust way to dispose and unsubscribe :(
if (_nativeCell == null)
formsCell.PropertyChanged -= OnPropertyChanged;
if (e.PropertyName == CustomViewCell.AllowHighlightProperty.PropertyName)
{
SetStyle(formsCell);
}
}
private void SetStyle(CustomViewCell formsCell)
{
//added this code as sometimes on tap, the separator disappears, if style is updated before tap animation finishes
//https://stackoverflow.com/questions/25613117/how-do-you-prevent-uitableviewcellselectionstylenone-from-removing-cell-separato
Device.StartTimer(TimeSpan.FromMilliseconds(50), () => {
Device.BeginInvokeOnMainThread(() =>
{
if (formsCell.AllowHighlight)
_nativeCell.SelectionStyle = UITableViewCellSelectionStyle.Default;
else
_nativeCell.SelectionStyle = UITableViewCellSelectionStyle.None;
});
return false;
});
}
}
}
Android渲染器:
[assembly: ExportRenderer(typeof(CustomViewCell), typeof(CustomViewCellRenderer))]
namespace SampleApp.Droid
{
public class CustomViewCellRenderer : ViewCellRenderer
{
Android.Views.View _nativeCell;
protected override Android.Views.View GetCellCore(Cell item, Android.Views.View convertView, Android.Views.ViewGroup parent, Android.Content.Context context)
{
_nativeCell = base.GetCellCore(item, convertView, parent, context);
SetStyle();
return _nativeCell;
}
// this one is simpler as the base class has a nice override-able method for our purpose - so we don't need to subscribe
protected override void OnCellPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
base.OnCellPropertyChanged(sender, e);
if(e.PropertyName == CustomViewCell.AllowHighlightProperty.PropertyName)
{
SetStyle();
}
}
private void SetStyle()
{
var formsCell = Cell as CustomViewCell;
if (formsCell == null)
return;
_nativeCell.Clickable = !formsCell.AllowHighlight;
}
}
}
样本用法1 - 通过数据绑定
<local:CustomViewCell AllowHighlight="{Binding IsHighlightEnabled}" ..>
<Grid>
<Grid x:Name="deselectGridLink" ..
...
</local:CustomViewCell>
示例用法2 - 通过代码隐藏
XAML
<!-- Add name attribute to view-cell -->
<local:CustomViewCell x:Name="deselectCell" ..>
<Grid>
<Grid x:Name="deselectGridLink" ..
...
</local:CustomViewCell>
代码隐藏
private void SetPageDetails()
{
if (App.cardCountForSelectedCategories == 0)
{
deselectCell.AllowHighlight= false; //disable background flash
...
}
else
{
deselectCell.AllowHighlight= true;
...
}
}
这尤其适用于ListView
。 现在更新的问题指定单元格是TableView
的一部分,因此此选项在当前问题上下文中不再有效。
您需要实现平台渲染器以禁用突出显示颜色,并将ItemTapped
处理程序添加到ListView
以通过将SelectedItem
始终设置为空来禁用选择。使用的参考文献:
要开始使用,请创建自定义视图单元格:
public class NoSelectViewCell : ViewCell { }
将iOS渲染器实现为:
[assembly: ExportRenderer(typeof(NoSelectViewCell), typeof(NoSelectViewCellRenderer))]
namespace SampleApp.iOS
{
public class NoSelectViewCellRenderer : ViewCellRenderer
{
public override UITableViewCell GetCell(Cell item, UITableViewCell reusableCell, UITableView tv)
{
var nativeCell = base.GetCell(item, reusableCell, tv);
nativeCell.SelectionStyle = UITableViewCellSelectionStyle.None;
return nativeCell;
}
}
}
将android渲染器实现为:
[assembly: ExportRenderer(typeof(NoSelectViewCell), typeof(NoSelectViewCellRenderer))]
namespace SampleApp.Droid
{
public class NoSelectViewCellRenderer : ViewCellRenderer
{
protected override Android.Views.View GetCellCore(Cell item, Android.Views.View convertView, Android.Views.ViewGroup parent, Android.Content.Context context)
{
var cell = base.GetCellCore(item, convertView, parent, context);
cell.Focusable = false;
cell.FocusableInTouchMode = false;
var listView = parent as Android.Widget.ListView;
if (listView != null)
{
listView.SetSelector(Android.Resource.Color.Transparent);
listView.CacheColorHint = Xamarin.Forms.Color.Transparent.ToAndroid();
}
return cell;
}
}
}
<强> XAML 强>
<ListView ItemTapped="Handle_ItemTapped">
<ListView.ItemTemplate>
<DataTemplate>
<local:NoSelectViewCell Height="50">
<Grid>
<Grid x:Name="deselectGridLink" VerticalOptions="CenterAndExpand" Padding="20, 0">
<Label TextColor="Blue" Style="{DynamicResource ListItemTextStyle}" x:Name="deselectLink" HorizontalOptions="StartAndExpand" VerticalOptions="Center" Text="Deselect All" />
</Grid>
<Grid x:Name="deselectGridLabel" VerticalOptions="CenterAndExpand" Padding="20, 0">
<Label TextColor="Silver" Style="{DynamicResource ListItemTextStyle}" x:Name="deselectLabel" HorizontalOptions="StartAndExpand" VerticalOptions="Center" Text="Deselect All" />
</Grid>
</Grid>
</local:NoSelectViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<强>代码隐藏强>
void Handle_ItemTapped(object sender, Xamarin.Forms.ItemTappedEventArgs e)
{
// don't do anything if we just de-selected the row
if (e.Item == null) return;
// do something with e.SelectedItem
((ListView)sender).SelectedItem = null; // de-select the row
}
答案 1 :(得分:0)
G.Sharada提出的建议非常适用于iOS,但在Android上,点击时我仍然眨眼。 将此行添加到样式文件中可以解决此问题。
<item name="android:colorActivatedHighlight">@android:color/transparent</item>