Browse Source

Various Mobile UI fixes and improvements

Frank van den Bos 1 year ago
parent
commit
ad914e09b6

+ 4 - 2
InABox.Mobile/InABox.Mobile.Shared/Components/MobileButton/MobileButton.xaml

@@ -10,6 +10,8 @@
         <local:StringToBooleanConverter x:Key="StringToBooleanConverter"/>
         <local:ImageSourceToBooleanConverter x:Key="ImageSourceToBooleanConverter"/>
         <local:MobileButtonTextFormatter x:Key="MobileButtonTextFormatter" x:Name="_textformatter"/>
+        <local:MobileButtonSizeConverter x:Key="HeightConverter" Dimension="Height" />
+        <local:MobileButtonSizeConverter x:Key="WidthConverter" Dimension="Width" />
     </ContentView.Resources>
     <ContentView.ControlTemplate>
         <ControlTemplate>
@@ -45,8 +47,8 @@
                                 x:Name="_image" 
                                 Source="{TemplateBinding Image}"
                                 IsVisible="{TemplateBinding Image, Converter={StaticResource ImageSourceToBooleanConverter}}"
-                                WidthRequest="24"
-                                HeightRequest="24"
+                                WidthRequest="{TemplateBinding ImageWidth, Converter={StaticResource WidthConverter}}"
+                                HeightRequest="{TemplateBinding ImageHeight, Converter={StaticResource HeightConverter}}"
                                 Aspect="AspectFit"
                             />
                             

+ 30 - 0
InABox.Mobile/InABox.Mobile.Shared/Components/MobileButton/MobileButton.xaml.cs

@@ -38,6 +38,24 @@ namespace InABox.Mobile
         }
     }
 
+    public enum MobileButtonSizeDimension
+    {
+        Height,
+        Width
+    }
+    
+    public class MobileButtonSizeConverter : UtilityConverter<Size,double>
+    {
+        public MobileButtonSizeDimension Dimension { get; set; }
+
+        protected override double Convert(Size value)
+        {
+            return Dimension == MobileButtonSizeDimension.Height
+                ? value.Height
+                : value.Width;
+        }
+
+    }
 
     [XamlCompilation(XamlCompilationOptions.Compile)]
     public partial class MobileButton
