Android自定义控件之基本原理(一)

前言:

在日常的Android开发中会经常和控件打交道,有时Android提供的控件未必能满足业务的需求,这个时候就需要我们实现自定义一些控件,今天先大致了解一下自定义控件的要求和实现的基本原理。

自定义控件要求:

1. 应当遵守Android标准的规范(命名,可配置,事件处理等)。

2. 在XML布局中科配置控件的属性。

3. 对交互应当有合适的反馈,比如按下,点击等。

4. 具有兼容性, Android版本很多,应该具有广泛的适用性。

自定义控件学习步骤:

  1 .View的工作原理

  2 .编写View类

  3.为View类增加属性

  4 .绘制屏幕

  5. 响应用户消息

  6 .自定义回调函数

自定义控件两种方式:

  1. 继承ViewGroup

例如:ViewGroup、LinearLayout、FrameLayout、RelativeLayout等。

  2. 继承View

例如:View、TextView、ImageView、Button等。

自定义控件基本绘制原理:

View的绘制基本上由measure()、layout()、draw()这个三个函数完成

1.)测量-Measure过程是计算视图大小,View measure过程相关方法主要有三个:

public final void measure(int widthMeasureSpec, int heightMeasureSpec)
protected final void setMeasuredDimension(int measuredWidth, int measuredHeight)
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)

measure调用onMeasure,onMeasure测量宽度、高度然后调用setMeasureDimension保存测量结果,measure,setMeasureDimension是final类型,view的子类不需要重写,onMeasure在view的子类中重写。

关于MeasureSpec:

(1)UPSPECIFIED :父容器对于子容器没有任何限制,子容器想要多大就多大.

(2) EXACTLY父容器已经为子容器设置了尺寸,子容器应当服从这些边界,不论子容器想要多大的空间.

(3) AT_MOST子容器可以是声明大小内的任意大小.

2.)布局-Layout过程用于设置视图在屏幕中显示的位置,View layout过程相关方法主要要三个:

public void layout(int l, int t, int r, int b)
protected boolean setFrame(int left, int top, int right, int bottom)
protected void onLayout(boolean changed, int left, int top, int right, int bottom)

layout通过调用setFrame(l,t,r,b),l,t,r,b即子视图在父视图中的具体位置,onLayout一般只会在自定义ViewGroup中才会使用

3.)绘制-draw过程主要用于利用前两步得到的参数,将视图显示在屏幕上,到这里也就完成了整个的视图绘制工作。

public void draw(Canvas canvas)
protected void onDraw(Canvas canvas)

通过调用draw函数进行视图绘制,在View类中onDraw函数是个空函数,最终的绘制需求需要在自定义的onDraw函数中进行实现,比如ImageView完成图片的绘制,如果自定义ViewGroup这个函数则不需要重载。

自定义控件示例:

这里先介绍继承View的方式为例,其实ViewGroup最终的继承的也是View。这里 模拟一个需求场景,需要一个圆形显示百分比。

public class PercentView extends View {
private final static String TAG = PercentView.class.getSimpleName();
private Paint mPaint;
public PercentView(Context context) {
super(context);
}
public PercentView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public PercentView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
Log.e(TAG, "onMeasure--widthMode-->" + widthMode);
switch (widthMode) {
case MeasureSpec.EXACTLY:
break;
case MeasureSpec.AT_MOST:
break;
case MeasureSpec.UNSPECIFIED:
break;
}
Log.e(TAG, "onMeasure--widthSize-->" + widthSize);
Log.e(TAG, "onMeasure--heightMode-->" + heightMode);
Log.e(TAG, "onMeasure--heightSize-->" + heightSize);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
Log.e(TAG, "onLayout");
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setColor(Color.GRAY);
// FILL填充, STROKE描边,FILL_AND_STROKE填充和描边
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
int with = getWidth();
int height = getHeight();
Log.e(TAG, "onDraw---->" + with + "*" + height);
float radius = with / 4;
canvas.drawCircle(with / 2, with / 2, radius, mPaint);
mPaint.setColor(Color.BLUE);
RectF oval = new RectF(with / 2 - radius, with / 2 - radius, with / 2
+ radius, with / 2 + radius); //用于定义的圆弧的形状和大小的界限
canvas.drawArc(oval, 270, 120, true, mPaint); //根据进度画圆弧
}
}

在布局中如何使用

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.whoislcj.views.PercentView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp" />
</LinearLayout>

显示效果:

如果布局文件改成

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.whoislcj.views.PercentView
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_margin="10dp" />
</LinearLayout>

显示效果变成

总结:

本篇主要介绍Android自定义控件的基本绘制原理,会在下一篇中介绍如何自定义属性。希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

(0)

