自定义视图最重要的部分是它的外观.你可以根据应用的需求简单或复杂的实现它. 这个教程包含了最常见的操作.
重写onDraw()
绘制自定义视图里最重要的一步是重写onDraw())方法. onDraw())的参数是视图可以用来绘制自己的Canvas对象. Canvas定义用来绘制文本、线条、位图和其他图像单元. 你可以在onDraw())里使用这些方法创建你的自定义用户界面(UI).
不过, 在你调用任何绘画的方法之前, 你必须创建Paint对象. 下一章节将会探讨Paint的更多细节.
创建绘画对象
android.graphics框架把绘图分成了两部分:
例如, Canvas提供画线条的方法, 而Paint提供定义线条颜色的方法. Canvas提供画矩形的方法, 而Paint定义是否用颜色填充矩形或让它为空. 简而言之, Canvas定义你可以在屏幕上画的形状, 而Paint为你画的每个形状定义颜色、样式、字体等等.
所以, 在你画任何东西之前, 你需要创建一个或多个Paint对象. * PieChart_'(饼图)例子的'_init()* 方法里有这样的实现, 这个方法在构造函数里调用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
private void init() {
mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mTextPaint.setColor(mTextColor);
if (mTextHeight == 0) {
mTextHeight = mTextPaint.getTextSize();
} else {
mTextPaint.setTextSize(mTextHeight);
}
mPiePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPiePaint.setStyle(Paint.Style.FILL);
mPiePaint.setTextSize(mTextHeight);
mShadowPaint = new Paint(0);
mShadowPaint.setColor(0xff101010);
mShadowPaint.setMaskFilter(new BlurMaskFilter(8, BlurMaskFilter.Blur.NORMAL));
...
|
提前创建对象是一个很重要的优化. 视图频繁的被重画, 并且许多绘图对象初始化需要消耗大量的资源. 在onDraw())方法里创建绘图对象会严重降低性能, 并可以让你的UI显得有些迟钝.
处理布局事件
为了正确的绘制你的自定义视图, 你需要知道它的大小. 复杂的自定义视图经常需要根据它的大小和在屏幕上的图形区域执行多次布局计算. 你永远不应该假设视图在屏上的大小. 即使只有一个应用使用你的视图, 应用也需要处理不同的屏幕尺寸, 多种屏幕分辨率, 以及在横屏和竖屏模式下的各种高宽比.
虽然View有很多处理尺寸大小的方法, 但是大部分的需要重写. 如果你的视图不需要特别控制它的大小, 你只需要重写方法: onSizeChanged() .
onSizeChanged()在你的视图第一次分配大小的时候调用, 如果你的视图因为任何原因改变了大小也会再次调用. 在该方法里计算位置、大小和其他一些与视图大小相关的值, 而不是你每次绘制的时候重新计算. 在PieChart(饼图)例子里, PieChar视图在onSizeChanged()里计算饼图的图形边界、文本标签的相对位置和其他视觉元素.
当你的视图分配了一个大小, 布局管理器会假设这个大小包含了所有视图的padding值. 你必须在计算你视图的大小的时候处理padding值. 下面是PieChart.onSizeChanged()中处理这个的代码片段:
1 2 3 4 5 6 7 8 9 10 11 12 |
// Account for padding
float xpad = (float)(getPaddingLeft() + getPaddingRight());
float ypad = (float)(getPaddingTop() + getPaddingBottom());
// Account for the label
if (mShowText) xpad += mTextWidth;
float ww = (float)w - xpad;
float hh = (float)h - ypad;
// Figure out how big we can make the pie.
float diameter = Math.min(ww, hh);
|
如果你需要出色的控制你视图的布局参数, 实现int) onMeasure()方法. 这个方法的参数是View.MeasureSpec值, 这个会告诉你你的视图的父元素想让你的视图有多大, 并且告诉你这个大小是否是最大值或只是一个建议. 作为优化, 这些值保存为整数的封装类型, 你可以用View.MeasureSpec里的静态方法解析每个整数里面的信息.
下面是实现int) onMeasure()的例子. 在这个实现里面, PieChart尝试让它的面积大小足以让饼图可以标签一样大:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// Try for a width based on our minimum
int minw = getPaddingLeft() + getPaddingRight() + getSuggestedMinimumWidth();
int w = resolveSizeAndState(minw, widthMeasureSpec, 1);
// Whatever the width ends up being, ask for a height that would let the pie
// get as big as it can
int minh = MeasureSpec.getSize(w) - (int)mTextWidth + getPaddingBottom() + getPaddingTop();
int h = resolveSizeAndState(MeasureSpec.getSize(w) - (int)mTextWidth, heightMeasureSpec, 0);
setMeasuredDimension(w, h);
}
|
在这段代码中有三个重点需要注意:
-
- 计算需要考虑视图的padding. 如上所述, 这个是视图的职责.
-
- 方法resolveSizeAndState()用来创建最终的宽和高. 这个方法通过比较视图的期望大小返回一个合适的View.MeasureSpec值传入int) onMeasure()
-
- onMeasure()方法没有返回值. 相反, 这个方法通过调用int) setMeasureDismension()方法传递结果. 调用这个方法是强制的. 如果你省略这个, View类会抛出runtime exception
绘图
一旦你有了创建的对象和定义了测绘布局的代码, 你可以实现方法onDraw()) . 每个视图实现不同的onDraw()) , 但是这里有些大多数视图常用的操作:
-
使用drawText()画文本, setTypeface())指定字体, setColor())指定文本颜色
-
画基本的形状用drawRect()) 、drawOval()) 、drawArc()) . 不论改变图形的填充样式还是边框样式还是都修改, 都是调用setStyle())
-
绘制复杂的形状用Path类. 通过给Path对象增加线条和曲线定义形状, 然后使用drawPath())绘制形状. 就像基本的形状一样, Path可以设置填充样式、边框样式、或者都设置, 都依靠setStyle())
-
定义渐变的填充样式通过创建LinearGradient对象. 在要填充的形状上通过调用setShader())使用LinearGradient对象
-
绘制位图使用drawBitmap()) .
例如, 这是是画PieChart的代码. 它混合使用了文本、线条、图形.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// Draw the shadow
canvas.drawOval(
mShadowBounds,
mShadowPaint
);
// Draw the label text
canvas.drawText(mData.get(mCurrentItem).mLabel, mTextX, mTextY, mTextPaint);
// Draw the pie slices
for (int i = 0; i < mData.size(); ++i) {
Item it = mData.get(i);
mPiePaint.setShader(it.mShader);
canvas.drawArc(mBounds,
360 - it.mEndAngle,
it.mEndAngle - it.mStartAngle,
true, mPiePaint);
}
// Draw the pointer
canvas.drawLine(mTextX, mPointerY, mPointerX, mPointerY, mTextPaint);
canvas.drawCircle(mPointerX, mPointerY, mPointerSize, mTextPaint);
}
|
相关推荐
android中自定义视图view的讲解,有很多现有的例子可以进行使用,非常方便
这是一个示例应用程序,它使用 Android 旋转传感器并使用自定义视图(姿态指示器,又名“人工...绘制自定义视图,包括使用 Porter-Duff 传输模式创建抗锯齿圆形切口。 更多详情、使用方法,请下载后细读README.md文件
通过本示例的学习,初学者可快速掌握自定义控件的开发技巧。本例是博文http://blog.csdn.net/l1028386804/article/details/47337949的完整代码,如想了解实现细节,请参考博文:...
Android中View(视图)绘制不同状态背景图片原理深入分析Android中View(视图)绘制不同状态背景图片原理深入分析Android中View(视图)绘制不同状态背景图片原理深入分析Android中View(视图)绘制不同状态背景图片原理深入...
本文主要介绍了Android视图树绘制指示器的实现原理和具体步骤。具有一定的参考价值,下面跟着小编一起来看下吧
android-swt-演示演示如何使用桌面 Java 和 SWT 显示 Android 自定义绘制视图的原型这个原型包括两个项目: DrawIt - 一个非常简单的 Android 应用程序,其中包含一个自定义绘制的视图 (TestView) AndroidPaint - 一...
自定义View学习之几何图形的绘制:维度图表绘制(模仿京东白条个人信用评分维普图的绘制)
ches Orchestra是Jetpack Compose的Android自定义视图兼容库的集合。 Orchestra:trumpet:Jetpack使用Balloon,ColorPickerView,PowerSpinner编写兼容的库。 气球并将依赖项代码添加到模块的build.gradle文件中。 ...
Android自定义视图的终极指南 过去五年来,我一直在设计,编写和发布Android自定义视图。 我想现在是时候总结一下并分享结果了。 在这里,您将找到与自定义视图和几个案例研究相关的主题。 代码样本将随机使用Java...
Android的AchievementView用于以Kotlin编写的成就弹出式窗口的自定义视图。 基本属性可以通过XML进行更改,例如其大小,颜色,可绘制,持续时间。 如果还不够的话,请随意将其自定义为Android的AchievementView。用...
// TODO 自动生成的方法存根 super.onDraw(canvas); int width = this.getWidth(); int height = this.getHeight(); width = (width > height) ? height : width; height = (width > height) ? height : ...
Android的DrawingView描述DrawingView允许用户使用不同的画笔进行绘制并提供一些功能。特征提供多种刷子在图像上绘图撤消/重做操作放大/缩小和翻译在BrushView中预览选定的画笔自定义背景色将工程图导出为位图演示版...
自定义的view,可以放在xml文件中和自带的控件一样的布局。有折线图、柱状图和饼图
支持月视图,周视图,年视图,自定义周开始,农历日历等。 热插拔UI定制! 您无法想到日历会如此优雅! AndroidStudio v3.5 + 支持版本(如果使用支持包) implementation 'com.haibin:calendarview:3.6.8' 如果...
一个允许用户签名或绘图的 Android 自定义视图,它将被保存到输出流中。 特殊的是你可以画一条平滑的线,笔画的大小会随着你的速度逐渐变化。 您应该关注两个值: 符号:filterWeight="0.2" 符号:strokeSize="@...
Android自定义声音振动曲线view,实现声波的View视图绘制。颜色、粗细、长度、大小都可进行动态设置。
[Android视图绘制流程完全解析,带你一步步深入了解View(二)](http://blog.csdn.net/guolin_blog/article/details/16330267) ###4、笔者自定View相关文章 [给自定义View添加xml属性]...
3、随机生成坐标点绘制每条TextItem,不断变换Text的横坐标实现弹幕的滚动 首先创建弹幕类,弹幕包括坐标,颜色,滚动速度,以及文字内容: public class Textitem { private String content; private float fx;...
custom工程演示了App开发的自定义控件相关知识,包括:自定义视图的步骤(声明属性、构造对象、测量尺寸、绘制视图)、自定义简单动画(任务片段、下拉刷新动画、圆弧进度动画)、自定义对话框的操作(对话框、改进...
遮罩视图