@@ -90,6 +108,18 @@ namespace InABox.Mobile
         {
             get => GetValue(ImageProperty) as ImageSource;
             set => SetValue(ImageProperty, value);
+        }        
+        public static readonly BindableProperty ImageSizeProperty = BindableProperty.Create(
+            nameof(ImageSize), 
+            typeof(Size), 
+            typeof(MobileButton),
+            new Size(24,24)
+        );
+        
+        public Size ImageSize
+        {
+            get => (Size)GetValue(ImageProperty);
+            set => SetValue(ImageProperty, value);
         }
         
         public static readonly BindableProperty TextProperty = BindableProperty.Create(

+ 1 - 1
InABox.Mobile/InABox.Mobile.Shared/Components/MobileCheckBox/MobileCheckBox.xaml

@@ -5,7 +5,7 @@
              xmlns:mobile="clr-namespace:InABox.Mobile;assembly=InABox.Mobile.Shared"
              x:Class="InABox.Mobile.MobileCheckBox">
     <ContentView.Resources>
-        <mobile:CheckBoxImageConverter x:Key="CheckBoxImageConverter" Checked="checked" Unchecked="unchecked"/>
+        <mobile:BooleanToImageConverter x:Key="CheckBoxImageConverter" Checked="checked" Unchecked="unchecked"/>
     </ContentView.Resources>
     <ContentView.ControlTemplate>
         <ControlTemplate >

+ 0 - 21
InABox.Mobile/InABox.Mobile.Shared/Components/MobileCheckBox/MobileCheckBox.xaml.cs

@@ -5,27 +5,6 @@ using Xamarin.Forms.Xaml;
 
 namespace InABox.Mobile
 {
-
-    public class CheckBoxImageConverter : IValueConverter
-    {
-        public ImageSource Checked { get; set; }
-        public ImageSource Unchecked { get; set; }
-        
-        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
-        {
-            if ((value is bool ischecked) && ischecked)
-                return Checked;
-            return Unchecked;
-        }
-
-        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
-        {
-            if (value is FileImageSource file)
-                return String.Equals(file.File, "checked");
-            return false;
-        }
-    }
-    
     [XamlCompilation(XamlCompilationOptions.Compile)]
     public partial class MobileCheckBox
     {

+ 7 - 1
InABox.Mobile/InABox.Mobile.Shared/Components/MobileEditor/MobileEditor.cs

@@ -4,6 +4,12 @@ namespace InABox.Mobile
 {
     public class MobileEditor : Editor
     {
-        
+        public MobileEditor()
+        {
+            TextColor = Color.Black;
+            BackgroundColor = Color.LightYellow;
+            FontSize = Device.GetNamedSize(NamedSize.Small, this);
+            PlaceholderColor = Color.Gray;
+        }
     }
 }

+ 7 - 1
InABox.Mobile/InABox.Mobile.Shared/Components/MobileEntry/MobileEntry.cs

@@ -4,6 +4,12 @@ namespace InABox.Mobile
 {
     public class MobileEntry : Entry
     {
-        
+        public MobileEntry()
+        {
+            TextColor = Color.Black;
+            BackgroundColor = Color.LightYellow;
+            FontSize = Device.GetNamedSize(NamedSize.Small, this);
+            PlaceholderColor = Color.Gray;
+        }
     }
 }

+ 2 - 1
InABox.Mobile/InABox.Mobile.Shared/Components/MobileList/MobileList.xaml.cs

@@ -94,7 +94,8 @@ namespace InABox.Mobile
                 _lastupdate.IsVisible = !LastUpdated.IsEmpty();
                 _lastupdate.Text = $"{DateTimeToAgeConverter.FormatTime(LastUpdated)}";
                 _pulltorefresh.IsVisible = PullToRefresh;
-                _numrecords.Text = $"{(ItemsSource as IList)?.Count ?? 0} records";
+                int count = (ItemsSource as IList)?.Count ?? 0;
+                _numrecords.Text = $"{count} record{(count == 1 ? "" : "s")}";
                 _numrecords.IsVisible = ShowRecordCount && ItemsSource is IList;
                 _refreshcard.IsVisible = _lastupdate.IsVisible || _pulltorefresh.IsVisible || _numrecords.IsVisible;
                 _emptylist.IsVisible = !ShowRecordCount;

+ 14 - 4
InABox.Mobile/InABox.Mobile.Shared/Components/MobileModuleList/MobileModuleList.xaml

@@ -6,9 +6,9 @@
     xmlns:mobile="clr-namespace:InABox.Mobile;assembly=InABox.Mobile.Shared"
     x:Class="InABox.Mobile.MobileModuleList" >
     
-    <ContentView.Resources>
-        <mobile:BooleanToColorConverter x:Key="BooleanToColorConverter" TrueColor="LightSalmon" FalseColor="LightGoldenrodYellow"/>
-    </ContentView.Resources>
+    <!-- <ContentView.Resources> -->
+    <!--     <mobile:BooleanToColorConverter x:Key="BooleanToColorConverter" TrueColor="LightSalmon" FalseColor="LightGoldenrodYellow"/> -->
+    <!-- </ContentView.Resources> -->
     
     <ContentView.Content>
         <mobile:MobileList 
@@ -23,11 +23,12 @@
                         HorizontalOptions="FillAndExpand"
                         BorderColor="{Binding BorderColor}"  
                         Margin="0,0,0,5" 
-                        BackgroundColor="{Binding AlertVisible, Converter={StaticResource BooleanToColorConverter}}"
+                        
                         Padding="5" 
                         HeightRequest="70"
                         Clicked="Module_Clicked"
                         IsEnabled="{Binding IsEnabled}">
+                        <!-- BackgroundColor="{Binding AlertVisible, Converter={StaticResource BooleanToColorConverter}}" -->
                         <mobile:MobileCard.Triggers>
                             <DataTrigger TargetType="mobile:MobileCard" Binding="{Binding IsEnabled}" Value="False">
                                 <Setter Property="BackgroundColor" Value="Silver" />
@@ -35,6 +36,15 @@
                             <DataTrigger TargetType="mobile:MobileCard" Binding="{Binding IsEnabled}" Value="False">
                                 <Setter Property="BorderColor" Value="Gray" />
                             </DataTrigger>
+                            
+                            <DataTrigger TargetType="mobile:MobileCard" Binding="{Binding AlertVisible}" Value="False">
+                                <Setter Property="BackgroundColor" Value="LightGoldenrodYellow" />
+                            </DataTrigger>
+                            
+                            <DataTrigger TargetType="mobile:MobileCard" Binding="{Binding AlertVisible}" Value="True">
+                                <Setter Property="BackgroundColor" Value="LightSalmon" />
+                            </DataTrigger>
+
                         </mobile:MobileCard.Triggers>
 
                         <Grid RowSpacing="0">

+ 76 - 0
InABox.Mobile/InABox.Mobile.Shared/Components/MobileRadioList/MobileRadioList.xaml

@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<ContentView 
+    xmlns="http://xamarin.com/schemas/2014/forms"
+    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+    xmlns:mobile="clr-namespace:InABox.Mobile;assembly=InABox.Mobile.Shared"
+    x:Class="InABox.Mobile.MobileRadioList">
+    
+    <ContentView.Resources>
+        <mobile:BooleanToImageConverter x:Key="CheckedConverter" Checked="checked" Unchecked="unchecked"/>
+    </ContentView.Resources>
+    
+    <ContentView.Content>
+            <mobile:MobileCard 
+            Padding="10" 
+            BorderColor="Gray" 
+            BackgroundColor="LightYellow" 
+            IsClippedToBounds="True">
+                <CollectionView  
+                    x:Name="_list"
+                    BackgroundColor="Transparent" 
+                    ItemSizingStrategy="MeasureAllItems"
+                    SelectionMode="None">
+                    <CollectionView.ItemsLayout>
+                        <LinearItemsLayout 
+                            ItemSpacing="5" 
+                            Orientation="Vertical" />
+                    </CollectionView.ItemsLayout>
+                    <CollectionView.ItemTemplate>
+                        <DataTemplate 
+                            x:DataType="mobile:MobileRadioListItem">
+                            
+                            <Grid
+                                Grid.ColumnSpacing="5">
+                                <Grid.ColumnDefinitions>
+                                    <ColumnDefinition Width="Auto"/>
+                                    <ColumnDefinition Width="*"/>
+                                </Grid.ColumnDefinitions>
+                                
+                                <Image
+                                    Grid.Column="0"
+                                    HeightRequest="20"
+                                    WidthRequest="20">
+                                    <!-- Source="{Binding IsChecked, Converter={StaticResource CheckedConverter}, Mode=TwoWay}"  -->
+                                    <Image.Triggers>
+                                        <DataTrigger TargetType="Image" Binding="{Binding IsChecked}" Value="True">
+                                            <Setter Property="Source" Value="checked" />
+                                        </DataTrigger>
+                                        <DataTrigger TargetType="Image" Binding="{Binding IsChecked}" Value="False">
+                                            <Setter Property="Source" Value="unchecked" />
+                                        </DataTrigger>
+                                        </Image.Triggers>
+                                    <Image.GestureRecognizers>
+                                        <TapGestureRecognizer Tapped="Tapped"/>
+                                    </Image.GestureRecognizers>
+                                </Image>
+                                
+                                <Label
+                                    Grid.Column="1"
+                                    Text="{Binding Text}"
+                                    TextColor="Black"
+                                    FontSize="Small"
+                                    VerticalTextAlignment="Center">
+                                    <Label.GestureRecognizers>
+                                        <TapGestureRecognizer Tapped="Tapped"/>
+                                    </Label.GestureRecognizers>
+                                </Label>
+                            </Grid>
+
+                        </DataTemplate>
+                    </CollectionView.ItemTemplate>
+                </CollectionView>
+            </mobile:MobileCard> 
+        
+    </ContentView.Content>
+</ContentView>

+ 57 - 0
InABox.Mobile/InABox.Mobile.Shared/Components/MobileRadioList/MobileRadioList.xaml.cs

@@ -0,0 +1,57 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using Xamarin.Forms;
+using Xamarin.Forms.Xaml;
+
+namespace InABox.Mobile
+{
+
+    
+    public class MobileRadioListChangedEventArgs : EventArgs
+    {
+    }
+
+    public delegate void MobileRadioListChangedEvent(object sender, MobileRadioListChangedEventArgs args);
+    
+    [XamlCompilation(XamlCompilationOptions.Compile)]
+    public partial class MobileRadioList
+    {
+        
+        public IList<MobileRadioListItem> Items { get; }
+        
+        public MobileRadioListItem SelectedItem
+        {
+            get => Items.FirstOrDefault(x => x.IsChecked);
+            set
+            {
+                foreach (var item in Items)
+                    item.IsChecked = item == value;
+            }
+        }
+
+        public event MobileRadioListChangedEvent Changed;
+        
+        public MobileRadioList()
+        {
+            Items = new ObservableCollection<MobileRadioListItem>();
+            InitializeComponent();
+            _list.ItemsSource = Items;
+        }
+        
+        private void Tapped(object sender, EventArgs e)
+        {
+            if ((sender as BindableObject)?.BindingContext is MobileRadioListItem item)
+            {
+                if (item != SelectedItem)
+                {
+                    SelectedItem = item;
+                    Changed?.Invoke(this, new MobileRadioListChangedEventArgs());
+                    _list.ItemsSource = null;
+                    _list.ItemsSource = Items;
+                }    
+            }
+        }
+    }
+}

+ 11 - 0
InABox.Mobile/InABox.Mobile.Shared/Components/MobileRadioList/MobileRadioListItem.cs

@@ -0,0 +1,11 @@
+using System;
+using Xamarin.Forms;
+
+namespace InABox.Mobile
+{
+    public class MobileRadioListItem : BindableObject
+    {
+        public string Text { get; set; }
+        public bool IsChecked { get; set; }
+    }
+}

+ 23 - 0
InABox.Mobile/InABox.Mobile.Shared/Converters/BooleanToImageConverter.cs

@@ -0,0 +1,23 @@
+using Xamarin.Forms;
+
+namespace InABox.Mobile
+{
+    public class BooleanToImageConverter : UtilityConverter<bool,ImageSource>
+    {
+        public ImageSource Checked { get; set; }
+        public ImageSource Unchecked { get; set; }
+
+        protected override ImageSource Convert(bool value)
+        {
+            return value
+                ? Checked
+                : Unchecked;
+        }
+
+        protected override bool Deconvert(ImageSource value)
+        {
+            return value == Checked;
+        }
+        
+    }
+}