Using VS 2017 Xamarin.Forms PCL iOS--how do I control the image visibility using a toggle switch? - ios

I am new to Xamarin.Forms. My project is a cross platform PCL. Single Page. Built using VS 2017. This question pertains to the iOS platform.
Background: App layout has 13 images all with the IsVisible=False. Each image has a toggle switch.
Objective: To have the user be able to control the image visibility through the toggle switch. When the switch is toggled the image will become visible.
Code sample below. Any insight would be greatly appreciated. Thank you.
XAML
<AbsoluteLayout>
<Image x:Name="Sheep_Image" Source="1-Sheep.png" Aspect="AspectFit" AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds=".15,.87,.5,.1" IsVisible="False"/>
<Switch x:Name="Switch" Toggled="Switch_Toggled"/>
</AbsoluteLayout>
xaml.cs
private void Switch_Toggled(object sender, ToggledEventArgs e){
var toggle = sender as ToggleSwitch;
Sheep_Image.IsVisible = toggle.IsOn;
}

The property for Toggle is called "IsToggled"

You need to subscribe an event handler to each toggle:
void Handle_Toggled(object sender, Xamarin.Forms.ToggledEventArgs e)
{
Sheep_Image.IsVisible = e.Value;
}
In XAML, you need this:
<Switch Toggled="Handle_Toggled" />

This should work too:
<Image x:Name="Image"></Image>
<Switch IsToggled="{Binding Source={x:Reference Image}, Path=IsVisible, Mode=TwoWay}" HorizontalOptions="Start"></Switch>

As #Dbl,#lowry0031, #BraveHeart said, I just make a summary and provide more details.
Solution 1 : Event Handle
private void Switch_Toggled(object sender, ToggledEventArgs e){
Sheep_Image.IsVisible = (sender as Switch).IsToggled;
//Or
//Sheep_Image.IsVisible = e.Value;
}
Solution 2 : Binding
<Image x:Name="Sheep_Image" Source="Icon-Small.png" Aspect="AspectFit" AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds=".15,.87,.5,.1" IsVisible="False"/>
<Switch x:Name="Switch" IsToggled="{Binding Source={x:Reference Sheep_Image}, Path=IsVisible, Mode=TwoWay}"/>
PS: Make sure the image is available in your Resource folder.
Test

Related

Xamarin.Forms on iOS 11.1.2: Webview loads a bigger font

