1.继承View组件,比如,LabelView继承了View
 
2.重写两个构造方法,比如,对于自定义View LabelView
 
LabelView(Context context),如果该自定义View是通过代码来实例化的,那么,就需要该构造方法;
LabelView(Context context, AttributeSet attrs),通过布局文件XML来使用该自定义View,那么,就需要该构造方法。
 
    /**
     * Constructor.  This version is only needed if you will be instantiating
     * the object manually (not from a layout XML file).
     * @param context
     */
    public LabelView(Context context) {
        super(context);
        initLabelView();
    }
 /**
     * Construct object, initializing with any attributes we understand from a
     * layout file. These attributes are defined in
     * SDK/assets/res/any/classes.xml.
     *
     * @see android.view.View#View(android.content.Context, android.util.AttributeSet)
     */
    public LabelView(Context context, AttributeSet attrs) {
        super(context, attrs);
   ....
     }
 
3.重写onDraw(Canvas canvas)和onMeasure(int measureWidth, int measureHeight)
 
onDraw(Canvas canvas),在实现自定义View的时候,你自己要创建一个Paint对象,用来设置自定义View的外观,尺寸,颜色。
然后,再在onDraw方法中,将图形绘制在系统传递过来的画布对象Canvas。
也就是说,系统回调onDraw来实现自定义View的渲染。
 
onMeasure(int measureWidth, int measureHeight),系统回调该方法,告诉你现在自定义View的宽度和高度是怎样设置的。
通过MeasureSpec.getMode(measureWidth),MeasureSpec.getSize(measureWidth)可以得到当前宽度的模式和大小。通过模式,可以知道用户设置的是wrap,match_parent,还是设置一个具体值,还说没有任何限制;通过大小,可以知道,当前系统检测到的当前View组件的宽度。
 
在得到这些信息后,你可以自己自定义,设置你想要的View组件的宽度和高度。
 
 
上面三个,就是自定义View的关键步骤。
 
-----------------------------------------------------------
 
其它方面:
1.Paint对象和Canvas的使用
 
要绘制一个自定义View,首先,你自己要确定出,图形的最终样式。按照最终样式,使用Paint对象,绘制出最终样式。Canvas对象的使用也需要关注。所以,在绘制图形的时候,要知道怎么使用Paint对象和Canvas绘制出最终的图形。
 
这方面的知识,需要补充。
 
 
2.属性设置
用户在使用你实现的自定义View的时候,它想自己定义View的属性,它想通过View提供的属性控制View的外观,尺寸,颜色等特征。那么,你实现的自定义View,就要提供给用户设置属性,并且要接收到用户传递过来的属性值,根据这些属性值构造出Paint对象。
这个的实现步骤:
1).在res目录下的values目录,创建一个attrs.xml,然后,在里面添加属性描述。如下:声明了三个属性。
 
2).然后,在自定义View的类中,声明setter方法,如下:
根据用户传递过来的属性,重新绘制自定义VIew。requestLayout()的调用,会触发系统回调onMeasure(int measureWidth, int measureHeight)方法;invalidate()的调用,会触发系统回调onDraw()方法。
/**
        * Sets the text to display in this label
        *
        * @param text
        *            The text to display. This will be drawn as one line.
        */
        public void setText(String text) {
               mText = text;
               requestLayout();
              invalidate();
       }
 
 
3).在使用该自定义View的布局文件中,要声明该自定义View的命名空间,如下:
声明了一个命名空间
xmlns:app = "http://schemas.android.com/apk/res/com.example.customview"
红色部分,是该自定义View所在的包。
然后,你就可以使用app:text,这样命名空间加属性名的方式来设置属性。属性名,与attrs.xml中声明名字一样。
< RelativeLayout xmlns:android ="http://schemas.android.com/apk/res/android"
    xmlns:tools= "http://schemas.android.com/tools"
    xmlns:app= "http://schemas.android.com/apk/res/com.example.customview"
    android:layout_width= "match_parent"
    android:layout_height= "match_parent" >
 
    <com.example.customview.LabelView
        android:id ="@+id/oneLabelView"
        android:layout_width ="wrap_content"
        android:layout_height ="wrap_content"
        app:text= "Somethine"
        app:textColor ="#00868B"
        app:textSize ="34sp" />
 
</ RelativeLayout>
 
