How to create square check box in iOS xamarin form [duplicate] - ios

This Below is my IOS Page .I want to show this type of check box on iOS in xamarin form. I have use Xamarin 5.0 version. When I am try to use check element in iOS show rounded check box but I want square check box.
<CheckBox x:Name="chkRememberMe" BackgroundColor="#7E7E7E" SizeChanged="20" IsChecked="False" CheckedChanged="ChkRememberMe_OnCheckedChanged" ></CheckBox>
This is my check box code what can I do that in iOS for a square checkbox.I'm completely new to xamarin.forms, I need to add a checkbox, radio buttons and drop down list. I tried some samples from net but I'm not able to get the checkbox. Can anyone help me to achieve.Controls.Checkbox to create checkbox for ios and andorid in Xamarin Forms.Now i am getting the checkbox but i cant read the value either it is checked or not.Here is my code

You could use the plugin Xamarin.Forms.InputKit from nuget .
xmlns:input="clr-namespace:Plugin.InputKit.Shared.Controls;assembly=Plugin.InputKit"
<input:CheckBox Text="xxx" Type="Check"/>
If you want to customize the style of the checkbox , you could check https://github.com/enisn/Xamarin.Forms.InputKit/wiki/CheckBox .

If you don't want to change the check boxes on other platforms, you can use a custom renderer to only change how it looks on iOS.
Subclass the CheckBox in your shared project:
public class CustomCheckBox : CheckBox {}
And add the custom renderer to the iOS project:
using CoreGraphics;
using UIKit;
using Xamarin.Forms.Platform.iOS;
using Xamarin.Forms;
using YourApp.iOS;
using YourApp.Controls; // namespace of your CustomCheckBox
using System.ComponentModel;
[assembly: ExportRenderer(typeof(CustomCheckBox), typeof(CustomCheckBoxRenderer))]
namespace YourApp.iOS
{
public class CustomCheckBoxRenderer : ViewRenderer<CustomCheckBox, UIView>
{
private const float SideLength = 18f;
private bool firstTime = true;
protected override void OnElementChanged(ElementChangedEventArgs<CustomCheckBox> e)
{
base.OnElementChanged(e);
if (Control == null)
{
var checkBox = new UIView();
SetNativeControl(checkBox);
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == CustomCheckBox.IsCheckedProperty.PropertyName || firstTime)
{
SetNeedsDisplay();
}
}
public override void Draw(CGRect rect)
{
Element.Color.ToUIColor().SetStroke();
if (Element.IsChecked)
{
var checkPath = new UIBezierPath();
checkPath.MoveTo(new CGPoint(1 + .2 * SideLength, 1 + .475 * SideLength));
checkPath.AddLineTo(new CGPoint(1 + .45 * SideLength, 1 + .675 * SideLength));
checkPath.AddLineTo(new CGPoint(1 + .8 * SideLength, 1 + .275 * SideLength));
checkPath.LineWidth = 3f;
checkPath.Stroke();
}
var boxPath = UIBezierPath.FromRoundedRect(
new CGRect(1f, 1f, SideLength, SideLength), UIRectCorner.AllCorners, new CGSize(2,2));
boxPath.LineWidth = 2f;
boxPath.Stroke();
firstTime = false;
}
public override CGSize SizeThatFits(CGSize size)
{
return new CGSize(SideLength + 2, SideLength + 2);
}
}
}

Related

The attribute android:onClick="FabOnClick" crashes app when Floating Action Button clicked

