Search Bar style changes in Xamarin Forms - xamarin.ios

I need to use Search Bar in my application for both Xamarin Android and Xamarin iOS.
I have to achieve below search bar in my application.
Please find code used in xaml,
<Frame Padding="0" OutlineColor="DarkGray" HasShadow="True" HorizontalOptions="FillAndExpand" VerticalOptions="Center">
<SearchBar x:Name="searchBar" Placeholder="Search" PlaceholderColor="LightGray" TextColor="#000000" HorizontalOptions="FillAndExpand" VerticalOptions="Center" TextChanged="SearchBar_TextChanged"/>
</Frame>
My search bar look like below, Need to remove the highlighted line from xamarin android.
Also find search bar renderer code,
protected override void OnElementChanged(ElementChangedEventArgs<SearchBar> e)
{
base.OnElementChanged(e);
var color = global::Xamarin.Forms.Color.LightGray;
var searchView = (Control as SearchView);
var searchIconId = searchView.Resources.GetIdentifier("android:id/search_mag_icon", null, null);
if (searchIconId > 0)
{
var searchPlateIcon = searchView.FindViewById(searchIconId);
(searchPlateIcon as ImageView).SetColorFilter(color.ToAndroid(), PorterDuff.Mode.SrcIn);
}
var symbolView = (Control as SearchView);
var symbolIconId = symbolView.Resources.GetIdentifier("android:id/search_close_btn", null, null);
if(symbolIconId>0)
{
var symbolPlateIcon = symbolView.FindViewById(symbolIconId);
(symbolPlateIcon as ImageView).SetColorFilter(color.ToAndroid(), PorterDuff.Mode.SrcIn);
}
}
Xamarin Android:
I have used frame control to show border in Search Bar. I have to remove search bar border bottom line or border color in it.
Xamarin iOS:
I have to acheive search bar control as seems in picture. I have to remove cancel word shown in search bar while searching in it. Also need to remove radius around in it.
Anyone suggest on this?

In Android, you could find the search_plate via id and set it to Transparent, like this:
if (Control != null)
{
var color = global::Xamarin.Forms.Color.LightGray;
var searchView = Control as SearchView;
int searchPlateId = searchView.Context.Resources.GetIdentifier("android:id/search_plate", null, null);
Android.Views.View searchPlateView = searchView.FindViewById(searchPlateId);
searchPlateView.SetBackgroundColor(Android.Graphics.Color.Transparent);
}
In iOS, you could find the Textfield of UISearchBar, then customize the border style of it. And remove the "Cancel" button via setting ShowsCancelButton to false. For example, like this:
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (Control != null)
{
Control.ShowsCancelButton = false;
UITextField txSearchField = (UITextField)Control.ValueForKey(new Foundation.NSString("searchField"));
txSearchField.BackgroundColor = UIColor.White;
txSearchField.BorderStyle = UITextBorderStyle.None;
txSearchField.Layer.BorderWidth = 1.0f;
txSearchField.Layer.CornerRadius = 2.0f;
txSearchField.Layer.BorderColor = UIColor.LightGray.CGColor;
}
}

Related

iOS 13 Changes to UISearchBar tint's, can't achieve the same outcome

