[Xamarin.Android] 自定义控件
[Xamarin.Android] 自定义控件
前言
软件项目开发的过程中,免不了遇到一些无法使用内建控件就能满足的客户需求,例如:时速表、折线图...等等。这时开发人员可以透过自定义控件的方式,为项目量身打造控件,来提供更加贴近用户需求的使用界面。本篇文章介绍在开发Xamarin.Android项目的时候,如何建立自定义控件,为自己留个纪录也希望能帮助到有需要的开发人员。
建立自定义控件
在Xamarin.Android项目中,有许多种方式可以建立自定义控件,本篇文章的范例采用继承View、覆写OnDraw的方式来实作自定义控件。
首先在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) { } // ......
}
接着在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;
}
} // ......
}
接着在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);
}
} // ......
}
自定义控件除了呈现静态数据之外,更大的功用是用来呈现动态数据,例如:目前时速、目前温度、载货量...等等。要完成呈现动态数据的功能,开发人员必须要在自定义控件中加入对象属性、对象方法来提供外部程序输入动态数据。而控件内部程序,在更新数据之后,就可以依照资料内容来在画面上描绘出对应的显示图形。
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] 自定义控件的更多相关文章
- [置顶]
xamarin android自定义标题栏(自定义属性、回调事件)
自定义控件的基本要求 这篇文章就当是自定义控件入门,看了几篇android关于自定义控件的文章,了解了一下,android自定义控件主要有3种方式: 自绘控件:继承View类,所展示的内容在OnDra ...
- [置顶]
xamarin android toolbar(踩坑完全入门详解)
网上关于toolbar的教程有很多,很多新手,在使用toolbar的时候踩坑实在太多了,不好好总结一下,实在浪费.如果你想学习toolbar,你肯定会去去搜索androd toolbar,既然你能看到 ...
- Xamarin.Forms 自定义控件(呈现器和效果)
Xamarin.Forms 使用目标平台的本机控件呈现用户界面,从而让 Xamarin.Forms 应用程序为每个平台保留了相应的界面外观.凭借效果,无需进行自定义呈现器实现,即可自定义每个平台上的本 ...
- XAMARIN.ANDROID SIGNALR 实时消息接收发送示例
SignalR 是一个开发实时 Web 应用的 .NET 类库,使用 SignalR 可以很容易的构建基于 ASP.NET 的实时 Web 应用.SignalR 支持多种服务器和客户端,可以 Host ...
- XAMARIN ANDROID 二维码扫描示例
现在二维码的应用越来越普及,二维码扫描也成为手机应用程序的必备功能了.本文将基于 Xamarin.Android 平台使用 ZXing.Net.Mobile 做一个简单的 Android 条码扫描示 ...
- 我正在使用Xamarin的跨平台框架—Xamarin.Android回忆录
一.缘起 在自己给别家公司做兼职外包的时候,已经明确知道外包的活不是那么好干的,一般在经历了初期热血澎湃的激情后,逐渐冷淡,愤怒,再冷淡,再愤怒…,听上去好像高潮迭起,但令人尴尬的是,这高潮迭起我们都 ...
- APP并非一个人在战斗,还有API—Xamarin.Android回忆录
前言 一般来说,一个客户端APP并非独立存在的,很多时候需要与服务器交互.大体可分为两方面的数据,常规字符串数据和文件数据,因为这两种数据很可能传输方式不一样,比如字符串之类的数据,使用HTTP协议, ...
- Xamarin.Android通知详解
一.发送通知的机制 在日常的app应用中经常需要使用通知,因为服务.广播后台活动如果有事件需要通知用户,则需要通过通知栏显示,而在Xamarin.Android下的通知需要获取Notification ...
- Xamarin.Android之SQLiteOpenHelper
一.前言 在手机中进行网络连接不仅是耗时也是耗电的,而耗电却是致命的.所以我们就需要数据库帮助我们存储离线数据,以便在用户未使用网络的情况下也可以能够使用应用的部分功能,而在需要网络连接的功能上采用提 ...
随机推荐
- 网上收集的以及自己总结的iOS开发技巧
Objective-C 1.让Xcode的控制台支持LLDB类型的打印 这有什么用? 怎么说尼,笔者认为这个还是比较有用滴,为什么有用尼? 因为在Xcode断点调试的时候, 在控制台输入 po sel ...
- php的单例模式
据说,单例模式是设计模式中最简单的一种. 不多说,先上代码,然后解说,一共两个文件: danli.class <?php class Danli { //保存类的实例的静态成员变量 static ...
- 做mapx、ArcEngine的二次开发出现“没有注册类别 (异常来自 HRESULT:0x80040154 (REGDB_E_CLASSNOTREG)”
转自:http://blog.sina.com.cn/s/blog_638e61a40100ynnc.html 出现这个问题主要是因为32位操作系统和64位操作系统存在兼容性问题. 解决方案: 1.鼠 ...
- DB2 v9.1 RACF 瞎学笔记
一.DB2 RACF control module 定义在prefix.SDSNSAMP(DSNXRXAC)中,查找一下数据集 符合*.SDSNSAMP数据集有两个,我这里使用的DB V9,自然pre ...
- Java 随机数
本章先讲解Java随机数的几种产生方式,然后通过示例对其进行演示. 广义上讲,Java中的随机数的有三种产生方式:(01). 通过System.currentTimeMillis()来获取一个当前时间 ...
- Web 项目可能会用到的20款优秀的开源工具
开源的应用程序和它们的源代码可以免费获得,因为版权是属于任何进行过修改或者提交代码的人.大多数提供开源软件的公司都可以建立行业标准,因此可以获得有利的竞争优势. 很多的开源应用程序和工具都有很强的替代 ...
- LeetCode-96. Unique Binary Search Trees
Description: Given n, how many structurally unique BST's (binary search trees) that store values 1.. ...
- LeetCode——Gas Station
There are N gas stations along a circular route, where the amount of gas at station i is gas[i]. You ...
- MySQL中的锁(表锁、行锁)
锁是计算机协调多个进程或纯线程并发访问某一资源的机制.在数据库中,除传统的计算资源(CPU.RAM.I/O)的争用以外,数据也是一种供许多用户共享的资源.如何保证数据并发访问的一致性.有效性是所在有数 ...
- HTML的学习
PS:最近已经进入实验室了,已经算是正式的成为其中的核心成员了,虽然自己学习的并不多.但是 相信自己通过努力能够走的越来越好.条件还是蛮不错的.这次给了一个关于WEB的项目,自己的还是 没有学完JAV ...