I'm using Xamarin.Forms to load an internet's webpage (requirements of the client, please don't judge me), the problem is that in iOS the webpage appears to be bigger that it is.
I don't have any custom render on iOS.
Here is the website loaded on safari on a iPhone 6 iOS 11.1.2
And here is loaded on the webview
MainPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:Juppie"
x:Class="Juppie.MainPage">
<Grid>
<WebView x:Name="Navegador" Source="http://empleosapp.caonainteractive.com/"
WidthRequest="1000" HeightRequest="1000" IsVisible="{Binding Path=HayInternet}" ></WebView>
<ActivityIndicator IsRunning="{Binding Path=Navegando}" IsVisible="{Binding Path=Navegando}"
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand"
RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent,
Property=Height,
Factor=0.33}"
RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent,
Property=Height,
Factor=0.33}"/>
</Grid>
</ContentPage>
MainPage.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Plugin.Connectivity;
using System.ComponentModel;
namespace Juppie
{
public partial class MainPage : ContentPage, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public MainPage()
{
InitializeComponent();
Navegador.Navigating += Navegador_Navigating;
Navegador.Navigated += (sender, e) => { Navegando = false; };
HayInternet = true;
BindingContext = this;
}
bool hayInternet;
public bool HayInternet
{
get
{
return hayInternet;
}
set
{
hayInternet = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("HayInternet"));
EvaluarInternet();
}
}
bool navegando;
public bool Navegando
{
get
{
return navegando;
}
set
{
navegando = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Navegando"));
}
}
public async void EvaluarInternet(){
if (!HayInternet)
{
await DisplayAlert("Aviso","Se requiere conexion a internet para emplear esta aplicacion", "OK");
}
}
protected override void OnAppearing()
{
HayInternet = CrossConnectivity.IsSupported && CrossConnectivity.Current.IsConnected;
CrossConnectivity.Current.ConnectivityChanged += (sender, args) =>
{
HayInternet = args.IsConnected;
};
base.OnAppearing();
}
protected override bool OnBackButtonPressed()
{
if (Navegador.CanGoBack)
{
Navegador.GoBack();
return false;
}
return base.OnBackButtonPressed();
}
void Navegador_Navigating(object sender, WebNavigatingEventArgs e)
{
Navegando = true;
if (e.Url.Contains("/banner"))
{
e.Cancel = true;
var uri = new Uri(e.Url.Replace("/banner", ""));
Device.OpenUri(uri);
}
}
}
}
I tried with a custom render and set the scalePageToFit = false, without success.
If anyone knows how can I fix this, please let me know.
Xaml: - VerticalOptions="FillAndExpand" seems to fill the HeightRequest and WidthRequest property specification requirements for the WebView to render in a StackLayout - in a Grid it seems to render anyway:
<Grid>
<WebView x:Name="webView"
VerticalOptions="FillAndExpand"
Source="https://www.xamarin.com/"/>
</Grid>
Renderer, ScalesPageToFit is false by default (at least in the simulator with iPhone SE 11.2)
[assembly: ExportRenderer(typeof(WebView), typeof(MyWebViewRenderer))]
namespace MyNamespace.iOS
{
public class MyWebViewRenderer : WebViewRenderer
{
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
if (NativeView != null && e.NewElement != null)
{
var webView = ((UIWebView)NativeView);
webView.ScalesPageToFit = true;
}
}
}
}
The screenshots below are from the simulator with iPhone SE.
ScalesPageToFit = true:
ScalesPageToFit = false:
Tested on my iPhone 6 and the app was showing the same size of font as Safari.
I also tested with larger system font in the font size in the app and it was not affected with the app font size.
But I did notice that when the activity indicator was running, my font size became smaller and it turned normal after the activity indicator disappear.
Maybe the font size issue was cause by the side effect of any additional stuff like a Nuget packages or Activity indicator?
You could try to use a new empty form and load only the Webview to compare the differences.
By the way, your app appearance is very alike with iPhone with turned on Display Zoom function.
Before turn on Display Zoom:
After turned on Display Zoom:
Is it possible that the sizing is overwritten by the accessability-settings from the iPhone?
See Settings-App -> General -> Accessability -> Bigger Text
(freely translated from german, actual menu entries may be named different)
I have faced the same issue.
In Xamarin.Forms App resolution is based on the Launch screen. If you are using Assets (LaunchImage) for Launch screen. Then your app resolution is set as per LaunchImage.
The best solution is: use storyboard (LaunchScreen.storyboard) or XIB for Launch screen. This improves your App UI. like font size and App resolution

React-Native webview onScroll Listener

I've been checking on the react-native docs but there doesn't seem to be any onScroll listener for the WebView component. Is there a work-around to this? The idea is to hide UI components when webview is scrolling and show them when the user stops scrolling or scrolls down.
I haven't done this myself but reviewing the docs, WebView has an onMessage prop that takes a function. The WebView invokes this function using window.postMessage.
I believe this is the recommended way of passing info from a WebView back to the parent app.
Update:
For WebView from react-native-webview, should use window.ReactNativeWebView.postMessage instead of window.postMessage. See react-native-webvie#communicating-between-js-and-native for details.
Old answer:
use injectedJavaScript :
(function(){
var callback=function(direction){
window.postMessage('scroll-'+ direction)}; // here you can also use json string
var initTop=document.body.scrollTop;
window.addEventListener('scroll',function(){
var currTop = document.body.scrollTop;
var dist = currTop-initTop;
if(dist === 0)
return;
callback(dist>0 ? 'down' : 'up');
initTop = currTop;
},false)
})(window);
Wrap the above script into a string jsStr, and then:
<WebView
source={{uri: YOUR_URL }}
injectedJavaScript={jsStr}
onMessage={(event) => {
console.log('scroll message', event.nativeEvent.data)
// then do something with the scroll message
}} />