I've been experimenting all day and trying to figure out just how to get my UISearchBar to appear the same in iOS13 as it appears in iOS12/11
So the way the search bar is added is simply a new UISearchController.
var searchController = new UISearchController(searchResultsController: null);
searchController.SearchBar.Placeholder = "Search";
searchController.SearchResultsUpdater = this;
searchController.HidesNavigationBarDuringPresentation = false;
searchController.DimsBackgroundDuringPresentation = false;
NavigationItem.SearchController = searchController;
NavigationItem.HidesSearchBarWhenScrolling = false;
The results on iOS 11/12:
The results on iOS 13:
On iOS 13 I am using the new UINavigationBarAppearance code like this:
var appearance = new UINavigationBarAppearance();
appearance.ConfigureWithOpaqueBackground();
appearance.BackgroundColor = ColorPalette.TintColor;
appearance.TitleTextAttributes = new UIStringAttributes { ForegroundColor = UIColor.White };
NavigationItem.StandardAppearance = appearance;
On iOS 11/12 I am using legacy way to achieve it:
NavigationController.NavigationBar.BarStyle = UIBarStyle.Black;
NavigationController.NavigationBar.TintColor = UIColor.White;
NavigationController.NavigationBar.BarTintColor = ColorPalette.TintColor;
NavigationController.NavigationBar.Translucent = false;
I've tried a number of things, but can't seem to get the UISearchBar to tint by itself how iOS11/12 achieves it.
I know that the new UISearchBar now has access to the UITextField and I can configure the background color's etc.
searchBar.setSearchFieldBackgroundImage(UIImage(), for: .normal)
The code above has a side effect which removes corner radius of the text field.
Extension
extension UISearchBar {
  /// This solves iOS 13 issue which is a light gray overay covers the textField.
  /// - Parameter color: A color for searchField
  func setSearchFieldBackgroundColor(_ color: UIColor) {
    searchTextField.backgroundColor = color
    setSearchFieldBackgroundImage(UIImage(), for: .normal)
    // Make up the default cornerRadius changed by `setSearchFieldBackgroundImage(_:for:)`
    searchTextField.layer.cornerRadius = 10
    searchTextField.clipsToBounds = true
  }
}
There were several properties added in iOS 13, so you need to use them with the help of a conditional. For changing the background color, you have to use the BackgroundColor property of the SearchBar, like this
searchController.SearchBar.BackgroundColor = UIColor.Red;
Use a custom renderer and override the OnElementChanged method this way
protected override void OnElementChanged(ElementChangedEventArgs<SearchBar> e)
{
base.OnElementChanged(e);
if (Control != null)
{
if(UIDevice.CurrentDevice.CheckSystemVersion(13,0))
Control.SearchTextField.BackgroundColor = Element.BackgroundColor.ToUIColor();
}
}
later on, you don't have to do anything else and worked for me on ios 12 and ios 13+
On iOS 13, you have access to the internal UISearchTextField through the SearchTextField property, you can set it's background directly (in my case, I need the background to be white). Be sure to check the iOS version to avoid exceptions.
if(UIDevice.CurrentDevice.CheckSystemVersion(13,0))
{
searchController.SearchBar.SearchTextField.BackgroundColor = UIColor.White;
}
You can achieve desired result by adding couple of lines.
searchBar.barTintColor = UIColor.red
searchBar.searchTextField.backgroundColor = UIColor.white
Before you try this code please link IB Outlets for searchBar
#IBOutlet weak var searchBar: UISearchBar!

Using iOS system icons in a NavigationPage with a TabbedPage

I'm using a custom renderer to use iOS system icons in the navigation bar. It works fine, except that if the page is a TabbedPage, only the navigation icons for the default tab's page get their system icons. On other tabs, the system icons don't appear.
My current approach is to override PushViewController. The problem seems to be that when it's called, only the button items for that first tab are available. How can the custom renderer detect when the buttons on the navigation bar are changing? Or is there a better approach?
Current implementation:
/// <summary>
/// Sets system icons on the navigation bar that match the item text.
/// </summary>
class SystemIconNavigationRenderer : NavigationRenderer
{
public override void PushViewController(UIViewController viewController, bool animated)
{
base.PushViewController(viewController, animated);
// If any buttons are customized, replaces the list. Editing individual items doesn't work because UIBarButtonItem.Image is null for a new UIBarButtonItem created from a system item.
var items = viewController.NavigationItem.RightBarButtonItems;
bool changed = false;
var newItems = new UIBarButtonItem[items.Length];
for (int i = 0; i < items.Length; ++i) {
var item = items[i];
UIBarButtonSystemItem systemItem = (UIBarButtonSystemItem)(-1);
switch (item.Title) {
case nameof(UIBarButtonSystemItem.Add): systemItem = UIBarButtonSystemItem.Add; break;
// More icons...
}
if (systemItem >= 0) {
newItems[i] = new UIBarButtonItem(systemItem) { Action = item.Action, Target = item.Target };
changed = true;
} else
newItems[i] = item;
}
if (changed) viewController.NavigationItem.RightBarButtonItems = newItems;
}
}

