Customizing the progress bar color in UWP using Xamarin Forms - xamarin

I made a progress bar customization (custom renderer) to change the progress bar color in iOS and Droid as seen in the following
Custom progress bar class in the PCL:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace App2
{
public class ColorProgressBar : ProgressBar
{
public static BindableProperty BarColorProperty
= BindableProperty.Create<ColorProgressBar, Color>(p =>
p.BarColor, default(Color));
public Color BarColor
{
get { return (Color)GetValue(BarColorProperty); }
set { SetValue(BarColorProperty, value); }
}
}
}
Custom renderer for iOS:
using App2;
using App2.iOS;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using Xamarin.Forms;
//using MonoTouch.Foundation;
//using MonoTouch.UIKit;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(ColorProgressBar),
typeof(ColorProgressBarRenderer))]
namespace App2.iOS
{
public class ColorProgressBarRenderer : ProgressBarRenderer
{
public ColorProgressBarRenderer()
{ }
protected override void
OnElementChanged(ElementChangedEventArgs<ProgressBar> e)
{
base.OnElementChanged(e);
if (e.NewElement == null)
return;
if (Control != null)
{
UpdateBarColor();
}
}
protected override void OnElementPropertyChanged(object sender,
PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName ==
ColorProgressBar.BarColorProperty.PropertyName)
{
UpdateBarColor();
}
}
private void UpdateBarColor()
{
var element = Element as ColorProgressBar;
Control.TintColor = element.BarColor.ToUIColor();
}
}
}
Custom renderer for Android:
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 Android.Renderscripts;
using static Java.Util.ResourceBundle;
using Xamarin.Forms.Platform.Android;
using Android.Graphics;
using System.ComponentModel;
using Xamarin.Forms;
using App2;
using App2.Droid;
[assembly: ExportRenderer(typeof(ColorProgressBar),
typeof(ColorProgressBarRenderer))]
namespace App2.Droid
{
public class ColorProgressBarRenderer : ProgressBarRenderer
{
public ColorProgressBarRenderer()
{ }
protected override void
OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.ProgressBar>
e)
{
base.OnElementChanged(e);
if (e.NewElement == null)
return;
if (Control != null)
{
UpdateBarColor();
}
}
protected override void OnElementPropertyChanged(object sender,
PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName ==
ColorProgressBar.BarColorProperty.PropertyName)
{
UpdateBarColor();
}
}
private void UpdateBarColor()
{
var element = Element as ColorProgressBar;
// http://stackoverflow.com/a/29199280
Control.IndeterminateDrawable.SetColorFilter(
element.BarColor.ToAndroid(), PorterDuff.Mode.SrcIn);
Control.ProgressDrawable.SetColorFilter(
element.BarColor.ToAndroid(), PorterDuff.Mode.SrcIn);
}
}
}
I'm setting the custom progress bar's color this way:
var progressBar = new ColorProgressBar();
progressBar.BarColor = Color.Red;
I don't understand how to make a custom renderer class for UWP that changes the color of the progress bar. Could someone please help me understand how to do this class?

You're going to want to update the Foreground property of the native Windows.UI.Xaml.Controls.ProgressBar control to change the color.
It should look something like this:
private void UpdateBarColor()
{
var element = Element as ColorProgressBar;
Control.Foreground = new Windows.UI.Xaml.Media.SolidColorBrush(
GetWindowsColor(element.BarColor));
}
Windows.UI.Color GetWindowsColor(Color color)
{
return Windows.UI.Color.FromArgb((byte)(255 * color.A), (byte)(255 * color.R), (byte)(255 * color.G), (byte)(255 * color.B));
}
This will take your BarColor, use it to make a SolidColorBrush of the right color, and then assign that to your native ProgressBar control.

Related

when focused remove underline from material entry control in xamarin forms for ios