There doesn't appear to be a lot of people using Xamarin for Visual Studio consequently there isn't a lot of information specific to that platform out there.
Having said that, I've been trying to get a Floating Action Button (FAB) to work and it's been quite the exercise. I finally got it to appear and assign it to a variable in the activity with help from the nice folks who use StackOverflow, but cannot get the android:onClick="FabOnClick" call to work. Clicking on the FAB causes the app to crash with the error:
Unhandled Exception:
Java.Lang.IllegalStateException: Could not find method FabOnClick(View) in a parent or ancestor Context for android:onClick attribute defined on view class android.support.design.widget.FloatingActionButton with id 'fab' occurred
This is the code in my activity:
public void FabOnClick(View v)
{
int x = 1;
}
It doesn't really do anything because I'm just trying to capture the click event for now. I set a breakpoint on the int x = 1 line to see when it's is executed. So what am I missing?
* Update *
I updated my activity code based on #Digitalsa1nt's answer below:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Acr.UserDialogs;
using Android.Net;
using System.Net;
using Android.Support.Design.Widget;
using System.Threading.Tasks;
using Android.Views.InputMethods;
using static Android.Views.View;
namespace OML_Android
{
[Activity(Label = "CreateAccount")]
public class CreateAccount : Activity
{
public string result = "";
public EditText aTextboxUsername;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.CreateAccount);
RequestedOrientation = Android.Content.PM.ScreenOrientation.Portrait;
aTextboxUsername = FindViewById<EditText>(Resource.Id.aTextboxUsername);
EditText aTextboxPassword = FindViewById<EditText>(Resource.Id.aTextboxPassword);
EditText aTextboxPassword2 = FindViewById<EditText>(Resource.Id.aTextboxPassword2);
EditText txtEmailAddress = FindViewById<EditText>(Resource.Id.txtEmailAddress);
EditText txtEmailAddress2 = FindViewById<EditText>(Resource.Id.txtEmailAddress2);
EditText txtFirstName = FindViewById<EditText>(Resource.Id.first_name);
EditText txtMI = FindViewById<EditText>(Resource.Id.mi);
EditText txtLastName = FindViewById<EditText>(Resource.Id.last_name);
EditText txtAddress = FindViewById<EditText>(Resource.Id.address);
EditText txtCity = FindViewById<EditText>(Resource.Id.city);
Spinner spnState = FindViewById<Spinner>(Resource.Id.state);
EditText txtZip = FindViewById<EditText>(Resource.Id.zip);
MaskedEditText.MaskedEditText txtPhone = FindViewById<MaskedEditText.MaskedEditText>(Resource.Id.phone);
Spinner spnCompany = FindViewById<Spinner>(Resource.Id.company_spinner);
Spinner spnDept = FindViewById<Spinner>(Resource.Id.department_spinner);
Spinner spnSection = FindViewById<Spinner>(Resource.Id.section_spinner);
Button ButtonSubmit = FindViewById<Button>(Resource.Id.button_submit);
ScrollView sv = FindViewById<ScrollView>(Resource.Id.scrollView1);
ButtonSubmit.SetBackgroundColor(Android.Graphics.Color.YellowGreen);
// Hide the keyboard (also doesn't work)
InputMethodManager board = (InputMethodManager)GetSystemService(Context.InputMethodService);
board.HideSoftInputFromWindow(aTextboxUsername.WindowToken, 0);
// get the floating action button.
FloatingActionButton myFab = FindViewById< FloatingActionButton>(Resource.Id.fab);
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
DataInterfaceWeb.DataInterface myService = new DataInterfaceWeb.DataInterface();
myFab.Click += FabButton_Click(); // <-- get error here
try
{
ConnectivityManager connectivityManager = (ConnectivityManager)GetSystemService(ConnectivityService);
NetworkInfo activeConnection = connectivityManager.ActiveNetworkInfo;
bool isOnline = (activeConnection != null) && activeConnection.IsConnected;
if (!isOnline)
{
showMessage("There is no internet or cell phone connection. Connect to a network or connect to a cellular network.", "ERROR");
}
}
catch (Exception ex)
{
showMessage("Connectivity Manager failed to create a connection due to error: " + ex.Message, "ERROR");
};
// Create your application here
ButtonSubmit.Click += async (sender, e) =>
{
try
{
result = myService.CheckForUser(Master.username, Master.password, aTextboxUsername.Text);
if (result.ToUpper() == "Y")
{
await showMessage("Username " + aTextboxUsername.Text + " is already in use. Please choose another", "ERROR");
// aTextboxUsername.SetSelectAllOnFocus(true);
aTextboxUsername.RequestFocus();
View insideView = FindViewById<EditText>(Resource.Id.aTextboxUsername);
sv.ScrollTo(0, (int)insideView.GetY());
aTextboxUsername.SelectAll();
}
}
catch (Exception ex)
{
showMessage("Account creation attempt failed due to error: " + ex.Message, "ERROR");
}
};
}
public async Task showMessage(string message, string messageType)
{
var result = await UserDialogs.Instance.ConfirmAsync(new ConfirmConfig
{
Message = messageType + System.Environment.NewLine + message,
OkText = "Ok",
});
}
public void FabButton_Click()
{
int x = 1;
}
}
}
The error I get now is:
Cannot implicitly convert 'void' to 'SystemEventHandler' on the line myFab.Click += FabButton_Click();.
#Digitalsa1nt did point me in the right direction. Instead of
fabButton.Click += FabButton_Click;
I just wired up an event, as the error suggested (duh):
myFab.Click += (sender, e) =>
{
FabButton_Click();
};
It now works as I would expect.
So I'm making a couple of assumptions in this answer. Firstly that you are working with a Xamarin.Native project and not a Xamarin.Forms project.
Secondly I am assuming you are using the FloatingActionButton from one of the support libraries such as: Android.Support.Design.Widget (base / V4 / V7).
Once you've defined your FAB within the AXML Layout page:
<android.support.design.widget.FloatingActionButton
app:backgroundTint="#color/colourPrimary"
android:id="#+id/fabButton"
android:src="#drawable/image"
app:fabSize="normal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:elevation="16dp"
android:translationZ="12dp"
app:rippleColor="#ffa9a9a9" />
You can get it from within your activity as such:
using Android.Support.Design.Widget;
// declare variable
private FloatingActionButton fabButton;
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
// call base
base.OnCreateView(inflater, container, savedInstanceState);
// inflate our view
var view = inflater.Inflate(Resource.Layout.MainTabWishlistPage, container, false);
// get our instance of the button using the resource ID.
fabButton = view.FindViewById<FloatingActionButton>(Resource.Id.fabButton);
// assign to click event
fabButton.Click += FabButton_Click;
}
private void FabButton_Click(object sender, EventArgs e)
{
int x = 1;
}
The above example is based on it being a fragment rather than an activity, but the methodology is the same.
Official Git Repo:
Xamarin/monodroid-samples - Floating Action Button Basic
Random online guide:
android-material-design-floating-action
In case this is a Xamarin.Forms project, look into James Montemagno's library (p.s one of the developers that works on Xamarin and creates tons of libraries to help make your life easier, definitely look through his other repos.)
jamesmontemagno/FloatingActionButton-for-Xamarin.Android

