I have a submit button in my page, when I click on the button, button color is slightly changing (highlight).
How to remove this highlight feature in xamarin forms.
On Android it is called ripple effect, you can create a custom renderer to hide it
[assembly: ExportRenderer(typeof(Button), typeof(MyButtonRenderer))]
namespace App.Droid
{
public class MyButtonRenderer : ButtonRenderer
{
public MyButtonRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
{
base.OnElementChanged(e);
if (Control.Background != null && e.NewElement != null)
{
var buttonBackgroundColor = e.NewElement.BackgroundColor;
Control.Background = new RippleDrawable(
new ColorStateList(
new[] { new int[] { } },
new[] { new int { } })
, new ColorDrawable(buttonBackgroundColor.ToAndroid()), null);
}
}
}
}
Related
I have a Tabbed page in my Xamarin Forms app. There I have two children content pages. There are two pickers and a button in the toolbar of the Tabbed page. What I want is to populate data from the server according to the values, which is changing in the pickers. I am using the MVVM design pattern. How can I pass picker values to the children pages? I tried to use the MessagingCenter, It works sometimes but not all the time.
Tabbedpage
public partial class LifekpiRankingTabbedRM : ZeroTabbarHeight
{
public LifekpiRankingTabbedRM(string uRegion)
{
InitializeComponent();
BindingContext = new LifekpiRankingRmTabbedViewModel(uRegion);
Children.Add(new LifeKpiRankingViewRM(uRegion));
Children.Add(new LifeKpiRankingViewRMsBM(uRegion));
}
}
Tabbedpage VM
public class LifekpiRankingRmTabbedViewModel : BaseViewModelHelper
{
public MonthData2 SelectedMonth
{
get => _selectedMonth;
set
{
_selectedMonth = value;
GenerateData(_selectedMonth.mIndex, SelectedKpi).Await(CompletedTask, ErrorHandle);
OnPropertyChanged();
}
}
public string SelectedKpi
{
get => _selectedKpi;
set
{
_selectedKpi = value;
GenerateData(SelectedMonth.mIndex, _selectedKpi).Await(CompletedTask, ErrorHandle);
OnPropertyChanged();
}
}
public LifekpiRankingRmTabbedViewModel(string uRegion)
{
this.uRegion = uRegion;
SelectedMonth = GetCurrentMonth();
SelectedKpi = KpiList.First();
reportType = "Monthly";
ReportTypeTapCommand = new Command(ChangeTypeCommand);
}
private async Task GenerateData(int selectedMonth, string selectedKpi)
{
AcrDialogClass.ShowLoadingDialog("Loading...");
if (runCount > 2)
{
var resRmData = await _apiServices.GetLifeRegionalKpiWiseRanking(selectedMonth, selectedKpi, isCumulative);
var resBmForRmData = await _apiServices.GetLifeBranchKpiWiseRankingForRM(selectedMonth, selectedKpi, uRegion, isCumulative);
if (resRmData != null)
{
MessagingCenter.Send<App, string>(App.Current as App, "KPI_REGINAL_RANKING", resRmData);
}
if (resBmForRmData != null)
{
MessagingCenter.Send<App, string>(App.Current as App, "KPI_BM_RANKING_FOR_RM", resBmForRmData);
}
}
else
{
runCount++;
}
}
private MonthData2 GetCurrentMonth()
{
var months = Enumerable.Range(1, 12).Select(i => new { I = i, M = DateTimeFormatInfo.InvariantInfo.GetMonthName(i) });
foreach (var ss in months)
{
MonthList.Add(new MonthData2() { mIndex = ss.I, mName = ss.M });
}
return MonthList.Find(r => r.mIndex == dt.Month);
}
private void ChangeTypeCommand()
{
if (isCumulative)
{
reportType = "Monthly";
isCumulative = false;
}
else
{
reportType = "Cumulative";
isCumulative = true;
}
GenerateData(SelectedMonth.mIndex, SelectedKpi).Await(CompletedTask, ErrorHandle);
}
private void CompletedTask()
{
AcrDialogClass.HideLoadingDialog();
}
private void ErrorHandle(Exception ex)
{
AcrDialogClass.HideLoadingDialog();
}
}
Tab 1
public partial class LifeKpiRankingViewRM : ContentPage
{
private LifeKpiRankingViewModelRM vm;
public LifeKpiRankingViewRM(string uRegion)
{
InitializeComponent();
BindingContext = new LifeKpiRankingViewModelRM(uRegion);
vm = BindingContext as LifeKpiRankingViewModelRM;
}
protected override void OnAppearing()
{
base.OnAppearing();
MessagingCenter.Subscribe<App, string>(App.Current, "KPI_REGINAL_RANKING", (snd, arg) =>
{
vm.SetValues(arg);
});
}
protected override void OnDisappearing()
{
base.OnDisappearing();
MessagingCenter.Unsubscribe<App, string>(App.Current, "KPI_REGINAL_RANKING");
}
}
Tab 2
public partial class LifeKpiRankingViewRMsBM : ContentPage
{
private LifeKpiRankingViewModelBMForRM vm;
public LifeKpiRankingViewRMsBM(string uRegion)
{
InitializeComponent();
BindingContext = new LifeKpiRankingViewModelBMForRM(uRegion);
vm = BindingContext as LifeKpiRankingViewModelBMForRM;
}
protected override void OnAppearing()
{
base.OnAppearing();
MessagingCenter.Subscribe<App, string>(App.Current, "KPI_BM_RANKING_FOR_RM", (snd, arg) =>
{
vm.SetValues(arg);
});
}
protected override void OnDisappearing()
{
base.OnDisappearing();
MessagingCenter.Unsubscribe<App, string>(App.Current, "KPI_BM_RANKING_FOR_RM");
}
}
At first, you can try to get the child page's instance and then set its value.
If you set the tabbedpage in the app.cs with MainPage = new LifekpiRankingTabbedRM():
var tabbedpage = App.Current.MainPage as LifekpiRankingTabbedRM;
var childpage1 = tabbedpage.Children[0];
var vm1 = childpage1.BindingContext as LifeKpiRankingViewModelRM;
vm1.SetValues(...);
Generally speaking, when you have the instance of the TabbedPage, you can get its child page and update the child page's value.
In addition, you can show more details about the MessageCenter not work and we can help you go on using the MessageCenter.
I have implemented a custom web view renderer in Droid project.
How can I redirect the Phone Dialer from WebView when I click on a phone number in WebView?
Any help is appreciated. Thanks!
You can try the following code:
public class MyWebViewRenderer : WebViewRenderer
{
public MyWebViewRenderer(Context context) : base(context) { }
static MyWebView _xwebView = null;
WebView _webView;
class ExtendedWebViewClient : Android.Webkit.WebViewClient
{
public override bool ShouldOverrideUrlLoading(WebView view, string url)
{
var tel = "tel:";
if (url != null)
{
if (url.StartsWith(tel))
{
var uri = Android.Net.Uri.Parse(url);
var intent = new Intent(Intent.ActionView, uri);
intent.SetFlags(ActivityFlags.NewTask);
Android.App.Application.Context.StartActivity(intent);
return true;
}
}
return false;
}
}
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.WebView> e)
{
base.OnElementChanged(e);
_xwebView = e.NewElement as MyWebView;
_webView = Control;
if (e.OldElement == null)
{
_webView.SetWebViewClient(new ExtendedWebViewClient());
}
}
}
And for the ios part:
public class MyWebViewRenderer : WkWebViewRenderer
{
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
NavigationDelegate = new MyWKNavigationDelegate();
}
class MyWKNavigationDelegate : WKNavigationDelegate
{
[Export("webView:decidePolicyForNavigationAction:decisionHandler:")]
public override void DecidePolicy(WKWebView webView, WKNavigationAction
navigationAction, Action<WKNavigationActionPolicy> decisionHandler)
{
var navType = navigationAction.NavigationType;
var targetFrame = navigationAction.TargetFrame;
var url = navigationAction.Request.Url;
if (
url.ToString().StartsWith("http") && (targetFrame != null &&
targetFrame.MainFrame == true)
)
{
decisionHandler(WKNavigationActionPolicy.Allow);
}
else if (
url.ToString().StartsWith("mailto:")
|| url.ToString().StartsWith("tel:")
|| url.ToString().StartsWith("Tel:"))
{
UIApplication.SharedApplication.application.OpenUrl(url);
}
}
}
}
This question already has answers here:
Remove underline from Entry Control in Xamarin Forms
(5 answers)
Closed 1 year ago.
We are using the visual material entry for our project.
using Xamarin.Forms.Material.IOS;
[assembly: ExportRenderer(typeof(Entry), typeof(CustomMaterialEntryRenderer), new[] { typeof(VisualMarker.MaterialVisual) })]
namespace MyApp.Android
{
public class CustomMaterialEntryRenderer : MaterialProgressBarRenderer
{
//...
}
}
How to remove material entry underline in xamarin forms ios?
You could set the active underline height to 0f to achieve this:
[assembly: ExportRenderer(typeof(CustomMaterialEntry), typeof(CustomMaterialEntryRenderer), new[] { typeof(VisualMarker.MaterialVisual) })]
namespace MyApp.iOS
public class CustomMaterialEntryRenderer : MaterialEntryRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if (this.Control != null)
{
Control.ActiveTextInputController.UnderlineHeightActive = 0f;
}
}
}
You can use custom renderers with material visual to achieve entry underline removal.
I am using the below code to apply it for all entries in the project and it is working with Xamarin Forms 4.8+
Xamarin Android
Entry
[assembly: ExportRenderer(typeof(Entry), typeof(EntryMaterialRendererAndroid), new[] { typeof(VisualMarker.MaterialVisual) })]
namespace XFTest.Droid.Renderers
{
public class EntryMaterialRendererAndroid : MaterialEntryRenderer
{
public EntryMaterialRendererAndroid(Context context) : base(context) { }
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if (Control != null)
{
Control.BoxStrokeWidth = 0;
Control.BoxStrokeWidthFocused = 0;
}
}
}
}
Xamarin iOS
Entry
[assembly: ExportRenderer(typeof(Entry), typeof(EntryMaterialRendereriOS), new[] { typeof(VisualMarker.MaterialVisual) })]
namespace XFTest.iOS.Renderers
{
public class EntryMaterialRendereriOS : MaterialEntryRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
EntryRemoveUnderLine();
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
EntryRemoveUnderLine();
}
protected void EntryRemoveUnderLine()
{
if (Control != null)
{
Control.BorderStyle = UITextBorderStyle.None;
Control.Underline.Enabled = false;
Control.Underline.DisabledColor = UIColor.Clear;
Control.Underline.Color = UIColor.Clear;
Control.Underline.BackgroundColor = UIColor.Clear;
Control.ActiveTextInputController.UnderlineHeightActive = 0f;
Control.PlaceholderLabel.BackgroundColor = UIColor.Clear;
}
}
}
}
I'm facing some issue with Slide menu in Masterdetail page. I want to disable the functionality in iOS.
In Android, I'm able to disable. But, in iOS it's not working.
"IsGestureEnabled="False" - This Property is working in Android. But not in iOS.
Please help me out this issue.
It seems an existing,and you can use CustomRenderer . Here is a workaround .However , this workaround seems obsolete because of the update of Xamarin.So we can improve it .
[assembly: ExportRenderer (typeof(MasterDetailPage), typeof(ExtendedMasterDetailPageRenderer), UIUserInterfaceIdiom.Phone)]
namespace Core.iOS.Renderers
{
public class ExtendedMasterDetailPageRenderer : PhoneMasterDetailRenderer
{
private MasterDetailPage page;
public ExtendedMasterDetailPageRenderer ()
{
}
// add following override method
public override void ViewDidLayoutSubviews()
{
base.ViewDidLayoutSubviews();
((MasterDetailPage)this.Element).PropertyChanged += HandlePropertyChanged;
}
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
((MasterDetailPage)this.Element).PropertyChanged += HandlePropertyChanged;
}
private void HandlePropertyChanged (object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == MasterDetailPage.IsGestureEnabledProperty.PropertyName)
{
var panGesture = typeof(PhoneMasterDetailRenderer).GetField ("panGesture", BindingFlags.NonPublic | BindingFlags.Instance).GetValue (this) as UIPanGestureRecognizer;
var hasPanGesture = false;
if (panGesture != null)
{
for (int i = 0; i < this.View.GestureRecognizers.Length; i++)
{
if (this.View.GestureRecognizers [i] is UIPanGestureRecognizer)
{
hasPanGesture = true;
break;
}
}
if (((MasterDetailPage)this.Element).IsGestureEnabled)
{
if (!hasPanGesture)
{
this.View.AddGestureRecognizer (panGesture);
}
return;
}
if (hasPanGesture)
{
this.View.RemoveGestureRecognizer (panGesture);
}
}
}
}
}
}
And in your MasterDetailPage
protected override void OnAppearing()
{
base.OnAppearing();
IsGestureEnabled = false;
}
Update
Create a CustomRenderer of Page
[assembly: ExportRenderer(typeof(Page), typeof(MyPageRenderer), UIUserInterfaceIdiom.Phone)]
namespace xxx.iOS
{
class MyPageRenderer : PageRenderer
{
public override void ViewDidLayoutSubviews()
{
base.ViewDidLayoutSubviews();
if (this.NavigationController != null)
{
var items = this.NavigationController.NavigationBar.Items;
if(items.Length > 0)
{
UIBarButtonItem leftItem = items[0].LeftBarButtonItem;
if(this.NavigationController.ViewControllers.Length == 1)
{
leftItem.Enabled = false;
}
}
}
}
}
}
If I have an Entry in my Xamarin Forms project and I keep typing on it until it goes off the end of the viewable page the text does not horizontally scroll in iOS as it does on Android - is there a way to make it do this?
I've tried replacing it with an Editor, but that doesn't have a placeholder, which I need.
An Entry is rendered as a UITextField on iOS which does not support scrolling. An Editor is rendered as a UITextView which does support scrolling.
One option would be to create a custom editor that includes a placeholder.
I have code for this. It's not pretty but it works.
Here is the CustomEditor code including new bindable properties for placeholder text and color.
public class CustomEditor : Editor
{
public static readonly BindableProperty PlaceholderProperty =
BindableProperty.Create(nameof(Placeholder), typeof(string), typeof(CustomEditor), default(string));
public string Placeholder
{
get { return (string)GetValue(PlaceholderProperty); }
set { SetValue(PlaceholderProperty, value); }
}
public static readonly BindableProperty PlaceholderColorProperty =
BindableProperty.Create(nameof(PlaceholderColor), typeof(Color), typeof(CustomEditor), default(Color));
public Color PlaceholderColor
{
get { return (Color)GetValue(PlaceholderColorProperty); }
set { SetValue(PlaceholderColorProperty, value); }
}
public static readonly BindableProperty DisabledColorProperty =
BindableProperty.Create(nameof(DisabledColor), typeof(Color), typeof(CustomEditor), default(Color));
public Color DisabledColor
{
get { return (Color)GetValue(DisabledColorProperty); }
set { SetValue(DisabledColorProperty, value); }
}
}
Here is the iOS custom renderer
[assembly: ExportRenderer(typeof(CustomEditor), typeof(CustomEditorRenderer))]
namespace Test.iOS.CustomRenderers
{
public class CustomEditorRenderer : EditorRenderer
{
private UILabel PlaceholderLabel { get; set; }
protected override void OnElementChanged(ElementChangedEventArgs<Editor> e)
{
base.OnElementChanged(e);
if (Control == null) return;
Control.Layer.BorderWidth = 0.5f;
Control.Layer.CornerRadius = 8;
Control.Layer.BorderColor = Color.FromHex("CDCDCD").ToCGColor();
if (PlaceholderLabel != null) return;
var element = Element as CustomEditor;
PlaceholderLabel = new UILabel
{
Text = element?.Placeholder,
TextColor = element?.PlaceholderColor.ToUIColor(),
BackgroundColor = UIColor.Clear
};
var edgeInsets = Control.TextContainerInset;
var lineFragmentPadding = Control.TextContainer.LineFragmentPadding;
Control.AddSubview(PlaceholderLabel);
var vConstraints = NSLayoutConstraint.FromVisualFormat(
"V:|-" + edgeInsets.Top + "-[PlaceholderLabel]-" + edgeInsets.Bottom + "-|", 0, new NSDictionary(),
NSDictionary.FromObjectsAndKeys(
new NSObject[] { PlaceholderLabel }, new NSObject[] { new NSString("PlaceholderLabel") })
);
var hConstraints = NSLayoutConstraint.FromVisualFormat(
"H:|-" + lineFragmentPadding + "-[PlaceholderLabel]-" + lineFragmentPadding + "-|",
0, new NSDictionary(),
NSDictionary.FromObjectsAndKeys(
new NSObject[] { PlaceholderLabel }, new NSObject[] { new NSString("PlaceholderLabel") })
);
PlaceholderLabel.TranslatesAutoresizingMaskIntoConstraints = false;
Control.AddConstraints(hConstraints);
Control.AddConstraints(vConstraints);
PlaceholderLabel.Hidden = Element.Text.NotEmpty();
}
protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == "Text")
{
PlaceholderLabel.Hidden = Control.Text.NotEmpty();
}
if (e.PropertyName == VisualElement.IsEnabledProperty.PropertyName)
{
var element = Element as CustomEditor;
SetTextColor(element);
}
}
private void SetTextColor(CustomEditor element)
{
Control.TextColor = element.IsEnabled ? element.TextColor.ToUIColor() : element.DisabledColor.ToUIColor();
}
}
}