Xamarin.Forms Action Bar - Center Aligned Image

Using Xamarin.Forms, how do I get the same effect as the application pictured below, specifically to show a centred image on the Action Bar / page tool bar (the section in a blue box)?
I would like to have a long width image in that section, and the solution must work for Android, iOS, Windows Phone, and Universal Windows (even if it means writing custom renderers or platform specific xamarin code).
I suggest you create your own Xamarin.Forms view and handle the navigation by yourself something similar to this:
public class CustomBackNavigationBar : StackLayout
{
public Image BackIcon;
public Image Icon;
public Label IconTitle;
public StackLayout IconContainer;
public CustomBackNavigationBar(string title, string icon)
{
Padding = new Thickness(15,5);
HeightRequest = 40;
Orientation = StackOrientation.Horizontal;
VerticalOptions = LayoutOptions.Start;
BackgroundColor = StaticData.BlueColor;
Spacing = 15;
BackIcon = new Image
{
Source = StaticData.BackIcon,
HorizontalOptions = LayoutOptions.Start
};
Label Title = new Label
{
Text = title,
TextColor = Color.White,
FontSize = Device.GetNamedSize(NamedSize.Default, typeof(Label)),
FontAttributes = FontAttributes.Bold,
VerticalTextAlignment = TextAlignment.Center
};
Icon = new Image
{
Source = icon
};
IconTitle = new Label
{
Text = StaticData.CallAgent,
TextColor = Color.White,
FontSize = Device.GetNamedSize(NamedSize.Micro, typeof(Label)),
};
IconContainer = new StackLayout
{
HorizontalOptions = LayoutOptions.EndAndExpand,
Spacing = 2,
Children = { Icon, IconTitle }
};
Children.Add(BackIcon);
Children.Add(Title);
Children.Add(IconContainer);
#region Events
BackIcon.GestureRecognizers.Clear();
BackIcon.GestureRecognizers.Add(new TapGestureRecognizer
{
Command = new Command(PopAsync)
});
#endregion
}
async void PopAsync()
{
await App.AppNavigation.PopAsync();
}
}

ListView with Groove like quick return header