Show ProgressBar programattically while user logging on

I found this class at Centering ProgressBar Programmatically in Android which would display a progressbar programmatically, problem is it's an Xamarin Android Studio example and I'm trying to convert it to Xamarin for Visual Studio 2017. This is the code that I have successfully converted with those lines that I can't seem to find a Xamarin VS 2017 equivalent for.
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
namespace OML_Android
{
class ProgressBarHandler
{
private ProgressBar mProgressBar;
private Context mContext;
public ProgressBarHandler(Context context)
{
mContext = context;
ViewGroup layout = (ViewGroup)((Activity)context).FindViewById(Android.Resource.Id.Content).RootView;
mProgressBar = new ProgressBar(context, null, Android.Resource.Attribute.ProgressBarStyleLarge);
// there is no setIndeterminate method for progressbar
mProgressBar.setIndeterminate(true);
// I cannot find an equivilent for LayoutParams
RelativeLayout.LayoutParams params = RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MatchParent, RelativeLayout.LayoutParams.MatchParent);
RelativeLayout rl = new RelativeLayout(context);
// No equivalent for Gravity.CENTER
rl.SetGravity(Gravity.CENTER);
rl.AddView(mProgressBar);
layout.AddView(rl, params);
hide();
}
public void show()
{
mProgressBar.Visibility = Android.Views.ViewStates.Visible;
}
public void hide()
{
mProgressBar.Visibility = Android.Views.ViewStates.Invisible;
}
}
}
Once I have this converted and working I want it to overlay my logon view until the view finishes processing.
I help you transform Java code to C#, there is running GIF.
There is code.
class ProgressBarHandler
{
private ProgressBar mProgressBar;
private Context mContext;
public ProgressBarHandler(Context context)
{
mContext = context;
ViewGroup layout = (ViewGroup)((Activity)context).FindViewById(Android.Resource.Id.Content).RootView;
mProgressBar = new ProgressBar(context, null, Android.Resource.Attribute.ProgressBarStyleLarge);
// there is no setIndeterminate method for progressbar
// mProgressBar.SetIndeterminate(true);
mProgressBar.Indeterminate = true;
// I cannot find an equivilent for LayoutParams
RelativeLayout.LayoutParams layoutparams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MatchParent, RelativeLayout.LayoutParams.MatchParent);
RelativeLayout rl = new RelativeLayout(context);
// No equivalent for Gravity.CENTER
rl.SetGravity(GravityFlags.Center );
rl.AddView(mProgressBar);
layout.AddView(rl, layoutparams);
hide();
}
public void show()
{
mProgressBar.Visibility = Android.Views.ViewStates.Visible;
}
public void hide()
{
mProgressBar.Visibility = Android.Views.ViewStates.Invisible;
}
}
You can use it directly like following code in Activity.
var progress= new ProgressBarHandler(this);
progress.show();

