[Xamarin Blog] Using Custom Controls in Xamarin.Forms on Android

JamesMontemagnoJamesMontemagno James MontemagnoUSForum Administrator, Xamarin Team, Developer Group Leader Xamurai
edited June 2014 in Xamarin.Forms

Just posted: Using Custom Controls in Xamarin.Forms on Android on the Xamarin Blog.

Read the full article to learn how to use any Android custom control in a Xamarin.Forms application.

Use this thread to discuss or ask questions.

Posts

  • RyanSouthRyanSouth Ryan South USMember ✭✭

    Thanks for the Example! I was wondering if you could do something similar on iOS? If you can how do figure out what class you would use? Basically instead of the HoloCircularProgressBar what would you look at using?

  • JamesMontemagnoJamesMontemagno James Montemagno USForum Administrator, Xamarin Team, Developer Group Leader Xamurai

    Hey @RyanSouth you would do the exact same thing, but in your iOS solution. Similar to the webcast found here: http://forums.xamarin.com/discussion/17792

    You could build something yourself like i did or there might be something on the component store such as: https://components.xamarin.com/view/radialprogress that you could apply this to.

  • JohnOGormanJohnOGorman John O'Gorman USMember

    James,

    I'm trying to set up my custom control and following your tutorial has helped a little however I have to implement my custom control via XAML. In your sample code as part of this tutorial (which I downloaded from Github) would you be able to tell me which classes are used for the XAML custom control? From looking at your code you seem to have written two ways of doing the same thing, I just don't know where one implementation starts and the other stops.

    Thanks.

  • JamesMontemagnoJamesMontemagno James Montemagno USForum Administrator, Xamarin Team, Developer Group Leader Xamurai

    @‌JohnOGorman
    So for either C# code behind or XAML UI we still use the same custom Xamarin.Forms control that I made: https://github.com/jamesmontemagno/Xamarin.Forms-Android-CustomProgressBar/blob/master/CustomProgressBar.Portable/CustomControls/CircularProgress.cs

    For XAML there are only 2 important parts to the Page.

    1.) Adding a xmlns:local so you can reference your control (https://github.com/jamesmontemagno/Xamarin.Forms-Android-CustomProgressBar/blob/master/CustomProgressBar.Portable/Pages/ProgressBarXAML.xaml#L6)

    2.) Adding the control. And you can see here I am data binding here to the viewmodel (both views are binding to this viewmodel) https://github.com/jamesmontemagno/Xamarin.Forms-Android-CustomProgressBar/blob/master/CustomProgressBar.Portable/Pages/ProgressBarXAML.xaml#L28-L35

    The code behind for the XAML page is nearly blank: https://github.com/jamesmontemagno/Xamarin.Forms-Android-CustomProgressBar/blob/master/CustomProgressBar.Portable/Pages/ProgressBarXAML.xaml.cs as all of the logic happens in the ViewModel. You can add an x:Name="MyControl" in XAML and then access this from the code behind if you want.

    I hope that helps...

  • SteeveLeDreauSteeveLeDreau Steeve Le Dreau FRMember
    edited January 2015

    Hi James, i try to use a custom renderer to change the default progress color of the progress bar.
    Here is my code. I don't find any property to set.
    Also, am i doing it right ? (my first custom renderer)

    [assembly: ExportRenderer(typeof(KalideaMobile.Resources.Controls.ProgressBar), typeof(ProgressBarCustomRenderer))]
    namespace KalideaMobile.CustomRenderers
    {
        public class ProgressBarCustomRenderer : ViewRenderer<KalideaMobile.Resources.Controls.ProgressBar, Android.Widget.ProgressBar>
        {
            public ProgressBarCustomRenderer()
                : base()
            {
            }
    
            protected override void OnElementChanged(ElementChangedEventArgs<KalideaMobile.Resources.Controls.ProgressBar> e)
            {
                base.OnElementChanged(e);
                if (e.OldElement != null || this.Element == null) return;
    
                var progress = new Android.Widget.ProgressBar(Forms.Context, null, Android.Resource.Attribute.ProgressBarStyleHorizontal);
    
                //progress.ProgressColor = this.Element.ProgressColor;
                double d = this.Element.Progress < 1 ? this.Element.Progress * 100 : this.Element.Progress;
                progress.Progress = (int)d;
    
                SetNativeControl(progress);
            }
    
            protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
            {
                base.OnElementPropertyChanged(sender, e);
                if (this.Element == null || this.Control == null) return;
    
                if (e.PropertyName == KalideaMobile.Resources.Controls.ProgressBar.ProgressColorProperty.PropertyName)
                {
                    //progress.ProgressColor = this.Element.ProgressColor;
                }
                else if (e.PropertyName == KalideaMobile.Resources.Controls.ProgressBar.ProgressProperty.PropertyName)
                {
                    Control.Progress = (int)this.Element.Progress;
                }
    
            }
        }
    }
    
  • SteeveLeDreauSteeveLeDreau Steeve Le Dreau FRMember

    Hi again, i find a way to change it. But not with the value of my dependency property.
    I add an AndroidResource in my drawable folder with this :
    <?xml version="1.0" encoding="utf-8"?>

        <item android:id="@android:id/background">
            <shape>
                <corners android:radius="5dip"/>
                <gradient
                    android:startColor="#000000"
                    android:centerColor="#736F6E"
                    android:centerY="0.75"
                    android:endColor="#999999"
                    android:angle="270"/>
            </shape>
        </item>
    
        <item android:id="@android:id/secondaryProgress">
            <clip>
                <shape>
                    <corners android:radius="5dip"/>
                    <gradient
                        android:startColor="#FF0000"
                        android:centerColor="#8B0000"
                        android:centerY="0.75"
                        android:endColor="#8B0000"
                        android:angle="270"/>
                </shape>
            </clip>
        </item>
    
        <item android:id="@android:id/progress">
            <clip>
                <shape>
                    <corners
                        android:radius="5dip"/>
                    <gradient
                        android:startColor="#4fc1e9"
                        android:endColor="#1482a8"
                        android:angle="270"/>
                </shape>
            </clip>
        </item>
    
    </layer-list>
    

    The renderer :

    public class ProgressBarCustomRenderer : ViewRenderer<KalideaMobile.Resources.Controls.ProgressBar, Android.Widget.ProgressBar>
    {
    public ProgressBarCustomRenderer()
        : base()
    {
    }
    
    protected override void OnElementChanged(ElementChangedEventArgs<KalideaMobile.Resources.Controls.ProgressBar> e)
    {
        base.OnElementChanged(e);
        if (e.OldElement != null || this.Element == null) return;
    
        // Dont work : have to create it on a new control.
        //Control.ProgressDrawable = Resources.GetDrawable(Resource.Drawable.style_progressBar);
    
        var progress = new Android.Widget.ProgressBar(Forms.Context, null, Android.Resource.Attribute.ProgressBarStyleHorizontal);
        progress.Progress = GetProgressionElement();
        progress.ProgressDrawable = Resources.GetDrawable(Resource.Drawable.style_progressBar);
        SetNativeControl(progress);
    }
    
    protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        base.OnElementPropertyChanged(sender, e);
        if (this.Element == null || this.Control == null) return;
    
        if (e.PropertyName == KalideaMobile.Resources.Controls.ProgressBar.ProgressColorProperty.PropertyName)
        {
            Control.ProgressDrawable = Resources.GetDrawable(Resource.Drawable.style_progressBar);
        }
        else if (e.PropertyName == KalideaMobile.Resources.Controls.ProgressBar.ProgressProperty.PropertyName)
        {
            Control.Progress = GetProgressionElement();
        }
    }
    
    private int GetProgressionElement()
    {
        return (int)(this.Element.Progress * 100);
    }
    }
    
  • ajinajin ajin USMember

    Hi,

    I downloaded the source code and try to implement the same in my project. I got an issue like "HoloCircularProgressBar" is not defined. I Couldn't find the 'com.refractored.monodroidtoolkit' either. I am using xamarin forms 1.4.2.6359

  • JamesMontemagnoJamesMontemagno James Montemagno USForum Administrator, Xamarin Team, Developer Group Leader Xamurai

    @ajin did you add https://www.nuget.org/packages/MonoDroid.Toolkit/ nuget to your android project?

  • ajinajin ajin USMember

    Hi James,

    Thanks for the help. It now worked. But I have a question. The width and height are now provided as 300 each. If i reduce it to 60 so that I want a small progress bar, I can see the size get reduced but the progress bar( the blue rectangle bar) size is not reduced. only the circle size get reduced, the bar remains the same.

    Is there any way to reduce the size of that bar?

Sign In or Register to comment.