When scrolling down, Groove moves the header up, outside of the viewable area just like a regular ListView header. When scrolling back up it moves the header back down into the viewable area right away, regardless of the current vertical scroll offset. The header seems to be part of the ListView content because the scrollbar includes the header.
How can this be implemented in a Windows 10 UWP app?
You can do this by utilizing the ListView's internal ScrollViewer's ViewChanged event.
First you got to obtain the internal ScrollViewer. This is the simplest version, but you might want to use one of the many VisualTreeHelper Extensions around to do it safer and easier:
private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
var border = VisualTreeHelper.GetChild(MyListView, 0);
var scrollviewer = VisualTreeHelper.GetChild(border, 0) as ScrollViewer;
scrollviewer.ViewChanged += Scrollviewer_ViewChanged;
}
In the EventHandler, you can then change the visibility of your header depending on the scroll direction.
private void Scrollviewer_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
{
var sv = sender as ScrollViewer;
if (sv.VerticalOffset > _lastVerticalOffset)
{
MyHeader.Visibility = Visibility.Collapsed;
}
else
{
MyHeader.Visibility = Visibility.Visible;
}
}
This is the basic idea. You might wan't to add some smooth animations instead of just changing the visibility.
After looking around a bit and experimentation I can now answer my own question.
One can use an expression based composition animation to adjust the Y offset of the the header in relation to scrolling. The idea is based on this answer. I prepared a complete working example on GitHub.
The animation is prepared in the SizeChanged event of the ListView:
ScrollViewer scrollViewer = null;
private double previousVerticalScrollOffset = 0.0;
private CompositionPropertySet scrollProperties;
private CompositionPropertySet animationProperties;
SizeChanged += (sender, args) =>
{
if (scrollProperties == null)
scrollProperties = ElementCompositionPreview.GetScrollViewerManipulationPropertySet(scrollViewer);
var compositor = scrollProperties.Compositor;
if (animationProperties == null)
{
animationProperties = compositor.CreatePropertySet();
animationProperties.InsertScalar("OffsetY", 0.0f);
}
var expressionAnimation = compositor.CreateExpressionAnimation("animationProperties.OffsetY - ScrollingProperties.Translation.Y");
expressionAnimation.SetReferenceParameter("ScrollingProperties", scrollProperties);
expressionAnimation.SetReferenceParameter("animationProperties", animationProperties);
var headerVisual = ElementCompositionPreview.GetElementVisual((UIElement)Header);
headerVisual.StartAnimation("Offset.Y", expressionAnimation);
};
The OffsetY variable in the animationProperties will drive the animation of the OffsetY property of the header. The OffsetY variable is updated in the ViewChanged event of the ScrollViewer:
scrollViewer.ViewChanged += (sender, args) =>
{
float oldOffsetY = 0.0f;
animationProperties.TryGetScalar("OffsetY", out oldOffsetY);
var delta = scrollViewer.VerticalOffset - previousVerticalScrollOffset;
previousVerticalScrollOffset = scrollViewer.VerticalOffset;
var newOffsetY = oldOffsetY - (float)delta;
// Keep values within negativ header size and 0
FrameworkElement header = (FrameworkElement)Header;
newOffsetY = Math.Max((float)-header.ActualHeight, newOffsetY);
newOffsetY = Math.Min(0, newOffsetY);
if (oldOffsetY != newOffsetY)
animationProperties.InsertScalar("OffsetY", newOffsetY);
};
While this does animate correctly, the header is not stacked on top of the ListView items. Therefore the final piece to the puzzle is to decrease the ZIndex of the ItemsPanelTemplate of the ListView:
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsStackPanel Canvas.ZIndex="-1" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
Which gives this as a result:

how change color in datagrid view base on string

[enter image description here][1][enter image description here][2]
how to change specific genre text color with color in datagridview base on text
how to change specific genre text color with color in datagridview base on textcom/K8l1o.png
http://i.stack.imgur.com/DgmkW.png
You can create a color from a name like this :
Color red = Color.FromName("Red");
If Color.FromName cannot find a match, it returns new Color(0,0,0);
Than you can use it in a paint event.
I noticed from your image you are using devexpress gridview, so you can try this code (untested !)
private void gridView1_RowStyle(object sender, DevExpress.XtraGrid.Views.Grid.RowStyleEventArgs e)
{
GridView gridView = sender as GridView;
if (e.RowHandle >= 0)
{
if (gridView.GetRowCellValue(e.RowHandle, gridView.Columns["color"]) != null)
{
Color color = Color.FromName(gridView.GetRowCellValue(e.RowHandle, gridView.Columns["color"]).ToString());
e.Appearance.BackColor = color;
}
}
}
but i do it like this
private void gridView1_RowCellStyle_1(object sender, RowCellStyleEventArgs e)
{
GridView View = sender as GridView;
if (e.Column.FieldName == "genre")
{
string category = View.GetRowCellDisplayText(e.RowHandle, View.Columns["genre"]);
if (category == "Gymnastics")
{
e.Appearance.ForeColor = Color.Magenta;
}

Resources