xamarin.forms webview.focused event raised on Android, but not on iOS

I'm using a Xamarin.Forms grid application to show a couple of html elements as WebViews in the cells of the grid CardGrid:
private async void CreateCardView()
{
CardGrid.Children.Clear();
// idx over all count elements of html snippets
for (idx = 0; idx < count; idx++)
{
string html = AuthoringCard(idx);
RenderingCard(html, idx);
}
}
AuthoringCard() creates the html code snippet.
RenderingCard() creates the WebView inside the grid cell.
private void RenderingCard(string htmlCard, int index)
{
int CardWidth = 300;
int CardHeight = 150;
int CardNoHorizontally = 3;
WebView uiCard = new WebView();
uiCard.HeightRequest = CardHeight - 5;
uiCard.WidthRequest= CardWidth - 5;
uiCard.VerticalOptions = LayoutOptions.Start;
uiCard.HorizontalOptions = LayoutOptions.Center;
uiCard.Margin = new Thickness(0);
uiCard.AutomationId = index.ToString();
uiCard.Focused += Card_Tapped;
uiCard.InputTransparent = false;
var htmlSource1 = new HtmlWebViewSource
{
Html = htmlCard,
};
uiCard.Source = htmlSource1;
CardGrid.Children.Add(uiCard);
int row = (int)Math.Floor((double)(index / CardNoHorizontally));
int column = index - (row * CardNoHorizontally);
Grid.SetRow(uiCard, row);
Grid.SetColumn(uiCard, column);
}
I want to catch the Focused event, when the user it tapping on the card (WebView) and using the AutomationId to get the index of the card (html code snippet):
private void Card_Tapped(object sender, EventArgs e)
{
WebView card = (WebView)sender;
int index = Convert.ToInt16(card.AutomationId));
}
This works fine with Android. Under iOS the event is never raised. Any idea for a solution?
Cause:
the property Focus in Forms correspond method that we called becomeFirstResponder in native iOS platform.Unfortunately,UIWebView and WKwebview do not support the method becomeFirstResponder.This method is only available in some 'input-controls' Such as UITextField and UITextView(Entry in Forms).So even if you set the event on a webview.It will not work in iOS.
Workaround:
You can add a TapGestureRecognizer on the webview.And you have to implement it by using CustomRenderer.Because it will create conflict if you add TapGestureRecognizer in forms.
Refer to the following code.
in Forms
public MainPage()
{
if (Device.RuntimePlatform == "iOS")
{
MessagingCenter.Subscribe<Object,string>(this,"webview_click", (sender,arg)=> {
// int index = Convert.ToInt16(arg));
});
}
}
in iOS
using System;
using Foundation;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using xxx;
using xxx.iOS;
using ObjCRuntime;
[assembly:ExportRenderer(typeof(WebView),typeof(MyWebViewRenderer))]
namespace xxx.iOS
{
public class MyWebViewRenderer : WebViewRenderer, IUIGestureRecognizerDelegate
{
public bool isFirstLoad = true;
public MyWebViewRenderer()
{
}
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
if (e != null)
{
UITapGestureRecognizer tap = new UITapGestureRecognizer(this, new Selector("Tap_Handle:"));
tap.WeakDelegate = this;
this.AddGestureRecognizer(tap);
}
}
[Export("gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:")]
public bool ShouldRecognizeSimultaneously(UIGestureRecognizer gestureRecognizer, UIGestureRecognizer otherGestureRecognizer)
{
return true;
}
[Export("Tap_Handle:")]
void Tap_Handle(UITapGestureRecognizer tap)
{
if(isFirstLoad)
{
isFirstLoad = false;
MessagingCenter.Send<Object,string>(this, "webview_click",Element.AutomationId);
}
}
}
}

Xamarin iOS Hide cancel button from Search Bar

