I have an entry for Password and an ImageButton.
On click of image Button, it should change to a different ImageButton.
For the first time when cursor is placed and keyboard appears, on selection of the image button, screen flickers.
I am using IsVisible property, setting the visibility to false and true when required, still it's flickering.
It's a popup page. Image size i downloaded using material icons and there i selected iOS and Android, for both, size is 24.
The idea is entry is of password, so by default IsPassword will be true. Once user selects the image, image should get changed and it should show me the password and again if i select the changed image, it should change to the previous one and hide the password.
.xaml
<StackLayout Orientation="Vertical">
<Label Text="Current Password"/>
<Entry x:Name="CurrentPasswordEntryText" Placeholder="Current Password" IsPassword="True"/>
<ImageButton x:Name="CurrentPasswordImage1" Source="baseline_visibility_off_black_24" IsVisible="true" Clicked="ImageButton1_Clicked"/>
<ImageButton x:Name="CurrentPasswordImage2" Source="baseline_visibility_black_24" IsVisible="false" Clicked="ImageButton2_Clicked"/>
</StackLayout>
.cs file
void ImageButton1_Clicked(System.Object sender, System.EventArgs e)
{
CurrentPasswordEntryText.IsPassword = false;
CurrentPasswordImage1.IsVisible = false;
CurrentPasswordImage2.IsVisible = true;
}
void ImageButton2_Clicked(System.Object sender, System.EventArgs e)
{
CurrentPasswordEntryText.IsPassword = true;
CurrentPasswordImage1.IsVisible = true;
CurrentPasswordImage2.IsVisible = false;
}
Try to use BatchBegin / BatchCommit methods:
.xaml
<StackLayout x:Name="CurrentPasswordLayout" Orientation="Vertical">
<Label Text="Current Password"/>
<Entry x:Name="CurrentPasswordEntryText" Placeholder="Current Password" IsPassword="True"/>
<ImageButton x:Name="CurrentPasswordImage1" Source="baseline_visibility_off_black_24" IsVisible="true" Clicked="ImageButton1_Clicked"/>
<ImageButton x:Name="CurrentPasswordImage2" Source="baseline_visibility_black_24" IsVisible="false" Clicked="ImageButton2_Clicked"/>
</StackLayout>
.cs
void ImageButton1_Clicked(System.Object sender, System.EventArgs e)
{
CurrentPasswordLayout.BatchBegin();
try
{
CurrentPasswordEntryText.IsPassword = false;
CurrentPasswordImage1.IsVisible = false;
CurrentPasswordImage2.IsVisible = true;
}
finally
{
CurrentPasswordLayout.BatchCommit();
}
}
void ImageButton2_Clicked(System.Object sender, System.EventArgs e)
{
CurrentPasswordLayout.BatchBegin();
try
{
CurrentPasswordEntryText.IsPassword = true;
CurrentPasswordImage1.IsVisible = true;
CurrentPasswordImage2.IsVisible = false;
}
finally
{
CurrentPasswordLayout.BatchCommit();
}
}
I am new in Xamarin, so forgive me if I am wrong. Seems like when the Image Source (or ImageButton Source, I presume) is changing, the entire StackLayout area is refreshed, so it is flickering. Try to put only one Image (or ImageButton) in one StackLayout, so the flickering only occurs inside the StackLayout which is unnoticeable because it is changing the image.
Related
I am trying to implement a keypad UI. In the keypad, the +(plus) and 0(zero) options are placed on a single image icon. So I need to show 0 on UI for single tap and for double tap I need to show the + on UI.
My Code
<Image
Grid.Column="1"
Source="ic_zero_xx.png"
Style="{StaticResource KeypadImageStyle}">
<Image.GestureRecognizers>
<TapGestureRecognizer
Tapped="ZeroTapped"
NumberOfTapsRequired="1">
</TapGestureRecognizer>
</Image.GestureRecognizers>
</Image>
private void ZeroTapped(object sender, EventArgs e)
{
phonenumber_label.Text = "0";
}
How I can mention 2 different taps at the same time on an image?
We can add two TapGestureRecognizer on that image, one for single tap and the other for double tap .
xaml
<Image >
<Image.GestureRecognizers>
<TapGestureRecognizer Tapped="TapGestureRecognizer_Single" NumberOfTapsRequired="1"/>
<TapGestureRecognizer Tapped="TapGestureRecognizer_Double" NumberOfTapsRequired="2"/>
</Image.GestureRecognizers>
</Image>
Code behind
private void TapGestureRecognizer_Single(object sender, EventArgs e)
{
label.Text = "0";
}
private void TapGestureRecognizer_Double(object sender, EventArgs e)
{
label.Text = "+";
}
I think you can use a timer If user tap twice within 150ms then it is a double tap.
int Tapped=0;
private void ZeroTapped(object sender,EventArgs e)
{
if(Tapped==0)
{
Device.StartTime(TimeSpan.FromMillSeconds(150),()=>
{
if(Tapped=1)
{
//1 tap.
}
else
{
//double tap.
}
Tapped=0;
return false;
}
}
else
{
Tapped++;
}
}
We are working on show/ hide password toggle functionality in Xamarin traditional approach. What is the best place to implement it? Is it in Xamarin.iOS &. Droid or in Xamarin.Core?
If it is in Xamarin.Core, can you let us know the process. Is it by value convertors?
Thanks in advance.
Recently, Microsoft MVP Charlin, wrote an article showing how to do this using Event Triggers in the Xamarin Forms code:
She was able to do it simply using a new ShowPasswordTriggerAction of type TriggerAction that implemented INotifyPropertyChanged.
Therein, she created a HidePassword bool property that Invoke a PropertyChanged event which changes the Source of the Icon image:
protected override void Invoke(ImageButton sender)
{
sender.Source = HidePassword ? ShowIcon : HideIcon;
HidePassword = !HidePassword;
}
Then place the Entry and ImageButton inside a layout (like a Frame or horizontally oriented LinearLayout) as shown:
<Entry Placeholder="Password"
IsPassword="{Binding Source={x:Reference ShowPasswordActualTrigger}, Path=HidePassword}"/>
<ImageButton VerticalOptions="Center"
HeightRequest="20"
HorizontalOptions="End"
Source="ic_eye_hide">
<ImageButton.Triggers>
<EventTrigger Event="Clicked">
<local:ShowPasswordTriggerAction ShowIcon="ic_eye"
HideIcon="ic_eye_hide"
x:Name="ShowPasswordActualTrigger"/>
</EventTrigger>
</ImageButton.Triggers>
</ImageButton>
We always use custom controls to show/hide password while entering the password using effects.
Android:
Create the control manually in ‘OnDrawableTouchListener’ method where, we are adding the ShowPass and HidePass icons to the entry control, changing them on the basis of user touch action and attaching it on effect invocation which will be fired when the effect is added to the control.
public class OnDrawableTouchListener : Java.Lang.Object, Android.Views.View.IOnTouchListener
{
public bool OnTouch(Android.Views.View v, MotionEvent e)
{
if (v is EditText && e.Action == MotionEventActions.Up)
{
EditText editText = (EditText)v;
if (e.RawX >= (editText.Right - editText.GetCompoundDrawables()[2].Bounds.Width()))
{
if (editText.TransformationMethod == null)
{
editText.TransformationMethod = PasswordTransformationMethod.Instance;
editText.SetCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, Resource.Drawable.ShowPass, 0);
}
else
{
editText.TransformationMethod = null;
editText.SetCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, Resource.Drawable.HidePass, 0);
}
return true;
}
}
return false;
}
}
Result:
IOS:
Create the control manually in 'ConfigureControl' method where we are adding the ShowPass and HidePassicons to the entry control, changing them on the basis of user touch action; and attaching it on effect invocation which will be fired when the effect will be added to the control.
private void ConfigureControl()
{
if (Control != null)
{
UITextField vUpdatedEntry = (UITextField)Control;
var buttonRect = UIButton.FromType(UIButtonType.Custom);
buttonRect.SetImage(new UIImage("ShowPass"), UIControlState.Normal);
buttonRect.TouchUpInside += (object sender, EventArgs e1) =>
{
if (vUpdatedEntry.SecureTextEntry)
{
vUpdatedEntry.SecureTextEntry = false;
buttonRect.SetImage(new UIImage("HidePass"), UIControlState.Normal);
}
else
{
vUpdatedEntry.SecureTextEntry = true;
buttonRect.SetImage(new UIImage("ShowPass"), UIControlState.Normal);
}
};
vUpdatedEntry.ShouldChangeCharacters += (textField, range, replacementString) =>
{
string text = vUpdatedEntry.Text;
var result = text.Substring(0, (int)range.Location) + replacementString + text.Substring((int)range.Location + (int)range.Length);
vUpdatedEntry.Text = result;
return false;
};
buttonRect.Frame = new CoreGraphics.CGRect(10.0f, 0.0f, 15.0f, 15.0f);
buttonRect.ContentMode = UIViewContentMode.Right;
UIView paddingViewRight = new UIView(new System.Drawing.RectangleF(5.0f, -5.0f, 30.0f, 18.0f));
paddingViewRight.Add(buttonRect);
paddingViewRight.ContentMode = UIViewContentMode.BottomRight;
vUpdatedEntry.LeftView = paddingViewRight;
vUpdatedEntry.LeftViewMode = UITextFieldViewMode.Always;
Control.Layer.CornerRadius = 4;
Control.Layer.BorderColor = new CoreGraphics.CGColor(255, 255, 255);
Control.Layer.MasksToBounds = true;
vUpdatedEntry.TextAlignment = UITextAlignment.Left;
}
}
Result:
For more details, please refer to the article below.
https://www.c-sharpcorner.com/article/xamarin-forms-tip-implement-show-hide-password-using-effects/
You could download the source file from GitHub for reference.
https://github.com/techierathore/ShowHidePassEx.git
You can use the PhantomLib library to do this. It has a control which allows you to have a show/hide icon for the password with examples. Just install the nuget. https://github.com/OSTUSA/PhantomLib
Your UI codes like this having a entry and image button
source to named accroding to your ui
<Frame CornerRadius="30" Background="white" Padding="0" HeightRequest="43" Margin="0,17,0,0">
<StackLayout Orientation="Horizontal">
<Entry x:Name="eLoginPassword"
Margin="15,-10,0,-15"
HorizontalOptions="FillAndExpand"
IsPassword="True"
Placeholder="Password"/>
<ImageButton
x:Name="ibToggleLoginPass"
Clicked="IbToggleLoginPass"
Source="eyeclosed"
Margin="0,0,13,0"
BackgroundColor="White"
HorizontalOptions="End"
/>
</StackLayout>
</Frame>
in C# code
// IbToggleLoginPass your defined method in xaml
//"eye" is drawable name for open eye and "eyeclosed" is drawable name for closed eye
private void IbToggleLoginPass(object sender, EventArgs e)
{
bool isPass = eLoginPassword.IsPassword;
ibToggleLoginPa`enter code here`ss.Source = isPass ? "eye" : "eyeclosed";
eLoginPassword.IsPassword = !isPass;
}
Trigger and a command
The trigger changes the icon, and the command changes the entry.
View xaml
<Grid>
<Entry Placeholder="Password" Text="{Binding Password, Mode=TwoWay}" IsPassword="{Binding IsPassword}" />
<ImageButton BackgroundColor="Transparent" WidthRequest="24" VerticalOptions="Center" TranslationY="-5" TranslationX="-10" HorizontalOptions="End"
Command="{Binding ToggleIsPassword}"
Source="eye" >
<ImageButton.Triggers>
<DataTrigger TargetType="ImageButton" Binding="{Binding IsPassword}" Value="True" >
<Setter Property="Source" Value="eye-slash" />
</DataTrigger>
</ImageButton.Triggers>
</ImageButton>
</Grid>
And in my ViewModel
private bool _IsPassword = true;
public bool IsPassword
{
get
{
return _IsPassword;
}
set
{
_IsPassword = value;
RaisePropertyChanged(() => IsPassword);
}
}
public ICommand ToggleIsPassword => new Command(() => IsPassword = !IsPassword);
We've got a ScrollView which I've set with a VerticalOptions of "End", so that when we add content to it at runtime it 'grows' from the bottom.
We're scrolling to the end when adding content, with animation. This looks good when the ScrollView is full and is actually scrolling.
However, when content is added to the ScrollView, the new content appears immediately with no animation.
Any thoughts on how to animate the growth of the ScrollView as the new content is added? Ideally I'd like it to slide up, like the animated scroll when it's full.
We're using a RepeaterView as the content of the ScrollView, if that's relevant.
Relevant existing code below (we're using Forms with MvvmCross - hence an MVVM pattern):
ViewModel
private async Task NextClick()
{
var claimFlowQuestion = await GetClaimFlowQuestion(_currentIndexQuestion);
Questions.Add(ClaimFlowExtendFromClaimFlow(claimFlowQuestion));
// Trigger PropertyChanged so the Repeater updates
await RaisePropertyChanged(nameof(Questions));
// Trigger the QuestionAdded event so the ScrollView can scroll to the bottom (initiated in the xaml.cs code behind)
QuestionAdded?.Invoke(this, new EventArgs());
}
XAML
<ScrollView Grid.Row="1" x:Name="QuestionScrollView">
<StackLayout VerticalOptions="End"
Padding ="10,0,10,0"
IsVisible="{Binding Busy, Converter={StaticResource InvertedBooleanConvertor}}}">
<controls:RepeaterView
x:Name="QuestionRepeater"
Margin ="10"
AutomationId="IdQuestions"
Direction ="Column"
ItemsSource ="{Binding Questions}"
ClearChild ="false">
<controls:RepeaterView.ItemTemplate>
<DataTemplate>
<ViewCell>
<controlsClaimFlowControls:QuestionBlock
Margin ="0,20,0,20"
QuestionNumber ="{Binding Index}"
QuestionText ="{Binding QuestionText}"
QuestionDescription="{Binding QuestionDescription}"
ItemsSource ="{Binding Source}"
DisplayMemberPath ="{Binding DisplayPaths}"
QuestionType ="{Binding QuestionType}"
SelectedItem ="{Binding Value}"
IsEnabledBlock ="{Binding IsEnabled}" />
</ViewCell>
</DataTemplate>
</controls:RepeaterView.ItemTemplate>
</controls:RepeaterView>
</StackLayout>
</ScrollView>
XAML.cs
protected override void OnAppearing()
{
if (BindingContext != null)
{
MedicalClaimConditionPageModel model = (MedicalClaimConditionPageModel)this.BindingContext.DataContext;
model.QuestionAdded += Model_QuestionAdded;
}
base.OnAppearing();
}
protected override void OnDisappearing()
{
MedicalClaimConditionPageModel model = (MedicalClaimConditionPageModel)this.BindingContext.DataContext;
model.QuestionAdded -= Model_QuestionAdded;
base.OnDisappearing();
}
void Model_QuestionAdded(object sender, EventArgs e)
{
Device.BeginInvokeOnMainThread(async () =>
{
if (Device.RuntimePlatform == Device.iOS)
{
// We need a Task.Delay to allow the contained controls to repaint and have their new sizes
// Ultimately we should come up with a better resolution - the delay value can vary depending on device and OS version.
await Task.Delay(50);
}
await QuestionScrollView.ScrollToAsync(QuestionRepeater, ScrollToPosition.End, true);
});
}
A reasonable answer has been posted by user yelinzh on the Xamarin forums:
How about trying to use Custom Renderer such as the fading effect.
[assembly: ExportRenderer(typeof(ScrollView_), typeof(ScrollViewR))]
namespace App3.Droid
{
public class ScrollViewR : ScrollViewRenderer
{
public ScrollViewR(Context context) : base(context)
{
}
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
this.SetFadingEdgeLength(300);
this.VerticalFadingEdgeEnabled = true;
}
}
}
This would probably work. In fact we've got for a different approach
(after feedback from the customer), where we're keeping the current question at the top of the screen and scrolling off upwards, so the content is no longer expanding.
Ive created a picker with data inside, when selected the data is added to a list. I want to the values that are added to the list to follow to the next page when calculate button is pressed.. tried a few different approaches but i cant get it right..
.cs
// add from picker to listview function
ObservableCollection<LayersClass> listProducts = new ObservableCollection<LayersClass>();
private void MainPicker_SelectedIndexChanged(object sender, EventArgs e)
{
// feedback popup box
var product = MainPicker.Items[MainPicker.SelectedIndex];
DisplayAlert(product, "Layer added to calculation list", "OK");
// if selected add to list
if (null != product)
{
LayersClass layer = new LayersClass();
layer.Product = product;
listProducts.Add(layer);
}
}
//calculate button
private async void Button_Clicked(object sender, EventArgs e)
{
// send selected values to CalculationPage ??
await Navigation.PushAsync(new CalculationPage());
}
xaml:
<ListView
x:Name="productsListView"
HasUnevenRows="False"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"
BackgroundColor="White">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.ContextActions>
<MenuItem Clicked="MenuItem_Clicked" Text="Delete" IsDestructive="true" CommandParameter="{Binding .}" />
</ViewCell.ContextActions>
<StackLayout>
<Label Text="{Binding Product}"></Label>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Button Margin="0,0,0,90" Text="Calculate" Clicked="Button_Clicked" FontSize="Medium" TextColor="#00AB8E" HorizontalOptions="Center" BackgroundColor="Transparent"/>
You should use parameter to pass data to the another page.
private async void Button_Clicked(object sender, EventArgs e)
{
// send selected values to CalculationPage ??
//Also you should write there an event.
var item = sender as Button;
var selectedItem = item as LayersClass;
await Navigation.PushAsync(new CalculationPage(item));
}
public CalculationPage(string item){
//when you type here dot after typing item like this -> item. you can see the layerclass items.
}
i want to create a greeting card maker app for WP7, when a user double taps an image from a listbox, I want that selected image to fill a rectangle on the same page.
Im passing 50 images into the list box like this:
public GCM()
{
InitializeComponent();
var articles = new List<Article>();
for (byte i = 1; i <= 20; i++)
{
Article article = new Article() { Name = "name"+i, ImagePath = "Assets/Images/Backgrounds/"+i+".jpg" };
articles.Add(article);
}
listBox1.DataContext = articles;
}
and its working fine, now heres an xml snippet:
<Rectangle Fill="#FFF4F4F5" Margin="28,24,30,148" Stroke="Black" Name="rect1" />
................(more code here).........................
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="10" >
<Image Name="bgs" Source="{Binding ImagePath}" Height="90" Width="90" DoubleTap="Load_BG" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
how can i fill the rectangle with the tapped image? this code (below) sets the string null everytime, no matter which image i select, although to my knowledge each has a different name and it should give different names for different images. I will use the name of the image to fill the rectangle. What am i doing wrong?
private void Load_BG(object sender, System.Windows.Input.GestureEventArgs e)
{
string abc = sender.GetType().Name;
}
Please excuse me if the solution is obvious..this is my first app ever. Thank you!
sender parameter should contains the control that triggered the event, in this case Image control. Try to cast it to Image type, then you can get the information you needed from Source property :
private void Load_BG(object sender, System.Windows.Input.GestureEventArgs e)
{
Image img = (Image)sender;
//do something with img.Source here
}
so heres the solution, it works now :)
private void listBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var img = listBox1.SelectedItem as Article;
ImageBrush imgBrush = new ImageBrush();
imgBrush.ImageSource = new BitmapImage(new Uri(img.ImagePath, UriKind.RelativeOrAbsolute));
rect1.Fill = imgBrush;
}