相关推荐

  • android自定义按钮示例(重写imagebutton控件实现图片按钮)

    由于项目这种类型的图片按钮比较多,所以重写了ImageButton类. 复制代码 代码如下: package me.henji.widget; import android.content.Context;import android.graphics.ColorMatrix;import android.graphics.ColorMatrixColorFilter;import android.util.AttributeSet;import android.view.MotionEvent

  • Android自定义组合控件之自定义下拉刷新和左滑删除实例代码

    绪论 最近项目里面用到了下拉刷新和左滑删除,网上找了找并没有可以用的,有比较好的左滑删除,但是并没有和下拉刷新上拉加载结合到一起,要不就是一些比较水的结合,并不能在项目里面使用,小编一着急自己组合了一个,做完了和QQ的对比了一下,并没有太大区别,今天分享给大家,其实并不难,但是不知道为什么网上没有比较好的Demo,当你的项目真的很急的时候,又没有比较好的Demo,那么"那条友谊的小船儿真是说翻就翻啊",好了,下面先来具体看一下实现后的效果吧: 代码已经上传到Github上了,小伙伴们记

  • Android中自定义控件的declare-styleable属性重用方案

    最近接触了Android自定义控件,涉及到自定义xml中得属性(attribute),其实也很简单,但是写着写着,发现代码不完美了,就是在attrs.xml这个文件中,发现属性冗余,于是就想有没有类似属性继承或者include之类的方法.本文将就declare-stylable中属性重用记录一下. 不完美的代码 复制代码 代码如下: <?xml version="1.0" encoding="utf-8"?> <resources>     

  • 实例讲解Android应用中自定义组合控件的方法

    自定义view大概可以分成: 继承view 组合view 自己画的view(用paint和canvas) 自定义viewgroup(widget) 最近又跟同学聊起来了,于是就准备自己实现一个imagebutton来练练手.(最简单的了)以及后面一个把imageview与textview结合使用的案例. ImageButton 要实现ImageButton最容易想到的不就是把button和imageview合在一起么.嗯,人容易就想到这是一个组合自定义view.可是如何把一个image放到but

  • Android自定义View之组合控件实现类似电商app顶部栏

    本文实例为大家分享了Android自定义View之组合控件,仿电商app顶部栏的相关代码,供大家参考,具体内容如下 效果图: 分析:左右两边可以是TextView和Button,设置drawableTop即可,中间的看着像是EditText,但是用过淘宝天猫等类似app的话会发现点击搜索不是在当前Activit进行搜索的,是跳转到另外的页面进行的,所以用TextView然后设置背景即可. 实现流程 参数列表: 设置属性文件:values下建立attrs.xml文件,添加需要自定义的属性. <?x

  • Android控件之RatingBar自定义星级评分样式

    一.RatingBar简单介绍 RatingBar是基于SeekBar(拖动条)和ProgressBar(状态条)的扩展,用星形来显示等级评定,在使用默认RatingBar时,用户可以通过触摸/拖动/按键(比如遥控器)来设置评分, RatingBar自带有两种模式 ,一个小风格 ratingBarStyleSmall,大风格为ratingBarStyleIndicator,大的只适合做指示,不适用与用户交互. 效果图展示: 二.实例 1.布局文件 <?xml version="1.0&qu

  • 在Android开发中使用自定义组合控件的例子

    一.定义一个XML布局文件 setting_item_view.xml <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height

  • Android自定义控件之开关按钮学习笔记分享

    今天来讲讲自定义单个控件,就拿开关按钮来讲讲,相信大家见了非常多这样的了,先看看效果: 我们可以看到一个很常见的开关按钮,那就来分析分析. 首先: 这是由两张图片构成: ①一张为有开和关的背景图片 ②一张为控制开和关的滑动按钮 第一步: 写个类继承View,并重写几个方法: 第一个为构造函数,重写一个参数的函数和两个参数的函数就够了,因为两个参数的函数能够使用自定义属性 第二个为控制控件的大小–>protected void onMeasure(int widthMeasureSpec, int

  • Android自定义播放器控件VideoView

    介绍 最近要使用播放器做一个简单的视频播放功能,开始学习VideoView,在横竖屏切换的时候碰到了点麻烦,不过在查阅资料后总算是解决了.在写VideoView播放视频时候定义控制的代码全写在Actvity里了,写完一看我靠代码好乱,于是就写了个自定义的播放器控件,支持指定大小,可以横竖屏切换,手动左右滑动快进快退.好了,下面开始. 效果图有点卡,我也不知道为啥..... VideoView介绍 这个是我们实现视频播放最主要的控件,详细的介绍大家百度就去看,这里介绍几个常用的方法. 用于播放视频

  • Android自定义控件之基本原理(一)

    前言: 在日常的Android开发中会经常和控件打交道,有时Android提供的控件未必能满足业务的需求,这个时候就需要我们实现自定义一些控件,今天先大致了解一下自定义控件的要求和实现的基本原理. 自定义控件要求: 1. 应当遵守Android标准的规范(命名,可配置,事件处理等). 2. 在XML布局中科配置控件的属性. 3. 对交互应当有合适的反馈,比如按下,点击等. 4. 具有兼容性, Android版本很多,应该具有广泛的适用性. 自定义控件学习步骤: 1 .View的工作原理 2 .编

  • Android自定义控件基本原理详解(一)

    前言: 在日常的Android开发中会经常和控件打交道,有时Android提供的控件未必能满足业务的需求,这个时候就需要我们实现自定义一些控件,今天先大致了解一下自定义控件的要求和实现的基本原理. 自定义控件要求: 1. 应当遵守Android标准的规范(命名,可配置,事件处理等).      2. 在XML布局中科配置控件的属性.      3. 对交互应当有合适的反馈,比如按下,点击等.      4. 具有兼容性, Android版本很多,应该具有广泛的适用性. 自定义控件学习步骤: 1

  • Android自定义控件之自定义组合控件(三)

    前言: 前两篇介绍了自定义控件的基础原理Android自定义控件基本原理详解(一).Android自定义控件之自定义属性(二).今天重点介绍一下如何通过自定义组合控件来提高布局的复用,降低开发成本,以及维护成本. 使用自定义组合控件的好处? 我们在项目开发中经常会遇见很多相似或者相同的布局,比如APP的标题栏,我们从三种方式实现标题栏来对比自定义组件带来的好处,毕竟好的东西还是以提高开发效率,降低开发成本为导向的.  1.)第一种方式:直接在每个xml布局中写相同的标题栏布局代码 <?xml v

  • Android自定义控件ViewGroup实现标签云(四)

    前言: 前面几篇讲了自定义控件绘制原理Android自定义控件基本原理详解(一) ,Android自定义控件之自定义属性(二) ,Android自定义控件之自定义组合控件(三),常言道:"好记性不如烂笔头,光说不练假把式!!!",作为一名学渣就是因为没有遵循这句名言才沦落于此,所以要谨遵教诲,注重理论与实践相结合,今天通过自定义ViewGroup来实现一下项目中用到的标签云. 需求背景: 公司需要实现一个知识点的标签显示,每个标签的长度未知,如下图所示 基本绘制流程: 绘制原理这里不再

  • Android自定义控件之自定义属性(二)

    前言: 上篇介绍了自定义控件的基本要求以及绘制的基本原理,本篇文章主要介绍如何给自定义控件自定义一些属性.本篇文章将继续以上篇文章自定义圆形百分比为例进行讲解.有关原理知识请参考Android自定义控件基本原理详解(一)这篇文章. 需求产生背景: 为何要引入自定义属性?当Android提供的原生属性不能满足实际的需求的时候,比如我们需要自定义圆形百分比半径大小.圆形背景.圆形显示的位置.圆形进度的背景等等.这个时候就需要我们自定义属性了. 自定义属性步骤: 1.)在res/values文件下添加

  • android自定义控件创建翻页接口详细代码

    本文分享的这个类的目的是为在看书翻页时,需要进行的动作提供接口,利用android自定义控件创建翻页接口,具体内容如下 BookPage.java package com.horse.util; import java.text.DecimalFormat; import java.util.Vector; import com.horse.bean.Chapter; import android.graphics.Bitmap; import android.graphics.Canvas;

  • Android自定义控件实现验证码倒计时

    今天给大家带来一个新的控件--验证码倒计时,先看下效果图 1 效果演示 2 使用方式 <com.landptf.view.CountDownM android:id="@+id/cdm_identifying_code" android:layout_width="wrap_content" android:layout_height="50dp" android:layout_alignParentRight="true&quo

  • 详解Android自定义控件属性TypedArray以及attrs

    最近在研究android自定义控件属性,学到了TypedArray以及attrs.大家也可以结合<理解Android中的自定义属性>这篇文章进行学习,后续一篇还有应用. 1.attrs文件编写 <?xml version="1.0" encoding="utf-8"?> <resources> <attr name="titleText" format="string" /> &

  • Android自定义控件属性详细介绍

     Android自定义控件属性详细介绍 1. reference:参考某一资源ID.  (1)属性定义: <declare-styleable name = "名称"> <attr name = "background" format = "reference" /> </declare-styleable> (2)属性使用: <ImageView android:layout_width = "

  • Android 自定义控件实现显示文字的功能

    Android 自定义控件实现显示文字的功能 自定义控件-–逐个显示文字 ONE Goal ,ONE Passion ! 前言: 今天要实现的效果时.让我们的文字一个一个显示出来.上效果图吧: 实现原理: 1,拿到要显示的文字. 2,计算文字显示的速率 字体显示的速度 v = 总的字体长度 / 总的显示时间 3,将文字根据速率显示到控件上. 自定义View: public class printTextView extends TextView { /** * 字体显示出来的时间 */ priv

随机推荐