using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using Xamarin.Forms.Material.iOS;
using MyApp.iOS;
using MyApp;
using UIKit;
using System.ComponentModel;
[assembly: ExportRenderer(typeof(CustomMaterialEntry), typeof(CustomMaterialEntryRenderer), new[] { typeof(VisualMarker.MaterialVisual) })]
namespace MyApp.iOS
{
public class CustomMaterialEntryRenderer : MaterialEntryRenderer
{
/// <summary>
/// Element Changed Event
/// </summary>
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if (this.Control != null)
{
UITextField UpdatedEntry = (UITextField)Control;
UpdatedEntry.Background = null;
UpdatedEntry.BackgroundColor = UIColor.Clear;
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (this.Control != null)
this.Control.Underline.Color = UIColor.Clear;
}
}
}
For android, it's working but when focused on the material entry in ios, it displays with the underline. please help me to remove the underline in ios for xamarin.forms
Try to set the active underline height to 0f :
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if (this.Control != null)
{
Control.ActiveTextInputController.UnderlineHeightActive = 0f;
}
}

In Xamarin Forms is there any way I can change the size of the images used in the tab bars when using Xamarin Shell?

I would like to be able to customize the bottom tab bar. From what I understand this isn’t yet possible but it might be a future feature. Until that time has anyone come across any custom renderers for iOS and Android that would allow me to change the size of the images that display in the bottom tab area?
You could use Custom Renderer to reset the size of icon in specific platforms .
in iOS projet
In the renderer I set the first icon as 60pt *60pt . You need to set the size on each item
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using xxx;
using xxx.iOS;
using CoreGraphics;
using Foundation;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(AppShell), typeof(MyShellRenderer))]
namespace xxx.iOS
{
public class MyShellRenderer : ShellRenderer
{
protected override IShellSectionRenderer CreateShellSectionRenderer(ShellSection shellSection)
{
var renderer = base.CreateShellSectionRenderer(shellSection);
if (renderer != null)
{
}
return renderer;
}
protected override IShellTabBarAppearanceTracker CreateTabBarAppearanceTracker()
{
return new CustomTabbarAppearance();
}
}
public class CustomTabbarAppearance : IShellTabBarAppearanceTracker
{
public void Dispose()
{
}
public void ResetAppearance(UITabBarController controller)
{
}
public void SetAppearance(UITabBarController controller, ShellAppearance appearance)
{
UITabBar myTabBar = controller.TabBar;
if (myTabBar.Items != null)
{
UITabBarItem itemOne = myTabBar.Items[0];
itemOne.Image = ScalingImageToSize(UIImage.FromBundle("tab_feed.png"),new CGSize(60,60)); // set the size here if you want to customize it
itemOne.SelectedImage = ScalingImageToSize(UIImage.FromBundle("tab_feed.png"), new CGSize(60, 60));
UITabBarItem itemTwo = myTabBar.Items[1];
itemTwo.Image = UIImage.FromBundle("tab_about.png");
itemTwo.SelectedImage = UIImage.FromBundle("tab_about.png");
//The same logic if you have itemThree, itemFour....
}
}
public UIImage ScalingImageToSize(UIImage sourceImage, CGSize newSize)
{
UIGraphics.BeginImageContextWithOptions(newSize, false, UIScreen.MainScreen.Scale);
sourceImage.Draw(new CGRect(0, 0, newSize.Width, newSize.Height));
UIImage newImage = UIGraphics.GetImageFromCurrentImageContext();
UIGraphics.EndImageContext();
return newImage;
}
public void UpdateLayout(UITabBarController controller)
{
}
}
}
in Android
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.Graphics;
using Android.Graphics.Drawables;
using Android.OS;
using Android.Runtime;
using Android.Support.Design.Widget;
using Android.Views;
using Android.Widget;
using xxx;
using xxx.Droid;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ExportRenderer(typeof(AppShell), typeof(MyShellRenderer))]
namespace xxx.Droid
{
public class MyShellRenderer : ShellRenderer
{
Context context;
public MyShellRenderer(Context context) : base(context)
{
this.context = context;
}
protected override IShellBottomNavViewAppearanceTracker CreateBottomNavViewAppearanceTracker(ShellItem shellItem)
{
return new CustomBottomNavAppearance(context);
}
}
public class CustomBottomNavAppearance : IShellBottomNavViewAppearanceTracker
{
Context context;
public CustomBottomNavAppearance(Context context)
{
this.context = context;
}
public void Dispose()
{
}
public void ResetAppearance(BottomNavigationView bottomView)
{
}
public void SetAppearance(BottomNavigationView bottomView, ShellAppearance appearance)
{
bottomView.ItemIconSize=250;
//The same logic if you have myItemTwo, myItemThree....
}
}
}