I wanted to hide 'cancel' button in my iOS search bar. I have implemented the following custom renderer code but it seems not to to work. If anyone knows solution , please share.
public class iOSSearchBar : SearchBarRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<SearchBar> args)
{
base.OnElementChanged(args);
UISearchBar bar = (UISearchBar)this.Control;
bar.AutocapitalizationType = UITextAutocapitalizationType.None;
bar.AutocorrectionType = UITextAutocorrectionType.No;
//bar.BarStyle = UIBarStyle.Default;
//bar.BarTintColor = UIColor.LightGray;
//bar.KeyboardType = UIKeyboardType.ASCIICapable;
bar.SearchBarStyle = UISearchBarStyle.Minimal;
bar.SetShowsCancelButton(false, false);
bar.ShowsCancelButton = false;
}
}
Thanks in advance
This worked for me.
https://gist.github.com/xleon/9f94a8482162460ceaf9
using System;
using Xamarin.Forms.Platform.iOS;
using Xamarin.Forms;
using UIKit;
using System.Diagnostics;
[assembly: ExportRenderer(typeof(SearchBar), typeof(Namespace.iOS.Renderers.ExtendedSearchBarRenderer))]
namespace Namespace.iOS.Renderers
{
public class ExtendedSearchBarRenderer : SearchBarRenderer
{
protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == "Text")
{
Control.ShowsCancelButton = false;
}
}
}
}
Write code to hide cancel button in layoutsubviews method.
public override void LayoutSubviews()
{
base.LayoutSubviews();
UISearchBar bar = (UISearchBar)this.Control;
bar.ShowsCancelButton = false;
}
Following is also working or me, no need to subclass searcher:
SearchBar.TextChanged += delegate
{
SearchBar.ShowsCancelButton = false;
};
I think i managed to remove it manually with:
protected override void OnElementChanged(ElementChangedEventArgs<SearchBar> e)
{
base.OnElementChanged(e);
if (Control != null)
{
Control.Subviews[0].Subviews[0].RemoveFromSuperview();
}
}
I spend some more time searching for this, so adding here in case someone else wants to do both.
In case you also need to remove the X button as well, I found the solution in this comment

How to fix rotation for WebView custom renderer for iOS using Xamarin.Forms?

I have created a custom renderer for a WebView in my Xamarin.Forms project. The WebView works great on Android. Unfortunately, on iOS, when the device is rotated, the webpage (any webpage) does not correctly adjust to the new dimensions of the WebView. If I use the built in WebView for Forms, the pages correctly resize on rotate.
What am I doing wrong with my custom renderer?
Below is a stripped down version of my custom renderer (the issue still occurs):
using Xamarin.Forms.Platform.iOS;
using Xamarin.Forms;
using UIKit;
using Foundation;
[assembly: ExportRenderer(typeof(WebView), typeof(MyProject.iOS.WebViewRenderer))]
namespace MyProject.iOS {
public class WebViewRenderer : ViewRenderer<WebView, UIWebView> {
protected override void OnElementChanged(ElementChangedEventArgs<WebView> e) {
if (Control == null) {
var webView = new UIWebView(Frame);
webView.AutoresizingMask = UIViewAutoresizing.All;
SetNativeControl(webView);
webView.LoadRequest(new NSUrlRequest(new NSUrl("http://cnn.com")));
}
}
}
}
To fix the issue, add the following to the custom renderer:
public override SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint) {
return new SizeRequest(Size.Zero, Size.Zero);
}
To fix the rotate problem you need to use the NativeView.Bounds when you create the UIWebView.
[assembly: ExportRenderer(typeof(CustomWebView), typeof(CustomWebViewRenderer))]
namespaceMobile.App.iOS
{
public class CustomWebViewRenderer : ViewRenderer<CustomWebView, UIWebView>
{
protected override void OnElementChanged(ElementChangedEventArgs<CustomWebView> e)
{
base.OnElementChanged(e);
if (Control == null)
{
var webView = new UIWebView(NativeView.Bounds);
webView.ShouldStartLoad += HandleShouldStartLoad;
webView.AutoresizingMask = UIViewAutoresizing.All;
webView.ScalesPageToFit = true;
SetNativeControl(webView);
webView.LoadRequest(new NSUrlRequest(new NSUrl(Element.Url)));
}
}
public override SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
{
return new SizeRequest(Size.Zero, Size.Zero);
}
}
}

Resources