I'm trying to change the search icon in a SearchBarRenderer Android custom renderer
and that's what I tried
Control.Iconified = false;
Control.SetIconifiedByDefault(false);
var searchView = Control.FindViewById<ImageView>(Resource.Id.search_button);
var searchicon = Resources.GetDrawable(Resource.Drawable.search);
searchView.SetImageDrawable(searchicon);
However, searchIcon is always null
When I looped through the children of SearchView I found and image view with ID 16909229 but setting the image drawable of that didn't change the search icon
I'm trying to change the search icon in a SearchBarRenderer Android custom renderer
Modify your code like this:
[assembly:ExportRenderer(typeof(SearchBar), typeof(MySearchBarRenderer))]
namespace yourprjectnamespace
{
public class MySearchBarRenderer : SearchBarRenderer
{
public MySearchBarRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.SearchBar> e)
{
base.OnElementChanged(e);
if (Control != null)
{
var searchView = Control;
int searchViewCloseButtonId = Control.Resources.GetIdentifier("android:id/search_mag_icon", null, null);
var closeIcon = searchView.FindViewById(searchViewCloseButtonId);
(closeIcon as ImageView).SetImageResource(Resource.Mipmap.icon);
}
}
}
}
Effect.
If you are using android.support.v7.widget.SearchView you can try to set it like this:
var searchIcon = (ImageView) searchView.FindViewById(Resource.Id.search_mag_icon);
searchIcon.SetImageResource(Resource.Drawable.my_custom_search_icon);
Source: https://stackoverflow.com/a/20362491/6248510 it's not the same question but it is related to it and in the answer it is included a way to set it
Related
I have a custom ButtonRenderer for Android and I want to change the color of the Image that I use for the button.
This is my ButtonRenderer:
public class VolosBaseButtonRenderer : Xamarin.Forms.Platform.Android.AppCompat.ButtonRenderer {
public VolosBaseButtonRenderer(Context context) : base(context) { }
protected override void OnElementChanged(ElementChangedEventArgs<Button> e) {
base.OnElementChanged(e);
// What I must do here for change the Image color????
}
protected override AppCompatButton CreateNativeControl() {
var context = new ContextThemeWrapper(Context, Resource.Style.Widget_AppCompat_Button_Borderless);
var button = new AppCompatButton(context, null, Resource.Style.Widget_AppCompat_Button_Borderless);
return button;
}
}
I tried these methods but none worked:
Control.Background.SetColorFilter(global::Android.Graphics.Color.Blue, global::Android.Graphics.PorterDuff.Mode.SrcIn);
Control.Background.SetTint(Color.Red.ToAndroid());
If it's possible I can apply a style at the button (but I don't know how to do it).
Any methods will be fine.
Thank you!
Assuming your custom Button has two properties, CustomImage, which stores a string of an resource image name, ie "icon.png", and another ImageTintColor, which stores a Xamarin.Forms.Color object, you can use it like so:
var button = (CustomButton)Control.Element;
using (var image = GetScaleDrawable(Resources.GetDrawable(button.CustomImage.Split('.')[0]),
(int)button.WidthRequest,
(int)button.HeightRequest))
{
if (button.ImageTintColor != Xamarin.Forms.Color.Default)
image.SetColorFilter(button.ImageTintColor.ToAndroid(), PorterDuff.Mode.SrcAtop);
this.Control.SetPadding(0, 0, 0, 0);
this.Control.SetCompoundDrawables(null, image, null, null);
}
Is it possible to remove the top blue border(or atleast change its color) of xamarins TableSection:
I looked at Xamarin TableView documentation, but I found no help there:
https://developer.xamarin.com/guides/xamarin-forms/user-interface/tableview/
My code at the moment looks like this:
public class UserProfilePushNotification : TableView
{
public UserProfilePushNotification(string text) : base()
{
Intent = TableIntent.Data;
Root = new TableRoot
{
new TableSection
{
new SwitchCell
{
Text = text
},
new TextCell()
{
Text = string.Empty
},
new TextCell
{
Text = "Android Version: 1.2.1"
}
}
};
}
}
I was digging into this problem and I found that TableView is implemented (in the default renderer) as a ListView.
The TableSection is just a normal item in the Listview, the first one.
If you don't use the Title Property from the TableSection (in this case you aren't using it) you can hide it.
To do this I created a custom render for the TableView and hidden the first element of the ListView:
[assembly:ExportRenderer(typeof(Project.MenuTableView), typeof(Project.Droid.MenuTableViewRenderer))]
namespace Project.Droid
{
public class MenuTableViewRenderer : TableViewRenderer
{
private bool _firstElementAdded = false;
protected override void OnElementChanged (ElementChangedEventArgs<TableView> e)
{
base.OnElementChanged (e);
if (Control == null)
return;
var listView = Control as Android.Widget.ListView;
listView.ChildViewAdded += (sender, args) =>
{
if (!_firstElementAdded)
{
args.Child.Visibility = ViewStates.Gone;
_firstElementAdded = true;
}
};
// Uncomment this if you want to remove all the dividers from the table.
//listView.DividerHeight = 0;
}
}
}
I am using Xamarin Forms picker control and require setting the text color, however there is no such property. I have tried making a custom renderer which worked out for me in android and ios (I ended up redrawing the control). In the wp8.1 platform there is no Draw event and the control itself in the renderer doesn't seem to have the properties to set the text color. I have also attempted changing the control the picker binds to unsuccessfully.
Currently I have created the bindable property TextColor in the PCL which is working. The code for my renderer is shown below (I have stripped all my test code and am putting only the basic code since I havent found anything useful yet and am putting my code just to keep everyone in context). Also note that the property Picker.TextColorProperty doesnt exist and is what I would like to do...
using Namespace.CustomControls;
using Namespace.WinPhone.Renderers;
using Xamarin.Forms;
using Xamarin.Forms.Platform.WinPhone;
[assembly: ExportRendererAttribute(typeof(BindablePicker), typeof(BindablePickerRenderer))]
namespace Namspace.WinPhone.Renderers
{
public class BindablePickerRenderer : PickerRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Picker> e)
{
base.OnElementChanged(e);
var picker = e.NewElement;
BindablePicker bp = (BindablePicker)this.Element;
if (this.Control != null)
{
var pickerStyle = new Style(typeof(Picker))
{
Setters = {
new Setter {Property = Picker.BackgroundColorProperty, Value = bp.BackgroundColor},
new Setter {Property = Picker.TextColorProperty, Value = bp.TextColor}
}
};
picker.Style = pickerStyle;
}
}
}
}
Anyhow I am wondering if anyone might have a little more knowledge on how to do this and could shed some light on me.
There is no TextColor property available in the Picker like you mention.
Even this being the case, we can still achieve changing the Picker text color for WindowsPhone.
I'm assuming you are inheriting from PickerRenderer as it was missing from your code example and I've added some extra things so this is more helpful to others:-
Define the interface in the PCL:-
public interface ICustomPicker2
{
Xamarin.Forms.Color MyBackgroundColor { get; set; }
Xamarin.Forms.Color MyTextColor { get; set; }
}
Extend the Xamarin.Forms Picker in the PCL:-
public class CustomPicker2
: Xamarin.Forms.Picker
, ICustomPicker2
{
public static readonly BindableProperty MyBackgroundColorProperty = BindableProperty.Create<CustomPicker2, Xamarin.Forms.Color>(p => p.MyBackgroundColor, default(Xamarin.Forms.Color));
public static readonly BindableProperty MyTextColorProperty = BindableProperty.Create<CustomPicker2, Xamarin.Forms.Color>(p => p.MyTextColor, default(Xamarin.Forms.Color));
public Xamarin.Forms.Color MyTextColor
{
get { return (Xamarin.Forms.Color)GetValue(MyTextColorProperty); }
set { SetValue(MyTextColorProperty, value); }
}
public Xamarin.Forms.Color MyBackgroundColor
{
get { return (Xamarin.Forms.Color)GetValue(MyBackgroundColorProperty); }
set { SetValue(MyBackgroundColorProperty, value); }
}
}
Create your WindowsPhone renderer like so in a class library:-
public class CustomPicker2Renderer
: PickerRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Picker> e)
{
base.OnElementChanged(e);
var picker = e.NewElement;
CustomPicker2 bp = (CustomPicker2)this.Element;
if (this.Control != null)
{
var pickerStyle = new Style(typeof(Picker))
{
Setters = {
new Setter {Property = Picker.BackgroundColorProperty, Value = bp.MyBackgroundColor},
}
};
SetPickerTextColor(bp.MyTextColor);
picker.Style = pickerStyle;
}
}
private void SetPickerTextColor(Xamarin.Forms.Color pobjColor)
{
byte bytR = (byte)(pobjColor.R * 255);
byte bytG = (byte)(pobjColor.G * 255);
byte bytB = (byte)(pobjColor.B * 255);
byte bytA = (byte)(pobjColor.A * 255);
//
((System.Windows.Controls.Control)(((System.Windows.Controls.Panel)this.Control).Children[0])).Foreground = new SolidColorBrush(System.Windows.Media.Color.FromArgb(bytA, bytR, bytG, bytB));
}
Note, the above is all what you need if you just want to set the text color the once.
However if you want to change the color after it has been initially set, then you will need to listen to the property change and act upon it like in the following:-
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
//
if (e.PropertyName == "MyTextColor")
{
SetPickerTextColor((this.Element as CustomPicker2).MyTextColor);
}
}
You will also need to export the renderer from the class library as well:-
[assembly: ExportRendererAttribute(typeof(CustomPicker2), typeof(CustomPicker2Renderer))]
I am creating a custom control in my C# application in order to add a new property (MyProperty below). It is inheriting from Label. One thing I would like it to do, is display at a particular size when I drag it on to my form (200x132). I'd also like it to display no text. However, no matter how I try to do this, it doesn't seem to work. I am able to set BackColor and BorderStyle with no problem, however. I'm fairly new to C#, so maybe I'm missing something obvious.
Here is my code:
using System.Drawing;
using System.Windows.Forms;
namespace MyProgram
{
public enum MyEnum
{
Value1, Value2, Value3
}
public partial class MyControl : Label
{
public MyControl()
{
BackColor = Color.LightCoral;
BorderStyle = BorderStyle.FixedSingle;
AutoSize = false;
Size = new Size(200, 132);
Text = "";
InitializeComponent();
}
protected override void OnPaint(PaintEventArgs pe)
{
base.OnPaint(pe);
}
private MyEnum myProperty;
public MyEnum MyProperty
{
get { return myProperty; }
set { myPropery = value; }
}
}
}
The answer provided via Dispersia's link has a bug, in my opinion. The text reset should happen once and then whatever a user does after that shouldn't matter. In Dispersia's link you can't actually set the text back to the control name because it will keep blanking it out.
The answer provided by cramopy doesn't technically answer your question, it is a way to do it by using the defaults on a UserControl though. You'll also need to bind the Text property of the UserControl to the label's.
The following should work while inheriting from a Label and will only reset the Text property once.
public partial class MyControl : Label
{
#region fields
private IComponentChangeService _changeService;
private bool canResetText = false;
#endregion
#region properties
protected override Size DefaultSize
{
get { return new Size(200, 132); }
}
[Browsable(false)]
public override bool AutoSize
{
get { return false; }
set { base.AutoSize = false; }
}
public override ISite Site
{
get { return base.Site; }
set
{
base.Site = value;
if (!base.DesignMode)
return;
this._changeService = (IComponentChangeService)base.GetService(typeof(IComponentChangeService));
if (this._changeService != null)
this._changeService.ComponentChanged += new ComponentChangedEventHandler(this.OnComponentChanged);
}
}
#endregion
#region constructors
public MyControl()
{
base.BackColor = Color.LightCoral;
base.BorderStyle = BorderStyle.FixedSingle;
}
#endregion
#region methods
protected override void InitLayout()
{
base.InitLayout();
this.canResetText = true;
}
private void OnComponentChanged(object sender, ComponentChangedEventArgs ce)
{
if (ce.Component != null &&
ce.Component == this &&
ce.Member.Name == "Text" &&
base.DesignMode &&
this.canResetText)
{
((MyControl)ce.Component).Text = string.Empty;
this.canResetText = false;
if (this._changeService != null)
this._changeService.ComponentChanged -= new ComponentChangedEventHandler(this.OnComponentChanged);
}
}
#endregion
}
#Dispersia reply only answers the myControl1 thing. (deleted meanwhile)
Here comes a full guide for solving your problem:
Add a new UserControl named MyLabel
Change the following within Designer Mode:
BorderStyle:= FixedSingle
Size:= 200; 132
Now Drag&Drop a new Label onto the control
Edit those Label values (also within Designer Mode):
AutoSize:= false
BackColor:= LightCoral
Dock:= Fill
Text:= clear/empty this box!! (don't write this inside the box, you really have to clear it!)
TextAlign:= MiddleCenter
Just recompile your project && add a MyLabel control from the Toolbar.
Now it show up as you wanted!!
I'm trying to display a list view with cells that are rendered with a custom iOS renderer. When scrolling the list, there are nasty overlays (as shown below). I boiled it down to the following lines of code.
The App contains a ListView with its ItemsSource set to a dummy list of all characters from A to Z. The ItemTemplate is created with a custom ItemCell defined below.
public class App : Application
{
public App()
{
MainPage = new ContentPage {
Content = new ListView {
ItemsSource = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray(),
ItemTemplate = new DataTemplate(typeof(ItemCell)),
},
};
}
}
The ItemCell contains a Label bound to the list item.
public class ItemCell: ViewCell
{
public ItemCell()
{
View = new Label();
View.SetBinding(Label.TextProperty, ".");
}
}
On iOS the Label is rendered with the following FixedLabelRenderer. It sets a native control represented by a UILabel containing the Element's Text.
public class FixedLabelRenderer : ViewRenderer<Label, UILabel>
{
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
base.OnElementChanged(e);
SetNativeControl(new UILabel(RectangleF.Empty) { Text = Element.Text });
}
}
Now the problem is that, apparently, when reusing a cell, the control is not removed, but only a new one is created. So I'm getting the overlays shown in the screenshots below.
(Left: before scrolling, Right: after scrolling)
Interestingly this issue doesn't happen with Xamarin.Forms 1.2.3 or 1.3.1, but with 1.3.5 and 1.4.0.
Oh, I found a solution on the Xamarin Forum:
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
base.OnElementChanged(e);
if (Control == null)
SetNativeControl(new UILabel());
if (e.NewElement != null)
Control.Text = e.NewElement.Text;
}
So basically you need to make sure to only create one UILabel and reuse it afterwards.