Is there a better way to set TabbedPage bottom tab bar height than in ViewModel?

I want to change the height of the bottom TabBar in my Xamarin app. Now I am doing this via ViewModel properties:
public partial class MainPage : TabbedPage
{
public int TabBarHeight
{
get { return _tabBarHeight; }
set { _tabBarHeight = value; OnPropertyChanged(); }
}
int _tabBarHeight = 200;
And a custom renderer for iOS:
using System;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using System.Diagnostics;
using Ja.Enums;
using System.ComponentModel;
using CoreGraphics;
[assembly: ExportRenderer(typeof(TabbedPage), typeof(Ja.iOS.TabbedPageRenderer))]
namespace Ja.iOS
{
public class TabbedPageRenderer : TabbedRenderer
{
private MainPage _page;
public TabbedPageRenderer()
{
this.ViewControllerSelected += OnTabbarControllerItemSelected;
}
public override void ViewWillLayoutSubviews()
{
base.ViewWillLayoutSubviews();
TabBar.Frame = new CGRect(TabBar.Frame.X, TabBar.Frame.Y + (TabBar.Frame.Height - _page.TabBarHeight), TabBar.Frame.Width, _page.TabBarHeight);
}
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
e.OldElement.PropertyChanged -= Current_PropertyChanged;
return;
}
if (e.NewElement != null)
{
_page = (MainPage)e.NewElement;
e.NewElement.PropertyChanged += Current_PropertyChanged;
}
}
void Current_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName == "FrameHeight")
ViewWillLayoutSubviews();
}
}
}
Is this an optimal way to be doing this? I seem to remember having a shared class. That class would contain the code that's in the first few lines of my main as bound elements.
Could anyone comment on this and perhaps suggest a better way of doing this.
Looks like something I would use a Custom Control for (which is what I think you mean with 'shared class').
First you create the class below in your PCL. A CustomTabbedPage, which inherits from TabbedPage but has one extra property: 'TabBarHeight'
public class CustomTabbedPage : TabbedPage {
public static readonly BindableProperty TabBarHeightProperty = BindableProperty.Create("TabBarHeight", typeof(int), typeof(TabbedPage), 0);
public int TabBarHeight {
get { return (int)GetValue(TabBarHeightProperty); }
set { SetValue(TabBarHeightProperty, value); }
}
}
Now edit your renderer to a renderer of the CustomTabbedPage. Then you can easily access the TabBarHeight property by using this.Element.TabBarHeight.
using System;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using System.Diagnostics;
using Ja.Enums;
using System.ComponentModel;
using CoreGraphics;
[assembly: ExportRenderer(typeof(CustomTabbedPage), typeof(Ja.iOS.CustomTabbedPageRenderer))]
namespace Ja.iOS
{
public class CustomTabbedPageRenderer : TabbedRenderer
{
public TabbedPageRenderer()
{
this.ViewControllerSelected += OnTabbarControllerItemSelected;
}
public override void ViewWillLayoutSubviews()
{
base.ViewWillLayoutSubviews();
TabBar.Frame = new CGRect(TabBar.Frame.X, TabBar.Frame.Y + (TabBar.Frame.Height - this.Element.TabBarHeight), TabBar.Frame.Width, this.Element.TabBarHeight);
}
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
if (e.OldElement != null) {
e.OldElement.PropertyChanged -= Element_PropertyChanged;
}
if (e.NewElement != null) {
e.NewElement.PropertyChanged += Element_PropertyChanged;
}
}
void Current_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName == "FrameHeight")
ViewWillLayoutSubviews();
}
}
}
There might be some syntax errors in there but you get the point.
Shoot if you have any questions.