---------------下面是实现例子--------------------------
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View; /**
* Example of how to write a custom subclass of View. LabelView is used to draw
* simple text views. Note that it does not handle styled text or right-to-left
* writing systems.
*
*/
public class LabelView extends View {
private Paint mTextPaint;
private String mText;
private int mAscent; /**
* Constructor. This version is only needed if you will be instantiating the
* object manually (not from a layout XML file).
*
* @param context
*/
public LabelView(Context context) {
super(context);
initLabelView();
} /**
* Construct object, initializing with any attributes we understand from a
* layout file. These attributes are defined in
* SDK/assets/res/any/classes.xml.
*
* @see android.view.View#View(android.content.Context,
* android.util.AttributeSet)
*/
public LabelView(Context context, AttributeSet attrs) {
super(context, attrs);
initLabelView(); TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.LabelView); CharSequence s = a.getString(R.styleable.LabelView_text);
if (s != null) {
setText(s.toString());
} // Retrieve the color(s) to be used for this view and apply them.
// Note, if you only care about supporting a single color, that you
// can instead call a.getColor() and pass that to setTextColor().
setTextColor(a.getColor(R.styleable.LabelView_textColor, 0xFF000000)); int textSize = a.getDimensionPixelOffset(
R.styleable.LabelView_textSize, 0);
if (textSize > 0) {
setTextSize(textSize);
} a.recycle();
} private final void initLabelView() {
mTextPaint = new Paint();
mTextPaint.setAntiAlias(true);
// Must manually scale the desired text size to match screen density
mTextPaint.setTextSize(16 * getResources().getDisplayMetrics().density);
mTextPaint.setColor(0xFF000000);
setPadding(3, 3, 3, 3);
} /**
* Sets the text to display in this label
*
* @param text
* The text to display. This will be drawn as one line.
*/
public void setText(String text) {
mText = text;
requestLayout();
invalidate();
} /**
* Sets the text size for this label
*
* @param size
* Font size
*/
public void setTextSize(int size) {
// This text size has been pre-scaled by the getDimensionPixelOffset
// method
mTextPaint.setTextSize(size);
requestLayout();
invalidate();
} /**
* Sets the text color for this label.
*
* @param color
* ARGB value for the text
*/
public void setTextColor(int color) {
mTextPaint.setColor(color);
invalidate();
} /**
* @see android.view.View#measure(int, int)
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(measureWidth(widthMeasureSpec),
measureHeight(heightMeasureSpec));
} /**
* Determines the width of this view
*
* @param measureSpec
* A measureSpec packed into an int
* @return The width of the view, honoring constraints from measureSpec
*/
private int measureWidth(int measureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec); if (specMode == MeasureSpec.EXACTLY) {
// We were told how big to be
result = specSize;
} else {
// Measure the text
result = (int) mTextPaint.measureText(mText) + getPaddingLeft()
+ getPaddingRight();
if (specMode == MeasureSpec.AT_MOST) {
// Respect AT_MOST value if that was what is called for by
// measureSpec
result = Math.min(result, specSize);
}
} return result;
} /**
* Determines the height of this view
*
* @param measureSpec
* A measureSpec packed into an int
* @return The height of the view, honoring constraints from measureSpec
*/
private int measureHeight(int measureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec); mAscent = (int) mTextPaint.ascent();
if (specMode == MeasureSpec.EXACTLY) {
// We were told how big to be
result = specSize;
} else {
// Measure the text (beware: ascent is a negative number)
result = (int) (-mAscent + mTextPaint.descent()) + getPaddingTop()
+ getPaddingBottom();
if (specMode == MeasureSpec.AT_MOST) {
// Respect AT_MOST value if that was what is called for by
// measureSpec
result = Math.min(result, specSize);
}
}
return result;
} /**
* Render the text
*
* @see android.view.View#onDraw(android.graphics.Canvas)
*/
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawText(mText, getPaddingLeft(), getPaddingTop() - mAscent,
mTextPaint);
}
}

