im trying to change between two images of a button when the same button is clicked
my xaml code is
<Button x:Name="BidderOne"
Click="BidderOne_Click" Height="5"
Grid.Row="2"
BorderBrush="#FFE7E3E3"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Margin="350,0,0,280"
>
<Button.Template>
<ControlTemplate>
<Image x:Name="BidderOneImage"
Source="/Assets/Star.png"
Width="50"/>
</ControlTemplate>
</Button.Template>
</Button>
im not sure what to write in my class, but what i found was something along the lines of this
private void BidderOne_Click(object sender, RoutedEventArgs e)
{
var selectedBidder = sender as Button;
// Button btn = new Button();
// btn = BidderOne;
ControlTemplate dt = BidderOne.Template;
Image btnImage = (Image)dt.TargetType = ;
var img = (Image)(selectedBidder.ContentTemplateRoot as StackPanel).Children[0];
var uri = new Uri("/Assetes/ClubsLogo.png", UriKind.Relative);
// var sri = Windows.UI.Xaml.Application.("Assetes/ClubsLogo.png", UriKind.Relative);
imgOn.UriSource=uri;
img.Source = imgOn;
}
It is not recommended to change the ControlTemplate of a Control at runtime. For these situations you should create a custom control.
I have written a simple ImageButton just so you can get the idea of creating what is needed for your problem.
Here is the code:
public sealed class ImageButton : Button
{
private Image _image;
public ImageButton()
{
this.DefaultStyleKey = typeof (Button);
_image = new Image();
}
protected override void OnApplyTemplate()
{
base.OnApplyTemplate();
this.Content = _image;
OnImage1SourceChanged(null, null);
}
public ImageSource Image1Source
{
get { return (ImageSource)GetValue(Image1SourceProperty); }
set { SetValue(Image1SourceProperty, value); }
}
public static readonly DependencyProperty Image1SourceProperty =
DependencyProperty.Register("Image1Source",
typeof (ImageSource),
typeof (ImageButton),
new PropertyMetadata(null, OnImage1SourceChangedCallback));
private static void OnImage1SourceChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var imageButton = d as ImageButton;
if (imageButton == null) return;
imageButton.OnImage1SourceChanged((ImageSource)e.OldValue, (ImageSource)e.NewValue);
}
private void OnImage1SourceChanged(ImageSource oldValue, ImageSource newValue)
{
if (_image != null)
{
_image.Source = Image1Source;
}
}
public ImageSource Image2Source
{
get { return (ImageSource)GetValue(Image2SourceProperty); }
set { SetValue(Image2SourceProperty, value); }
}
public static readonly DependencyProperty Image2SourceProperty =
DependencyProperty.Register("Image2Source",
typeof (ImageSource),
typeof (ImageButton),
new PropertyMetadata(null));
protected override void OnTapped(TappedRoutedEventArgs e)
{
base.OnTapped(e);
if (_image != null)
{
_image.Source = Image2Source;
}
}
}
and you use it like this:
<controls:ImageButton Width="60" Height="60" Image1Source="/Assets/Images/Chat/ic_comment_favorite_yellow.png" Image2Source="/Assets/Images/Flags/afghanistan.png"/>
Try this
EDITED
private void BidderOne_Click(object sender, RoutedEventArgs e) {
var selectedBidder = sender as Button;
// WRONG -> Image image = selectedBidder.Template.FindName("BidderOneImage", selectedBidder) as Image;
Image image = VisualTreeHelper.GetChild(selectedBidder, 0) as Image;
image.Source = new BitmapImage(new Uri("NEW IMAGE URI"));
}
Related
I want to show long text of picker item in two lines using custom render how can I achieve it?
First , you need a custom renderer for picker .
To override the item you need to replace the original view with a AlertDialog .
Then custom a ListView and set it as AlertDialog.View .
Then you can customize everything in the Adapter(here we need to customize the textview ).
Sample code
[assembly: ExportRenderer(typeof(Picker), typeof(MyPickerRenderer))]
namespace FormsApp.Droid
{
public class MyAdapter : ArrayAdapter
{
private IList<string> _data;
Context _context;
public MyAdapter(Context context, int resource , IList<string> data) : base(context,resource)
{
_context = context;
_data = data;
}
public override int Count => _data.Count;
public override Android.Views.View GetView(int position, Android.Views.View convertView, ViewGroup parent)
{
TextView textview = new TextView(_context);
textview.TextSize = 18;
textview.SetTextColor(Android.Graphics.Color.DarkGray);
textview.Ellipsize = TruncateAt.End;
textview.SetMaxLines(2); //this line
textview.Text = _data[position];
return textview;
}
}
public class MyListView : Android.Widget.ListView
{
public MyListView(Context context, IList<string> data) : base(context)
{
this.DividerHeight = 0;
this.Adapter = new MyAdapter(context, 0, data);
}
}
class MyPickerRenderer : Xamarin.Forms.Platform.Android.AppCompat.PickerRenderer
{
IElementController ElementController => Element as IElementController;
public MyPickerRenderer(Context context):base(context)
{
}
private AlertDialog _dialog;
protected override void OnElementChanged(ElementChangedEventArgs<Picker> e)
{
base.OnElementChanged(e);
if (e.NewElement == null || e.OldElement != null)
return;
Control.Click += Control_Click;
}
protected override void Dispose(bool disposing)
{
Control.Click -= Control_Click;
base.Dispose(disposing);
}
private void Control_Click(object sender, EventArgs e)
{
Picker model = Element;
var picker = new MyListView(Context, model.Items);
var layout = new LinearLayout(Context) { Orientation = Orientation.Vertical };
layout.SetPadding(35, 30, 35, 0);
layout.AddView(picker);
ElementController.SetValueFromRenderer(VisualElement.IsFocusedProperty, true);
var builder = new AlertDialog.Builder(Context);
builder.SetView(layout);
builder.SetTitle(model.Title ?? "");
builder.SetNegativeButton("Cancel ", (s, a) =>
{
ElementController.SetValueFromRenderer(VisualElement.IsFocusedProperty, false);
// It is possible for the Content of the Page to be changed when Focus is changed.
// In this case, we'll lose our Control.
Control?.ClearFocus();
_dialog = null;
});
_dialog = builder.Create();
_dialog.DismissEvent += (ssender, args) =>
{
ElementController?.SetValueFromRenderer(VisualElement.IsFocusedProperty, false);
};
_dialog.Show();
}
}
}
Testing code in Forms xaml
<Picker x:Name="picker" Title="Select a monkey">
<Picker.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>abc</x:String>
<x:String>aaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbccccccccccccccccdddddddddddddddddddddd</x:String>
</x:Array>
</Picker.ItemsSource>
</Picker>
Before
After
I created an entry where you type in a value, but now I want to create a bitmap with the text of an entry. When I got the bitmap, I can load it in SkiaSharp and use BitmapModifiers on it.
Is this possible?
I would recommend you to go through these examples on github.
Dummy sample could look like this:
This is xaml page:
<StackLayout>
<Entry x:Name="InputText" />
<Button Text="Create Bitmap" Clicked="Button_Clicked" />
</StackLayout>
Codebehind:
SKBitmap helloBitmap;
void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
SKImageInfo info = args.Info;
SKSurface surface = args.Surface;
SKCanvas canvas = surface.Canvas;
canvas.Clear(SKColors.Aqua);
canvas.DrawBitmap(helloBitmap, 0, 0);
}
private void Button_Clicked(object sender, EventArgs e)
{
CreateBitmapFromText(InputText.Text);
}
private void CreateBitmapFromText(string text)
{
// Create bitmap and draw on it
using (SKPaint textPaint = new SKPaint { TextSize = 48 })
{
SKRect bounds = new SKRect();
textPaint.MeasureText(text, ref bounds);
helloBitmap = new SKBitmap((int)bounds.Right,
(int)bounds.Height);
using (SKCanvas bitmapCanvas = new SKCanvas(helloBitmap))
{
bitmapCanvas.Clear();
bitmapCanvas.DrawText(text, 0, -bounds.Top, textPaint);
}
}
SKCanvasView canvasView = new SKCanvasView();
canvasView.PaintSurface += OnCanvasViewPaintSurface;
Content = canvasView;
}
I am having an grid holding in Button. I want to set corner radius for this button by programmatically in xamarin.uwp. If it possible means i want to set corner radius for Bottom left alone. Please suggest your ideas for this query.
For your requirement, you could custom BottomLeft BindableProperty. then use it in your custom button render like the following.
Custom Forms buttom
public class MyButton : Button
{
public static readonly BindableProperty BottomLeftProperty = BindableProperty.Create(
propertyName: "BottomLeft",
returnType: typeof(int),
declaringType: typeof(MyButton),
defaultValue: default(int));
public int BottomLeft
{
get { return (int)GetValue(BottomLeftProperty); }
set { SetValue(BottomLeftProperty, value); }
}
}
CustomButtonRenderer.cs
public class CustomButtonRenderer : ButtonRenderer
{
Windows.UI.Xaml.Controls.ContentPresenter _contentPresenter;
MyButton _myElement;
protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
{
base.OnElementChanged(e);
if (Control == null)
{
SetNativeControl(new FormsButton());
}
if (e.NewElement != null)
{
Control.Loaded += Control_Loaded;
_myElement = Element as MyButton;
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == MyButton.BottomLeftProperty.PropertyName)
{
UpdateBottomLeftBorderRadius(_myElement.BottomLeft);
}
}
private void Control_Loaded(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
_contentPresenter = MyFindChildByName(Control, "ContentPresenter") as Windows.UI.Xaml.Controls.ContentPresenter;
if (_myElement.IsSet(MyButton.BottomLeftProperty) && _myElement.BottomLeft != (int)MyButton.BottomLeftProperty.DefaultValue)
{
UpdateBottomLeftBorderRadius(_myElement.BottomLeft);
}
}
private void UpdateBottomLeftBorderRadius(int bottomLeft)
{
if (_contentPresenter != null)
{
_contentPresenter.CornerRadius = new CornerRadius(0, 0, 0, bottomLeft);
}
}
public static DependencyObject MyFindChildByName(DependencyObject parant, string ControlName)
{
int count = VisualTreeHelper.GetChildrenCount(parant);
for (int i = 0; i < count; i++)
{
var MyChild = VisualTreeHelper.GetChild(parant, i);
if (MyChild is FrameworkElement && ((FrameworkElement)MyChild).Name == ControlName)
return MyChild;
var FindResult = MyFindChildByName(MyChild, ControlName);
if (FindResult != null)
return FindResult;
}
return null;
}
}
Usage
<local:MyButton x:Name="Hello" Text="hello"
WidthRequest="100"
HeightRequest="100"
Margin="0,100,0,0"
BottomLeft="15"
VerticalOptions="Center"
HorizontalOptions="Center"
Clicked="MyButton_Clicked"/>
For edit the bottom left property programatically.
HelloBtn.BottomLeft = 30;
I have an activity indicator designed inside a absolute layout. Based on a button click event, I try to show and hide the activity indicator alternatively. But due to some reason, I cannot see my activity Indicator.Any help will be greatly appreciated!!! Thanks in advance.
This is my .xaml.cs class:
public partial class PBTestPage : ContentPage
{
private bool _pbIndicator;
public PBTestPage()
{
InitializeComponent();
}
public bool PBIndicator{
get{
return _pbIndicator;
}set{
_pbIndicator = value;
OnPropertyChanged();
}
}
protected override void OnAppearing()
{
base.OnAppearing();
var parentLayout = new AbsoluteLayout();
var stackContent = new StackLayout();
AbsoluteLayout.SetLayoutFlags(stackContent,AbsoluteLayoutFlags.PositionProportional);
AbsoluteLayout.SetLayoutBounds(stackContent,new Rectangle(0f,0f,AbsoluteLayout.AutoSize,AbsoluteLayout.AutoSize));
var activityIndicator = new ActivityIndicator
{
Color = Color.Black,
IsRunning = PBIndicator,
IsVisible = PBIndicator
};
AbsoluteLayout.SetLayoutFlags(activityIndicator, AbsoluteLayoutFlags.PositionProportional);
AbsoluteLayout.SetLayoutBounds(activityIndicator, new Rectangle(.5, .5, AbsoluteLayout.AutoSize, AbsoluteLayout.AutoSize));
var button = new Button
{
Text="Click",
VerticalOptions=LayoutOptions.CenterAndExpand,
HorizontalOptions=LayoutOptions.CenterAndExpand,
};
button.Clicked += OnClicked;
stackContent.Children.Add(button);
parentLayout.Children.Add(stackContent);
parentLayout.Children.Add(activityIndicator);
Content = parentLayout;
}
private void OnClicked(object sender, EventArgs e)
{
if(PBIndicator==false){
PBIndicator = true;
}else{
PBIndicator = false;
}
}
}
I'm inferring you're intending to use bindings by the use of OnPropertyChanged, so it's a good time to start do it.
I've made some changes in your code and I guess it will work properly now. The changes are:
Moved the layout creation to the constructor (I can't see create the whole same layout on every time the page is shown as a good choice );
The OnClicked event just invert the value of the property, no need to check it before with an if;
Using Bindings to handle the ActivityIndicator's properties state;
Set true to PBIndicator property on the OnAppearing event.
This is the changed code:
public partial class PBTestPage : ContentPage
{
private bool _pbIndicator;
public bool PBIndicator
{
get { return _pbIndicator; }
set
{
_pbIndicator = value;
OnPropertyChanged();
}
}
public PBTestPage()
{
InitializeComponent();
var parentLayout = new AbsoluteLayout();
var stackContent = new StackLayout();
AbsoluteLayout.SetLayoutFlags(stackContent, AbsoluteLayoutFlags.PositionProportional);
AbsoluteLayout.SetLayoutBounds(stackContent, new Rectangle(0f, 0f, AbsoluteLayout.AutoSize, AbsoluteLayout.AutoSize));
var activityIndicator = new ActivityIndicator
{
Color = Color.Black
};
activityIndicator.SetBinding(ActivityIndicator.IsRunningProperty, new Binding(nameof(PBIndicator)));
activityIndicator.SetBinding(ActivityIndicator.IsVisibleProperty, new Binding(nameof(PBIndicator)));
activityIndicator.BindingContext = this;
AbsoluteLayout.SetLayoutFlags(activityIndicator, AbsoluteLayoutFlags.PositionProportional);
AbsoluteLayout.SetLayoutBounds(activityIndicator, new Rectangle(.5, .5, AbsoluteLayout.AutoSize, AbsoluteLayout.AutoSize));
var button = new Button
{
Text = "Click",
VerticalOptions = LayoutOptions.CenterAndExpand,
HorizontalOptions = LayoutOptions.CenterAndExpand,
};
button.Clicked += OnClicked;
stackContent.Children.Add(button);
parentLayout.Children.Add(stackContent);
parentLayout.Children.Add(activityIndicator);
Content = parentLayout;
}
protected override void OnAppearing()
{
base.OnAppearing();
PBIndicator = true;
}
private void OnClicked(object sender, EventArgs e)
{
PBIndicator = !PBIndicator;
}
}
Let me know if it works. I hope it helps.
Try this one
private void OnClicked(object sender, EventArgs e)
{
if(PBIndicator==false){
activityIndicator.IsRunning=true;
}else{
activityIndicator.IsRunning=false;
}
}
I'm new to Xamarin and I'm currently doing a project in Xamarin Forms PCL.
Is there a way to change the font colour and size of Picker?
<Picker x:Name="pkr_color" Grid.Row="4" Grid.Column="1" HorizontalOptions="FillAndExpand"
BackgroundColor="#ededed" Title="Select Color">
<Picker.Items>
<x:String>Red</x:String>
<x:String>Blue</x:String>
<x:String>Green</x:String>
</Picker.Items>
</Picker>
Thanks in advance!
You will need to write a custom renderer for each platform.
using System;
using Project.iOS;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer (typeof (Picker), typeof (CustomPickerRenderer))]
namespace Project.iOS
{
public class CustomPickerRenderer : PickerRenderer
{
protected override void OnElementChanged (ElementChangedEventArgs<Picker> e)
{
base.OnElementChanged (e);
if (Control != null) {
Control.TextColor = UIKit.UIColor.White;
}
}
}
}
Here is an example for iOS. This would change the color of the text, you will need to do something similar for Android, and just add your font sizing change as well.
Font size of a picker can be changed with PCL code.
Create MainPage.xaml file
<Picker x:Name="PickerList" Title="Select Any One" IsVisible="False" SelectedIndexChanged="PickerList_SelectedIndexChanged">
<Picker.Items>
<x:String>Option 1</x:String>
<x:String>Option 2</x:String>
<x:String>Option 3</x:String>
</Picker.Items>
</Picker>
<Label x:Name="PickerLabel" Text="Tap to Select Picker" FontSize="14" HorizontalOptions="Start">
<Label.GestureRecognizers>
<TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped"/>
</Label.GestureRecognizers>
</Label>
Create MainPage.xaml.cs file
private void PickerList_SelectedIndexChanged(object sender, EventArgs e)
{
PickerLabel.Text = PickerList.Items[PickerList.SelectedIndex];
// PickerLabel.Text = PickerList.SelectedItem.ToString() ;
}
private void TapGestureRecognizer_Tapped(object sender, EventArgs e)
{
PickerList.Focus();
}
this solves the problem for Android and IOS.
I Hope Below Code Helpful to Get Your TextColor
**In Xaml**
<Picker SelectedIndexChanged="OnColorPickerSelected" TextColor="{Binding TextColor}"/>
**In Code Behind**
private void OnColorPickerSelected(object sender, EventArgs e)
{
((ViewModel)BindingContext).Color= pkr_color.Items[pkr_color.SelectedIndex];
ChooseColorPickerTextColor(((ViewModel)BindingContext).Color, pkr_color);
}
**Implement ChooseColorPickerTextColor Method Here**
private void ChooseColorPickerTextColor(string selectedColor, Picker pickerName)
{
Picker colorPickerTextColor = pickerName;
if (selectedColor == "Red")
{
colorPickerTextColor.TextColor = Color.Red;
}
else if (selectedColor == "Yellow")
{
colorPickerTextColor.TextColor = Color.Yellow;
}
else if (selectedColor == "Green")
{
colorPickerTextColor.TextColor = Color.Green;
}
else if (selectedColor == "Blue")
{
colorPickerTextColor.TextColor = Color.Blue;
}
else if (selectedColor == "Maroon")
{
colorPickerTextColor.TextColor = Color.Maroon;
}
else if (selectedColor == "Pink")
{
colorPickerTextColor.TextColor = Color.Pink;
}
else
{
colorPickerTextColor.TextColor = Color.Aqua;
}
}
By using "WidthRequest" We can Increase size of the picker
For changing typeface, size, underline, text, textcolor, alert dialog button position, button text in Android native numberpicker (xamarin form picker), you can handle it with a custom render like this:
using System;
using System.Collections.Generic;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using Android.Graphics.Drawables;
using Android.Graphics;
[assembly: ExportRenderer(typeof(Picker), typeof(MyPickerRenderer))]
namespace Daddy.Droid
{
public class MyPickerRenderer : Xamarin.Forms.Platform.Android.PickerRenderer
{
Typeface fontFace = null;
private IElementController ElementController => Element as IElementController;
private AlertDialog _dialog;
public MyPickerRenderer(Context context) : base(context)
{
AutoPackage = false;
}
[Obsolete("This constructor is obsolete as of version 2.5. Please use PickerRenderer(Context) instead.")]
public MyPickerRenderer()
{
AutoPackage = false;
}
protected override void OnElementChanged(ElementChangedEventArgs<Picker> e)
{
base.OnElementChanged(e);
if (e.NewElement == null || e.OldElement != null || Control == null)
return;
fontFace = Typeface.CreateFromAsset(this.Context.Assets, "somefont.ttf");
GradientDrawable gd = new GradientDrawable();
gd.SetStroke(0, Android.Graphics.Color.Transparent);
Control.SetBackground(gd);
Control.TextSize = 14f;
Control.SetTypeface(fontFace, TypefaceStyle.Normal);
Control.Click += Control_Click;
}
protected override void Dispose(bool disposing)
{
Control.Click -= Control_Click;
base.Dispose(disposing);
}
private void Control_Click(object sender, EventArgs e)
{
Picker model = Element;
NumberPicker picker = new NumberPicker(Context);
int count = picker.ChildCount;
for (int i = 0; i < count; i++)
{
Android.Views.View v = picker.GetChildAt(i);
if(v.GetType() == typeof(EditText))
{
Java.Lang.Reflect.Field field = picker.Class.GetDeclaredField("mSelectorWheelPaint");
field.Accessible = true;
((Paint)field.Get(picker)).SetTypeface(fontFace);
((EditText)v).SetTypeface(fontFace, TypefaceStyle.Normal);
picker.Invalidate();
}
}
if (model.Items != null && model.Items.Any())
{
picker.MaxValue = model.Items.Count - 1;
picker.MinValue = 0;
picker.SetDisplayedValues(model.Items.ToArray());
picker.WrapSelectorWheel = false;
picker.DescendantFocusability = DescendantFocusability.BlockDescendants;
picker.Value = model.SelectedIndex;
picker.Visibility = ViewStates.Visible;
}
var layout = new LinearLayout(Context) { Orientation = Orientation.Vertical };
layout.Visibility = ViewStates.Visible;
layout.AddView(picker);
ElementController.SetValueFromRenderer(VisualElement.IsFocusedProperty, true);
var builder = new AlertDialog.Builder(Context);
builder.SetView(layout);
builder.SetTitle(model.Title ?? "");
builder.SetNegativeButton("Cancel", (s, a) =>
{
ElementController.SetValueFromRenderer(VisualElement.IsFocusedProperty, false);
Control?.ClearFocus();
_dialog = null;
});
builder.SetPositiveButton("This One", (s, a) =>
{
ElementController.SetValueFromRenderer(Picker.SelectedIndexProperty, picker.Value);
if (Element != null)
{
if (model.Items.Count > 0 && Element.SelectedIndex >= 0)
Control.Text = model.Items[Element.SelectedIndex];
ElementController.SetValueFromRenderer(VisualElement.IsFocusedProperty, false);
Control?.ClearFocus();
}
_dialog = null;
});
_dialog = builder.Create();
_dialog.DismissEvent += (ssender, args) =>
{
ElementController?.SetValueFromRenderer(VisualElement.IsFocusedProperty, false);
};
_dialog.Show();
Android.Widget.Button nbutton = _dialog.GetButton((int)Android.Content.DialogButtonType.Positive);
nbutton.SetTypeface(fontFace, TypefaceStyle.Normal);
nbutton.SetTextColor(Android.Graphics.Color.ParseColor("#33b5e5"));
nbutton.TextSize = 16f;
LinearLayout layOut = (LinearLayout)nbutton.Parent;
layOut.SetGravity(GravityFlags.CenterHorizontal);
Android.Views.View v1 = layOut.GetChildAt(1);
v1.Visibility = ViewStates.Gone;
int res = Resources.GetIdentifier("alertTitle", "id", "android");
TextView textView = (TextView)_dialog.FindViewById(res);
textView.SetTextColor(Android.Graphics.Color.Gray);
textView.SetTypeface(fontFace, TypefaceStyle.Normal);
textView.Gravity = GravityFlags.Center;
}
}
}
Put the Label and Picker in the same Grid cell.Don't set Title of the picker instead the Text of the Label will work as Title.
<Label x:Name="PickerLabel" Text="Picker Title" TextColor="Any Color"></Label>
<Picker x:Name="Picker" SelectedIndexChanged="Picker_SelectedIndexChanged" TextColor="Any Color" />
Now make the Text of Label Invisible when an Item is selected from Picker.
void Picker_SelectedIndexChanged(object sender, System.EventArgs e)
{
PickerLabel.IsVisible = false;
}