Here's what I have implemented so far for iOS:
using System; using Xamarin.Forms; namespace Japanese { public class ExtCheckedTextCell: TextCell { public static readonly BindableProperty IsCheckedProperty = BindableProperty.Create( "IsChecked", typeof(bool), typeof(ExtCheckedTextCell), defaultValue: false); public bool IsChecked { get { return (bool)GetValue(IsCheckedProperty); } set { SetValue(IsCheckedProperty, value); } } } } and my renderer looks like this:
using System; using System.ComponentModel; using System.Diagnostics; using Japanese; using Japanese.iOS; using UIKit; using Xamarin.Forms; using Xamarin.Forms.Platform.iOS; [assembly: ExportRenderer(typeof(ExtCheckedTextCell), typeof(ExtCheckedTextCellRenderer))] namespace Japanese.iOS { public class ExtCheckedTextCellRenderer : TextCellRenderer { public override UITableViewCell GetCell(Cell item, UITableViewCell reusableCell, UITableView tv) { var nativeCell = base.GetCell(item, reusableCell, tv); if (item is ExtCheckedTextCell formsCell) { SetCheckmark(nativeCell, formsCell); SetTap(nativeCell, formsCell); } return nativeCell; } protected override void HandlePropertyChanged(object sender, PropertyChangedEventArgs args) { base.HandlePropertyChanged(sender, args); System.Diagnostics.Debug.WriteLine($"HandlePropertyChanged {args.PropertyName}"); var nativeCell = sender as CellTableViewCell; if (nativeCell?.Element is ExtCheckedTextCell formsCell) { if (args.PropertyName == ExtCheckedTextCell.IsCheckedProperty.PropertyName) SetCheckmark(nativeCell, formsCell); } } void SetCheckmark(UITableViewCell nativeCell, ExtCheckedTextCell formsCell) { if (formsCell.IsChecked) nativeCell.Accessory = UITableViewCellAccessory.Checkmark; else nativeCell.Accessory = UITableViewCellAccessory.None; } } For reference here's the XAML where it is used:
<TableSection> <local:CheckedTextCell Text="{Binding [6].Name}" IsChecked="{Binding [6].IsSelected}" Tapped="atiSelectValue" /> <local:CheckedTextCell Text="{Binding [7].Name}" IsChecked="{Binding [7].IsSelected}" Tapped="atiSelectValue" /> <local:CheckedTextCell Text="{Binding [8].Name}" IsChecked="{Binding [8].IsSelected}" Tapped="atiSelectValue" /> </TableSection> Does anyone have any ideas how can I implement this in Android using a custom renderer or if it is even possible to do it?
Here's an example (not mine) of what it looks like in iOS. What I am hoping for is the Android can show a similar tick mark on the right side.
2 Answers
Answers 1
Custom Renderer
You can build a custom renderer in Android (although, I think an easier approach is to create a custom ViewCell):
using System.ComponentModel; using Android.Content; using Android.Views; using Android.Widget; using Sof; using Sof.Droid; using Xamarin.Forms; using Xamarin.Forms.Platform.Android; using AView = Android.Views.View; [assembly: ExportRenderer(typeof(ExtCheckedTextCell), typeof(ExtCheckedTextCellRenderer))] namespace Sof.Droid { public class ExtCheckedTextCellRenderer : TextCellRenderer { public const string CheckedText = "✓"; private TextView Check { get; set; } protected override AView GetCellCore(Cell item, AView convertView, ViewGroup parent, Context context) { var view = base.GetCellCore(item, convertView, parent, context) as BaseCellView; if (this.Check == null) { this.Check = new TextView(context); this.Check.Gravity = GravityFlags.Center; using (var lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.MatchParent)) { view.AddView(this.Check, lp); } var paddingRight = context.Resources.GetDimension(Resource.Dimension.abc_list_item_padding_horizontal_material); view.SetPadding(view.PaddingLeft, view.PaddingTop, (int)paddingRight, view.PaddingBottom); } return view; } protected override void OnCellPropertyChanged(object sender, PropertyChangedEventArgs args) { base.OnCellPropertyChanged(sender, args); if (args.PropertyName.Equals(ExtCheckedTextCell.IsCheckedProperty.PropertyName) && sender is ExtCheckedTextCell extCheckedTextCell && this.Check != null) { this.Check.Text = extCheckedTextCell.IsChecked ? CheckedText : string.Empty; } } } } Custom Xamarin.Forms.ViewCell (no platform-specific code needed)
For a simple layout like you want (label and checkmark), a custom ViewCell seems more appropriate and allows direct control over the style.
ExtCheckedTextCell2.xaml
<?xml version="1.0" encoding="UTF-8"?> <ViewCell xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Sof.ExtCheckedTextCell2" x:Name="this"> <ViewCell.View> <StackLayout Orientation="Horizontal" Padding="12, 0"> <Label HorizontalOptions="FillAndExpand" Text="{Binding Text, Source={x:Reference this}}" VerticalTextAlignment="Center" /> <Label IsVisible="{Binding IsChecked, Source={x:Reference this}}" HorizontalOptions="End" Text="✓" VerticalTextAlignment="Center"/> </StackLayout> </ViewCell.View> </ViewCell> ExtCheckedTextCell2.xaml.cs
public partial class ExtCheckedTextCell2 : ViewCell { public static readonly BindableProperty IsCheckedProperty = BindableProperty.Create( nameof(IsChecked), typeof(bool), typeof(ExtCheckedTextCell2), default(bool)); public static readonly BindableProperty TextProperty = BindableProperty.Create( nameof(Text), typeof(string), typeof(ExtCheckedTextCell2), default(string)); public ExtCheckedTextCell2() { InitializeComponent(); } public bool IsChecked { get { return (bool)GetValue(IsCheckedProperty); } set { SetValue(IsCheckedProperty, value); } } public string Text { get { return (string)GetValue(TextProperty); } set { SetValue(TextProperty, value); } } protected override void OnTapped() { base.OnTapped(); this.IsChecked = !this.IsChecked; } } Result
<TableView> <TableSection Title="Custom Renderer"> <local:ExtCheckedTextCell Text="Test1" Tapped="Handle_Tapped" /> <local:ExtCheckedTextCell Text="Test2" Tapped="Handle_Tapped" /> <local:ExtCheckedTextCell Text="Test3" Tapped="Handle_Tapped" /> </TableSection> <TableSection Title="Custom Xamarin.Forms ViewCell"> <local:ExtCheckedTextCell2 Text="Test1" /> <local:ExtCheckedTextCell2 Text="Test2" /> <local:ExtCheckedTextCell2 Text="Test3" /> </TableSection> </TableView> Answers 2
But you can also do it in xaml ?
This is a xaml only solution :) should work for Android and Ios .
.xaml
<?xml version="1.0" encoding="utf-8"?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="StackoverflowQ.Views.MainPage" Title="Driving & Navigation"> <ContentPage.Resources> </ContentPage.Resources> <ScrollView> <StackLayout> <StackLayout x:Name="Header" BackgroundColor="#efeff4" HorizontalOptions="FillAndExpand" HeightRequest="30" Padding="10"> <Label Text="NAVIGATION VOICE VOLUME" Margin="0, 0, 0, 5" VerticalOptions="EndAndExpand" /> </StackLayout> <StackLayout Orientation="Horizontal" Padding="10"> <Label Text="No Voice" TextColor="Black" /> <Image Source="checkboxchecker.png" IsVisible="{Binding IsCheckBoxVisible}" HorizontalOptions="EndAndExpand" /> <StackLayout.GestureRecognizers> <TapGestureRecognizer Command="{Binding TapCheckBoxCommand}" NumberOfTapsRequired="1" /> </StackLayout.GestureRecognizers> </StackLayout> <BoxView HeightRequest="1" HorizontalOptions="FillAndExpand" BackgroundColor="#efeff4" /> </StackLayout> </ScrollView> </ContentPage> ViewModel
namespace StackoverflowQ.ViewModels { public class MainPageViewModel : ViewModelBase { public DelegateCommand TapCheckBoxCommand { get; set; } private bool _isCheckBoxVisible; public bool IsCheckBoxVisible { get => _isCheckBoxVisible; set => SetProperty(ref _isCheckBoxVisible, value); } public MainPageViewModel(INavigationService navigationService) : base(navigationService) { Title = "Main Page"; TapCheckBoxCommand = new DelegateCommand(TapCheckBoxSelected); } public void TapCheckBoxSelected() { IsCheckBoxVisible = !IsCheckBoxVisible; } } } 


0 comments:
Post a Comment