自定义View的实现流程的更多相关文章

  1. 自定义View分类与流程

    自定义View分类与流程(进阶篇)## 转载出处: http://www.gcssloop.com/customview/CustomViewProcess/ 自定义View绘制流程函数调用链(简化版 ...

  2. Android查缺补漏(View篇)--自定义 View 的基本流程

    View是Android很重要的一部分,常用的View有Button.TextView.EditView.ListView.GridView.各种layout等等,开发者通过对这些View的各种组合以 ...

  3. 自定义View的基本流程

    1.明确需求,确定你想实现的效果2.确定是使用组合控件的形式还是全新自定义的形式,组合控件即使用多个系统控件来合成一个新控件,你比如titilebar,这种形式相对简单,参考:http://blog. ...

  4. 从一个简洁的进度刻度绘制中了解自定义View的思路流程

    先看效果(原谅我的渣像素),进度的刻度.宽度.颜色可以随意设定: [项目github地址: https://github.com/zhangke3016/CircleLoading] 实现起来并不难, ...

  5. 自定义View(1)简单流程及示例模板

    1,继承View , ViewGroup,或TextView等等 2,绘制相关的api, canvas 画布, paint 画笔 2,重写重要的函数(注意这个顺序) onMeasure 属于View的 ...

  6. 自定义控件(视图)2期笔记01:自定义控件之自定义View的步骤

    1. 根据Android Developers官网的介绍,自定义控件你需要以下的步骤: (1)创建View (2)处理View的布局 (3)绘制View (4)与用户进行交互 (5)优化已定义的Vie ...

  7. Android -- 自定义view实现keep欢迎页倒计时效果

    1,最近打开keep的app的时候,发现它的欢迎页面的倒计时效果还不错,所以打算自己来写写,然后就有了这篇文章. 2,还是老规矩,先看一下我们今天实现的效果 相较于我们常见的倒计时,这次实现的效果是多 ...

  8. Android查缺补漏(View篇)--自定义View利器Canvas和Paint详解

    上篇文章介绍了自定义View的创建流程,从宏观上给出了一个自定义View的创建步骤,本篇是上一篇文章的延续,介绍了自定义View中两个必不可少的工具Canvas和Paint,从细节上更进一步的讲解自定 ...

  9. 自定义View实战--实现一个清新美观的加载按钮

    本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布 在 Dribble 上偶然看到了一组交互如下: 当时在心里问自己能不能做,答案肯定是能做的,不过我比较懒,觉得中间那个伸缩变化要编写 ...

随机推荐

  1. 20145214 《Java程序设计》第10周学习总结

    20145214 <Java程序设计>第10周学习总结 学习内容总结 计算机网络概述 在计算机网络中,现在命名IP地址的规定是IPv4协议,该协议规定每个IP地址由4个0-255之间的数字 ...

  2. 从电梯问题,看c和c++之间的区别(有点懂了)错觉错觉

    磕磕碰碰的也相继用c和c++构造了不少的电梯了.虽然对自我的表现不满意,但是总体来说还是有一定的收获的,对于c和c++之间的区别感觉也摸到了一点点门道了... 用c语言构造电梯的步骤: 第一步: 分析 ...

  3. TCP系列12—重传—2、Linux超时重传引入示例

    在前面我们概述了TCP的超时重传之后我们简单的看一下tcp超时重传的示例.首先简单的描述一下测试过程 1.设置/proc/sys/net/ipv4/tcp_early_retrans为2,关掉TLP功 ...

  4. 团队组队&灰化肥挥发会发黑

    1. 队伍展示 (1. 队名: 灰化肥挥发会发黑 (2. 队员风采 苏叶潇(队长) 201521123114 与众不同,擅长软件测试,对编程望而却步,希望成为测试人员. 宣言:不求最好,只求更好. 李 ...

  5. js图片转换为base64

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. VMbox复制虚拟机后网卡问题-bring up interface eth0:Device eth0 does not seem to be present

    1.使用 ifconfig -a 查看mac地址 eg:HWaddr:08:00:29:B2:2B   2.vi /etc/sysconfig/network-scripts/ifcfg-eth0 将 ...

  7. MySQL & export

    MySQL & export mysql export table form command line https://cn.bing.com/search?q=mysql%20export% ...

  8. JavaScript Array 类型

    除 Object类型外,Array 类型算是ECMAScript中最常用的类型了,而且,ECMAScript中的数组和其他多数语言的数组有着非常大的差别,虽然这些数组都是数据的有序列表,但与其他语言不 ...

  9. 【bzoj1614】[Usaco2007 Jan]Telephone Lines架设电话线 二分+SPFA

    题目描述 Farmer John打算将电话线引到自己的农场,但电信公司并不打算为他提供免费服务.于是,FJ必须为此向电信公司支付一定的费用. FJ的农场周围分布着N(1 <= N <= 1 ...

  10. css之display样式,padding,margin

    1. 块级标签变成行内标签 <!DOCTYPE html> <html lang="en"> <head> <meta charset=& ...