I'm trying to use the BackColor variable to fill an OvalShape.
I'm doing this because I need to set the color at runtime and it is the only custom control that uses FillColor instead of BackColor.
The color is changed at runtime using a propertygrid.
I'm overwriting BackColor and it works until I click on the OvalShape.
if I click on the Oval it colors the entire Control not just the Oval.
public override Color BackColor
{
get
{
if (oval == null)
{
return Color.Transparent;
}
else
{
return oval.FillColor;
}
}
set
{
if (oval == null)
{
base.BackColor = Color.Transparent;
if (sc != null)
sc.BackColor = Color.Transparent;
}
else
{
base.BackColor = Color.Transparent;
if (sc != null)
sc.BackColor = Color.Transparent;
oval.FillColor = value;
}
}
}
sc is the ShapeContainer.
I think the problem is that when I click the control is gets the oval.FillColor for the backColor.
Related
I have the following code in iOS renderer:
public class TabbedPageRenderer : TabbedRenderer
{
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
try
{
var tabbarController = (UITabBarController)this.ViewController;
if (null != tabbarController)
{
tabbarController.ViewControllerSelected += OnTabBarReselected;
}
}
catch (Exception exception)
{
Console.WriteLine(exception);
}
}
void OnTabBarReselected(object sender, UITabBarSelectionEventArgs e)
{
var tabs = Element as TabbedPage;
var playTab = tabs.Children[4];
if (TabBar.SelectedItem.Title == "Play")
{
if (tabs != null)
{
playTab.Title = "Pause";
playTab.Icon = "ionicons_2_0_1_pause_outline_22.png";
}
App.pauseCard = false;
}
else
{
if (tabs != null)
{
playTab.Title = "Play";
playTab.Icon = "ionicons_2_0_1_play_outline_25.png";
}
App.pauseCard = true;
}
}
}
What this do is let the user pause/play a timer running in a page. When opening the app, Home tab will be open so the Play icon is displayed. But when switching to the Play tab, by default the timer is running so the Pause title and icon is displayed.
The code above works perfectly for iOS. But I am still lost in Android. I have tried the following code for Android:
public class MyTabbedPageRenderer: TabbedPageRenderer, TabLayout.IOnTabSelectedListener
{
void TabLayout.IOnTabSelectedListener.OnTabReselected(TabLayout.Tab tab)
{
var tabs = Element as TabbedPage;
var playTab = tabs.Children[4];
var selectedPosition = tab.Position;
if(selectedPosition == 4)
{
if (playTab.Title == "Play")
{
if (tabs != null)
{
playTab.Title = "Pause";
playTab.Icon = "ionicons_2_0_1_pause_outline_22.png";
}
App.pauseCard = false;
}
else
{
if (tabs != null)
{
playTab.Title = "Play";
playTab.Icon = "ionicons_2_0_1_play_outline_25.png";
}
App.pauseCard = true;
}
}
}
}
Obviously this would only work when reselecting the tab. Would really appreciate if someone could point me to the right direction here.
Like #G.hakim, you also need add TabLayout.IOnTabSelectedListener.OnTabSelected method, and it will be same as OnTabReselected:
void TabLayout.IOnTabSelectedListener.OnTabSelected(TabLayout.Tab tab)
{
var tabs = Element as TabbedPage;
var playTab = tabs.Children[4];
var selectedPosition = tab.Position;
if(selectedPosition == 4)
{
if (playTab.Title == "Play")
{
if (tabs != null)
{
playTab.Title = "Pause";
playTab.Icon = "ionicons_2_0_1_pause_outline_22.png";
}
App.pauseCard = false;
}
else
{
if (tabs != null)
{
playTab.Title = "Play";
playTab.Icon = "ionicons_2_0_1_play_outline_25.png";
}
App.pauseCard = true;
}
}
}
I'm developing Xamarin iOS app.
Is it possible to create global styles (e.g. for buttons) in Xamarin iOS apps like in Xamarin Android apps?
Any ideas?
Apple provides Appearance API that you could use for this purpose.
There is a nice article about it on official Xamarin developer portal.
The idea behind it is that you could use static methods on the controls to set a desired appearance, for example:
UIButton.Appearance.TintColor = UIColor.LightGray;
UIButton.Appearance.SetTitleColor(UIColor.FromRGB(0,127,14), UIControlState.Normal);
Create a control set common theme in that.
For example
public class CustomTextField : UITextField
{
public UIView RightViewEnabled
{
get;
set;
}
public UIView RightViewDisabled
{
get;
set;
}
public override CoreGraphics.CGRect LeftViewRect(CoreGraphics.CGRect forBounds)
{
var rect = base.LeftViewRect(forBounds);
rect.X += 10;
//rect.Y -= 2;
return rect;
}
public override CoreGraphics.CGRect RightViewRect(CoreGraphics.CGRect forBounds)
{
var rect = base.RightViewRect(forBounds);
rect.X -= 10;
return rect;
}
public override CoreGraphics.CGRect TextRect(CoreGraphics.CGRect forBounds)
{
var rect = base.TextRect(forBounds);
if (LeftView != null)
rect.X += 5;
if (RightView != null)
rect.Width -= 10;
return rect;
}
public override CoreGraphics.CGRect EditingRect(CoreGraphics.CGRect forBounds)
{
var rect = base.EditingRect(forBounds);
if (LeftView != null)
rect.X += 5;
//if (RightView != null)
// rect.X -= 10;
return rect;
}
public override bool Enabled
{
get
{
return base.Enabled;
}
set
{
base.Enabled = value;
if (value)
{
if (RightViewEnabled != null)
RightView = RightViewEnabled;
base.TextColor = _textColor;
}
else
{
if (RightViewDisabled != null)
RightView = RightViewDisabled;
if (TextColorDisabled != null)
base.TextColor = TextColorDisabled;
}
}
}
public UIColor TextColorDisabled
{
get;
set;
}
private UIColor _textColor;
public override UIColor TextColor
{
get
{
return base.TextColor;
}
set
{
_textColor = value;
base.TextColor = value;
}
}
public Guid ValueId
{
get;
set;
}
public override bool CanPerform(ObjCRuntime.Selector action, Foundation.NSObject withSender)
{
if (action == new Selector("paste:") || action == new Selector("cut:") || action == new Selector("copy:")
|| action == new Selector("select:") || action == new Selector("selectAll:") || action == new Selector("delete:") || action == new Selector("_promptForReplace:")
|| action == new Selector("_transliterateChinese:") || action == new Selector("_showTextStyleOptions:") || action == new Selector("_define:") || action == new Selector("_addShortcut:")
|| action == new Selector("_accessibilitySpeak:") || action == new Selector("_accessibilitySpeakLanguageSelection:") || action == new Selector("_accessibilityPauseSpeaking:") || action == new Selector("makeTextWritingDirectionRightToLeft:")
|| action == new Selector("makeTextWritingDirectionLeftToRight:") || action == new Selector("_share:"))
return false;
else
return base.CanPerform(action, withSender);
}
}
I can successfully work with the badge on my tabbar if i use it straight in my ViewWillAppear function but if i create a function where i try to control it then the badge does not appear.
This is the tabbedpaged renderer where I have to the function that changes the badge.
public override void ViewWillAppear(bool animated)
{
if (TabBar == null) return;
if (TabBar.Items == null) return;
var tabs = Element as TabbedPage;
if (tabs != null)
{
for (int i = 0; i < TabBar.Items.Length; i++)
{
UpdateItem(TabBar.Items[i], tabs.Children[i].Icon);
}
}
base.ViewWillAppear(animated);
}
private void UpdateItem(UITabBarItem item, string icon)
{
TabBar.UnselectedItemTintColor = UIColor.White;
}
public void UpdateBadge ()
{
var tabs = Element as TabbedPage;
if (tabs != null)
{
Device.BeginInvokeOnMainThread(() =>
{
var tab = TabBar.Items[3];
tab.BadgeValue = "New";
tab.BadgeColor = UIColor.Red;
});
}
}
Then I have another file where I handle a pushnotification and this is where I call the UpdateBadgefunction to both push a notification and also update the badge in the app.
void IPush.SendPush()
{
var notification = new UILocalNotification();
notification.SoundName = UILocalNotification.DefaultSoundName;
UIApplication.SharedApplication.PresentLocalNotificationNow(notification);
TabbedPage_Renderer tpr = new TabbedPage_Renderer();
tpr.UpdateBadge();
}
But as stated above this does not add the badge.
If I however add...
var tab = TabBar.Items[3];
tab.BadgeValue = "New";
tab.BadgeColor = UIColor.Red;
...inside the ViewWillAppear straight away it successfully shows an iconbadge when i start the app up but the idea is to control it so i can update the badge whenever i want.
We should not use the instance of the Renderer directly.
If you want to change the UI in the platform's renderer, we can try to define a BindableProperty in the forms. Then tell the renderer do some configuration when this property changed.
Firstly, define a BindableProperty in the page which you want to change its Badge like:
public static readonly BindableProperty BadgeTextProperty = BindableProperty.Create(nameof(BadgeText), typeof(string), typeof(MainPage), "0");
public string BadgeText {
set
{
SetValue(BadgeTextProperty, value);
}
get
{
return (string)GetValue(BadgeTextProperty);
}
}
Secondly, in the renderer, we can set the badge text when this property changed like:
for (int i = 0; i < TabBar.Items.Length; i++)
{
UpdateItem(TabBar.Items[i], tabs.Children[i].Icon);
//register the property changed event
tabs.Children[i].PropertyChanged += TabbarPageRenderer_PropertyChanged;
}
private void TabbarPageRenderer_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
var page = sender as Page;
if (page == null)
return;
if (e.PropertyName == "BadgeText")
{
if (CheckValidTabIndex(page, out int tabIndex))
{
switch(tabIndex)
{
case 0:
UpdateBadge(TabBar.Items[tabIndex], (page as MainPage).BadgeText);
break;
case 1:
//Second Page, you can expand this switch depending on your tabs children
UpdateBadge(TabBar.Items[tabIndex], (page as SecondPage).BadgeText);
break;
default:
break;
}
}
return;
}
}
public bool CheckValidTabIndex(Page page, out int tabIndex)
{
tabIndex = Tabbed.Children.IndexOf(page);
return tabIndex < TabBar.Items.Length;
}
private void UpdateItem(UITabBarItem item, string icon)
{
TabBar.UnselectedItemTintColor = UIColor.White;
...//set the tabItem
}
private void UpdateBadge(UITabBarItem item, string badgeText)
{
item.BadgeValue = text;
item.BadgeColor = UIColor.Red;
}
At last, set the BadgeText in the forms when you want to update the badge.
My Custom renderer for Radio Button is,
public class RadioButtonRenderer : ViewRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<CustomRadioButton> e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
e.OldElement.PropertyChanged += ElementOnPropertyChanged;
}
if (this.Control == null)
{
var radButton = new RadioButton(this.Context);
radButton.CheckedChange += radButton_CheckedChange;
this.SetNativeControl(radButton);
}
Control.Text = e.NewElement.Text;
Control.Checked = e.NewElement.Checked;
Element.PropertyChanged += ElementOnPropertyChanged;
}
Can anybody know how to set space between radio button to text.
Android RadioButton widget is a CompoundButton and you can set its TextView's relative padding:
Control.SetPaddingRelative(150, 0, 0, 0);
I am following around on a kindle book I bought for developing metro apps. For some reason I cannot set the text value of a text box in a method outside the OnNavigatedTo method. This is the code that the book provides:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
//passed in the view model
viewModel = e.Parameter as ViewModel;
this.DataContext = viewModel;
viewModel.PropertyChanged += (sender, eventArgs) =>
{
if (eventArgs.PropertyName == "SelectedItemIndex")
{
if (viewModel.SelectedIndex == -1)
{
SetItemDetail(null);
}
else
{
SetItemDetail(viewModel.GroceryList[viewModel.SelectedIndex]);
}
}
SetItemDetail(viewModel.GroceryList[viewModel.SelectedIndex]);
};
}
private void SetItemDetail(GroceryItem item)
{
ItemDetailName.Text = "test"; //(item == null) ? "" : item.Name;
ItemDetailQuantity.Text = "test"; //(item == null) ? "" : item.Quantity.ToString();
//if (item != null)
//{
// ItemDetailStore.SelectedItem = item.Store;
//}
//else
//{
// ItemDetailStore.SelectedIndex = -1;
//}
}
I have commented parts out in the set item detail method, but I still cannot set the value of a textbox when I click it (this is supposed to be the behavior). I have used break points and the property of the textbox is getting set, however, it is not displayed on screen.
Thanks.