[Xamarin.Android] 自定义控件

[Xamarin.Android] 自定义控件

前言

软件项目开发的过程中,免不了遇到一些无法使用内建控件就能满足的客户需求,例如:时速表、折线图...等等。这时开发人员可以透过自定义控件的方式,为项目量身打造控件,来提供更加贴近用户需求的使用界面。本篇文章介绍在开发Xamarin.Android项目的时候,如何建立自定义控件,为自己留个纪录也希望能帮助到有需要的开发人员。

前言01

建立自定义控件

在Xamarin.Android项目中,有许多种方式可以建立自定义控件,本篇文章的范例采用继承View、覆写OnDraw的方式来实作自定义控件。

  1. 首先在Xamarin.Android项目中,加入一个类别:「CountMeter」,并且让CountMeter继承Android.Views.View以及实作对应Android.Views.View的建构子。

    public sealed class CountMeter : View
    {
        // Constructors
        public CountMeter(Context context) : base(context) { }
    
        public CountMeter(Context context, IAttributeSet attributeSet) : base(context, attributeSet) { }
    
        public CountMeter(Context context, IAttributeSet attributeSet, int defaultStyle) : base(context, attributeSet, defaultStyle) { }        
    
        // ......
    }
    
  2. 接着在CountMeter类别中,覆写Android.Views.View的OnMeasure方法,让自定义控件能够正确显示android:layoutwidth、android:layoutheight...等等尺寸设定。

    public sealed class CountMeter : View
    {
        // Fields
        private readonly int _defaultWidth = 400;
    
        private readonly int _defaultHeight = 210;
    
    
        // Methods
        protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
        {
            // Base
            base.OnMeasure(widthMeasureSpec, heightMeasureSpec);
    
            // Size
            this.SetMeasuredDimension(this.MeasureSize(widthMeasureSpec, _defaultWidth), this.MeasureSize(heightMeasureSpec, _defaultHeight));
        }
    
        private int MeasureSize(int measureSpec, int defaultSize)
        {
            // Size
            var specSize = MeasureSpec.GetSize(measureSpec);
    
            // Measure
            switch (MeasureSpec.GetMode(measureSpec))
            {
                case MeasureSpecMode.AtMost: return Math.Min(specSize, defaultSize);
                case MeasureSpecMode.Exactly: return specSize;
                default: return defaultSize;
            }
        }
    
        // ......
    }
    

    建立01

  3. 接着在CountMeter类别中,覆写Android.Views.View的OnDraw方法,使用程序代码的方式来描绘自定义控件呈现在接口上的显示外观。而针对如何描绘控件外观,开发人员可以参考下列资料,学习如何透过Xamarin.Android所提供的绘图类别来使用图形描绘功能:「Xamarin>Android>Other UX>Drawing」。

    public sealed class CountMeter : View
    {
        // Fields
        private readonly int _defaultWidth = 400;
    
        private readonly int _defaultHeight = 210;
    
    
        // Methods
        protected override void OnDraw(Canvas canvas)
        {
            // Base
            base.OnDraw(canvas);
    
            // Background
            canvas.DrawColor(Color.White);
    
            // Paint   
            var paint = new Paint();
            paint.Color = Color.Red;
            paint.StrokeWidth = 10;
    
            // Size
            var x = 0;
            var y = 0;
            var width = this.Width;
            var height = this.Height - 10;
            var ellipseWidth = width;
            var ellipseHeight = height * 2;
            var scaleLength = 20;
            var spaceLength = 10;
    
            // Scale   
            paint.Color = Color.Red;
            for (int scaleCount = 0; scaleCount <= 100; scaleCount += 10)
            {
                var scaleAngle = 180f / 100f * scaleCount;
                var scaleOffset = scaleLength;
                var scalePoint1 = this.GetEllipsePoint(x, y, ellipseWidth, ellipseHeight, scaleAngle);
                var scalePoint2 = this.GetEllipsePoint(x + scaleOffset, y + scaleOffset, ellipseWidth - scaleOffset * 2, ellipseHeight - scaleOffset * 2, scaleAngle);
                canvas.DrawLine(scalePoint1.X, scalePoint1.Y, scalePoint2.X, scalePoint2.Y, paint);
            }
        }
    
        // ......
    }
    

    建立02

  4. 自定义控件除了呈现静态数据之外,更大的功用是用来呈现动态数据,例如:目前时速、目前温度、载货量...等等。要完成呈现动态数据的功能,开发人员必须要在自定义控件中加入对象属性、对象方法来提供外部程序输入动态数据。而控件内部程序,在更新数据之后,就可以依照资料内容来在画面上描绘出对应的显示图形。

    public sealed class CountMeter : View
    {
        // Fields
        private int _count = 0;
    
    
        // Properties
        public int Count
        {
            get
            {
                // Get
                return _count;
            }
            set
            {
                // Set
                _count = value;
    
                // Refresh
                this.Invalidate();
            }
        }
    
    
        // Methods
        protected override void OnDraw(Canvas canvas)
        {
            // Base
            base.OnDraw(canvas);
    
            // Background
            canvas.DrawColor(Color.White);
    
            // Paint   
            var paint = new Paint();
            paint.Color = Color.Red;
            paint.StrokeWidth = 10;
    
            // Size
            var x = 0;
            var y = 0;
            var width = this.Width;
            var height = this.Height - 10;
            var ellipseWidth = width;
            var ellipseHeight = height * 2;
            var scaleLength = 20;
            var spaceLength = 10;
    
            // Needle
            paint.Color = Color.Gold;
            var needleAngle = 180f / 100f * _count;
            var needleOffset = scaleLength + spaceLength;
            var needlePoint1 = this.GetEllipsePoint(x + needleOffset, y + needleOffset, ellipseWidth - needleOffset * 2, ellipseHeight - needleOffset * 2, needleAngle);
            var needlePoint2 = new PointF(width / 2, height);
            canvas.DrawLine(needlePoint1.X, needlePoint1.Y, needlePoint2.X, needlePoint2.Y, paint);
        }
    
        // ......
    }
    

    建立03

