[Xamarin.Android] 自定义控件

前言

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

建立自定义控件

在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;
    }
    } // ......
    }

  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);
    }
    } // ......
    }

  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);
    } // ......
    }

使用自定义控件

完成建立自定义控件的开发步骤后,接下来就是将自定义控件加入到项目之中。在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;
    };
    }
    }

范例下载

范例程序代码:点此下载

[Xamarin.Android] 自定义控件的更多相关文章

  1. [置顶] xamarin android自定义标题栏(自定义属性、回调事件)

    自定义控件的基本要求 这篇文章就当是自定义控件入门,看了几篇android关于自定义控件的文章,了解了一下,android自定义控件主要有3种方式: 自绘控件:继承View类,所展示的内容在OnDra ...

  2. [置顶] xamarin android toolbar(踩坑完全入门详解)

    网上关于toolbar的教程有很多,很多新手,在使用toolbar的时候踩坑实在太多了,不好好总结一下,实在浪费.如果你想学习toolbar,你肯定会去去搜索androd toolbar,既然你能看到 ...

  3. Xamarin.Forms 自定义控件(呈现器和效果)

    Xamarin.Forms 使用目标平台的本机控件呈现用户界面,从而让 Xamarin.Forms 应用程序为每个平台保留了相应的界面外观.凭借效果,无需进行自定义呈现器实现,即可自定义每个平台上的本 ...

  4. XAMARIN.ANDROID SIGNALR 实时消息接收发送示例

    SignalR 是一个开发实时 Web 应用的 .NET 类库,使用 SignalR 可以很容易的构建基于 ASP.NET 的实时 Web 应用.SignalR 支持多种服务器和客户端,可以 Host ...

  5. XAMARIN ANDROID 二维码扫描示例

    现在二维码的应用越来越普及,二维码扫描也成为手机应用程序的必备功能了.本文将基于 Xamarin.Android 平台使用 ZXing.Net.Mobile  做一个简单的 Android 条码扫描示 ...

  6. 我正在使用Xamarin的跨平台框架—Xamarin.Android回忆录

    一.缘起 在自己给别家公司做兼职外包的时候,已经明确知道外包的活不是那么好干的,一般在经历了初期热血澎湃的激情后,逐渐冷淡,愤怒,再冷淡,再愤怒…,听上去好像高潮迭起,但令人尴尬的是,这高潮迭起我们都 ...

  7. APP并非一个人在战斗,还有API—Xamarin.Android回忆录

    前言 一般来说,一个客户端APP并非独立存在的,很多时候需要与服务器交互.大体可分为两方面的数据,常规字符串数据和文件数据,因为这两种数据很可能传输方式不一样,比如字符串之类的数据,使用HTTP协议, ...

  8. Xamarin.Android通知详解

    一.发送通知的机制 在日常的app应用中经常需要使用通知,因为服务.广播后台活动如果有事件需要通知用户,则需要通过通知栏显示,而在Xamarin.Android下的通知需要获取Notification ...

  9. Xamarin.Android之SQLiteOpenHelper

    一.前言 在手机中进行网络连接不仅是耗时也是耗电的,而耗电却是致命的.所以我们就需要数据库帮助我们存储离线数据,以便在用户未使用网络的情况下也可以能够使用应用的部分功能,而在需要网络连接的功能上采用提 ...

随机推荐

  1. Android实战技巧:深入解析AsyncTask

    AsyncTask的介绍及基本使用方法 关于AsyncTask的介绍和基本使用方法可以参考官方文档和Android实战技巧:多线程AsyncTask这里就不重复. AsyncTask引发的一个问题 上 ...

  2. mysql 启动错误-server PID file could not be found

    [root@centos var]# service mysqld stop MySQL manager or server PID file could not be found!       [F ...

  3. JRE和JDK

    转自:http://www.cnblogs.com/myitm/archive/2011/05/03/2035942.html   很多程序员已经干了一段时间java了依然不明白jdk与jre的区别. ...

  4. CommonJS 模块规范 1.1.1

    本规范致力于描述一类可以同时适用于客户端和服务器端的模块系统.该系统中的模块拥有自己的作用域,可以从其他模块导入单例对象,或者对外提供 API. Require require 是一个函数对象. re ...

  5. 获取当前 Python 版本

    方法一 >>> from platform import python_version >>> print python_version() 2.7.8 方法二 & ...

  6. 不同gdb,相同数据集合并

    众所周知,数据处理是GIS中一项重要且繁琐的工作,处理数据的工具和方法也太多了,在做数据处理的时候,经常会遇到这样的问题:对存储在不同gdb中.并且数据集名称相同的数据进行合并处理: 如图:数据组织如 ...

  7. Apache+tomcat+mod_jk+centos6.2负载均衡集群配置--转载

    转载地址:http://blog.163.com/chenhui_java/blog/static/17267249420128101191860/ 注: 由于长期受转载毒害,所以本人日志均是原创:其 ...

  8. RTX发送消息提醒实现以及注意事项

    一.RTX简介 RTX是腾讯公司推出的企业级即时通信平台.该平台定位于降低企业通信费用,增强企业内部沟通能力,改善企业与客户之间的沟通渠道,创造新兴的企业沟通文化,提高企业生产力.RTX平台的主要功能 ...

  9. Supervisor – 用于 Unix 系统的进程监控工具

    Supervisor 是一个客户端/服务端模式的系统,使用户能够监视和控制 UNIX 操作系统的进程.Supervisor 为你提供一个地方来启动,停止和监视进程.进程可以单独或成组的形式控制.您还可 ...

  10. 【HTML5】Canvas 实现放大镜效果

    图片放大镜 效果 在线演示    源码 原理 首先选择图片的一块区域,然后将这块区域放大,然后再绘制到原先的图片上,保证两块区域的中心点一致, 如下图所示: 初始化 <canvas id=&qu ...