how to use native views in Nativescript

I'm using NativeScript with Angular2 and typescript.
Trying to add native elements this way :
html :
<StackLayout #camview class="camView">
</StackLayout>
typescript :
#ViewChild("camview") camview: ElementRef;
constructor()
{
}
ngOnInit()
{
alert("AA");
var label = new UILabel(CGRectMake(0, 0, 200, 200));
label.text = "Hello World again";
label.textColor = UIColor.whiteColor();
this.camview.nativeElement.addSubview(label);
alert("BB");
}
I'm not sure wheter an elementRef.nativeElement.addSubView is supposed to work but nothing appear on the resulting screen.
What's even more surprising is how alert AA works but not alert BB, like if code interpretation was interupted between them
I don't have any errors or complains, the app continues to run and I'm able to navigate away and back to this page.
I tried to force an error by misspelling UILabel to UILabeel, but it does not produce an error as I would have expected.. its just the same behaviour.
Am I supposed to tell nativescript these are native elements/mehods somehow?
After a couple of hours, I realized how to do it.
XML:
<StackLayout #stackLayout></StackLayout>
TS:
#ViewChild('stackLayout') stackLayout: ElementRef<StackLayout>;
addButton() {
this.androidButton = new android.widget.Button(applicationModule.android.context);
this.androidButton.setText("Some button text");
this.stackLayout.nativeElement.nativeView.addView(this.androidButton);
}

Xamarin Forms FFImageLoading Image not showing

I am trying to use FFImageLoading in one of our Xamarin Forms Projects but I am having some weird issues.
When I try to put Sources="anyvalidimageurl" on the XAML, I get this error:
Invalid XAML: Value cannot be null. Parameter name: 'obj'
This is the XAML:
<ffimageloading:CachedImage HorizontalOptions="Center"
WidthRequest="300"
HeightRequest="300"
DownsampleToViewSize="true"
Source="http://myimage.com/image.png"
x:Name="imgImage">
</ffimageloading:CachedImage>
I tried to load the image through code, but no image is shown on iOS.
You need to add this to your AppDelegate.cs
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
FFImageLoading.Forms.Touch.CachedImageRenderer.Init();
var dummy = new FFImageLoading.Forms.Touch.CachedImageRenderer();
global::Xamarin.Forms.Forms.Init();
LoadApplication(new App());
return base.FinishedLaunching(app, options);
}
For more information see https://github.com/luberda-molinet/FFImageLoading/issues/55
Did you miss to include CachedImageRenderer.Init(); in AppDelegate.cs

TextInputLayout hint issue when handling FocusChange event

My app has a couple of EditTexts with a TextInputLayout wrapped around them. This works fine in most cases, but when I attach a handler to the FocusChange event of the EditText, the hint fails to animate.
I found this issue on the android forum, but he uses the OnFocusChangeListener. Proxying the call should not be necessary with events, right?
Any ideas on this issue? Is it a bug in the Xamarin android design support NuGet package?
Thanks in advance
Layout code:
<android.support.design.widget.TextInputLayout
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content">
<EditText
android:id="#+id/txtProductCode"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="1"
android:inputType="textCapCharacters|textNoSuggestions"
android:hint="Artikelcode" />
</android.support.design.widget.TextInputLayout>
Fragment code:
public override void OnStart()
{
base.OnStart();
txtProductCode.FocusChange += txtProductCode_FocusChange;
// ...
}
void txtProductCode_FocusChange(object sender, View.FocusChangeEventArgs e)
{
if (!e.HasFocus)
txtDescription.Text = GetProductDescription();
}
From this post this i found my solution for the problem.
As stated in the post it's kind of a workaround but i think this should work in the new design library version 22.2.1 but for me the problem still persists.
Here is my code based on the mentioned post:
final View.OnFocusChangeListener userNameEtFocusListener = userNameEt.getOnFocusChangeListener();
userNameEt.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
userNameEtFocusListener.onFocusChange(v, hasFocus);
if (!hasFocus){
userInfoValidator.checkUserNameAvailable(userNameEt.getText().toString());
}
}
});

Resources