使用自定义控件

完成建立自定义控件的开发步骤后,接下来就是将自定义控件加入到项目之中。在Xamarin.Android项目中,有许多种方式可以将自定义控件,加入到实际处理用户接口Activity类别之中,本篇文章的范例采用直接加入axml档案的方式,在项目中使用自定义控件。

  • Main.axml

    <CustomControlSample.CountMeter
        android:id="@+id/MyCountMeter1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp" />
    

透过加入axml档案方式将自定义控制向加入项目之后,在实际处理用户接口Activity类别中,就可以跟内建控件一样透过FindViewById方法来取得控件,并且操作控件所提供方法、属性、事件,来提供更加贴近用户需求的使用界面。

  • MainActivity.cs

    [Activity(Label = "CustomControlSample", MainLauncher = true, Icon = "@drawable/icon")]
    public class MainActivity : Activity
    {
        // Fields
        private int _count = 0;
    
    
        // Methods
        protected override void OnCreate(Bundle bundle)
        {
            // Base
            base.OnCreate(bundle);
    
            // View
            this.SetContentView(Resource.Layout.Main);
    
            // CountMeter
            var countMeter1 = FindViewById<CountMeter>(Resource.Id.MyCountMeter1);
    
            // UpButton
            var upButton = FindViewById<Button>(Resource.Id.UpButton);
            upButton.Click += delegate
            {
                _count += 10;
                countMeter1.Count = _count;
            };
    
            // DownButton
            var downButton = FindViewById<Button>(Resource.Id.DownButton);
            downButton.Click += delegate
            {
                _count -= 10;
                countMeter1.Count = _count;
            };
        }
    }
    

    使用01

范例下载

范例程序代码:点此下载

转载于:https://www.cnblogs.com/clark159/p/4042908.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值