How to make back button return to the system Windows Phone

I have a small app there is 3 seconds intro page, then the content page. When I push back button I go back to the intro screen, but I think I should go back to the system. How to do it?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using System.ServiceModel.Syndication;
using System.Xml;
using Microsoft.Phone.Tasks;
namespace RSS {
public partial class FeedPage : PhoneApplicationPage {
public FeedPage() {
InitializeComponent();
this.Loaded += new RoutedEventHandler(PhonePage1_Loaded);
}
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) {
clearBackStack();
base.OnNavigatedTo(e);
}
void clearBackStack() {
while (this.NavigationService.BackStack.Any()) {
this.NavigationService.RemoveBackEntry();
}
}
void PhonePage1_Loaded(object sender, RoutedEventArgs e) {
// clearBackStack();
WebClient wc = new WebClient();
wc.OpenReadCompleted += new OpenReadCompletedEventHandler(wc_OpenReadCompleted);
wc.OpenReadAsync(new Uri("http://www.carmagazine.co.uk/Shared/Handlers/RssHandler.ashx?&N=190&Ns=P_Publication_Date|1&?"));
}
void wc_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e) {
SyndicationFeed feed;
try {
using (XmlReader reader = XmlReader.Create(e.Result)) {
feed = SyndicationFeed.Load(reader);
lista.ItemsSource = feed.Items;
}
} catch (WebException we) { MessageBox.Show("Internet connection is down.");}
}
private void Button_Click(object sender, System.Windows.RoutedEventArgs e) {
WebBrowserTask webBrowserTask = new WebBrowserTask();
String url = (String)((Button)sender).Tag;
webBrowserTask.Uri = new Uri(url);
webBrowserTask.Show();
}
}
}
You should clear the BackStack in the OnNavigateTo method of your content page
while (this.NavigationService.BackStack.Any())
{
this.NavigationService.RemoveBackEntry();
}
The following code is the best practice for the back button key press.
protected override void OnBackKeyPress(CancelEventArgs e)
{
while (NavigationService.CanGoBack)
NavigationService.RemoveBackEntry();
base.OnBackKeyPress(e);
}
This ensures that your application will exit and return to the main screen on pressing the BackKey.

Detect Autoscrollposition value change in panel

How to detect if the Autoscrollposition value changes in the panel1?
For example,
textbox1 and textbox2.
which added in panel1. The autoscroll property is set to true.
I am only interested in detecting when the value of panel autoscrollposition changes.
The above for dynamic textboxes which are incremented.
Software in use: C#, Visual Studio 2005.
The Component required for it. is:
ListBox1
ListBox2
Panel
Button.
The Namespace for Class:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Collections;
Here is the Complete Solution Code:
namespace detectpanelvalue
{
public partial class Form1 : Form
{
private Point tbpoint = new Point(10, 14);
private Point tbbpoint = new Point(300, 14);
private ArrayList arylst;
private ArrayList arylst1;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
panel1.Paint += new PaintEventHandler(panel1_Paint);
}
void panel1_Paint(object sender, PaintEventArgs e)
{
System.Drawing.Point pnlpt;
pnlpt = panel1.AutoScrollPosition;
if (tbpoint !=null || pnlpt != null )
{
pnlpt = tbpoint;
}
arylst1 = new ArrayList();
arylst1.Add(pnlpt);
}
private void runtime()
{
foreach (Point pt in arylst)
{
listBox1.Items.Add(pt);
}
foreach (Point ptt in arylst1)
{
listBox2.Items.Add(ptt);
}
}
private void button1_Click(object sender, EventArgs e)
{
TextBox tb = new TextBox();
tb.Location = tbpoint;
this.panel1.Controls.Add(tb);
tbpoint.Y += 30;
TextBox bb = new TextBox();
bb.Location = tbbpoint;
this.panel1.Controls.Add(bb);
tbbpoint.Y += 30;
arylst = new ArrayList();
arylst.Add(tbpoint);
runtime();
}
}
}
It is helpful for adjust the panel autoscrollposition.

Resources