Android学习(十)—— Android自定义控件

Android自定义控件

安卓在使用中大多数使用已有的一些控件,用法比较简单,还有一部分是比较复杂的、用户自己想的控件,这些就需要进行自定义控件,今天就来简单说一下自定义控件。

1、绘制过程

  • 创建一个类,继承View类
  • onMeasure()方法,测量计算视图的大小
  • onLayout()方法,设置视图在屏幕中显示的位置
  • onDraw()方法,绘制视图

以上就是自定义控件的绘制过程。

2、主要内容解释

  • measure操作

  用于计算视图的大小,即视图的宽度和长度。在view中定义为final类型,要求子类不能修改。measure()函数中又会调用下面的函数:

(1)onMeasure(),确定视图大小,也就是说measure只是对onMeasure的一个包装,子类可以覆写onMeasure()方法实现自己的计算视图大小的方式,并通过setMeasuredDimension(width, height)保存计算结果。

  (2)关于MeasureSpec:

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

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

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

  • layout操作 

用于设置视图在屏幕中显示的位置。在view中定义为final类型,要求子类不能修改。layout()函数中有两个基本操作:

(1)setFrame(l,t,r,b),l,t,r,b即子视图在父视图中的具体位置,该函数用于将这些参数保存起来;

(2)onLayout(),在View中这个函数什么都不会做,提供该函数主要是为viewGroup类型布局子视图用的;

  • draw操作

利用前两部得到的参数,将视图显示在屏幕上,到这里也就完成了整个的视图绘制工作。其内部定义了绘图的基本操作:

(1)绘制背景;

(2)如果要视图显示渐变框,这里会做一些前期工作;

(3)绘制视图本身,即调用onDraw()函数。在view中onDraw()是个空函数,也就是说具体的视图都要覆写该函数来实现自己的显示。

(4)绘制子视图,即dispatchDraw()函数。在view中这是个空函数,具体的视图不需要实现该方法,它是专门为容器类准备的,也就是容器类必须实现该方法;

(5)应用程序调用了setVerticalFadingEdge或者setHorizontalFadingEdge,如果需要可以开始绘制渐变框;

(6)绘制滚动条;

从上面可以看出自定义View需要最少覆写onMeasure()和onDraw()两个方法。

  • 自定义View的方法
  1. onFinishInflate(): 回调方法,当应用从XML加载该组件并用它构建界面之后调用的方法
  2. onMeasure():检测View组件及其子组件的大小
  3. onLayout(): 当该组件需要分配其子组件的位置、大小时
  4. onSizeChange():当该组件的大小被改变时
  5. onDraw(): 当组件将要绘制它的内容时
  6. onKeyDown: 当按下某个键盘时
  7. onKeyUp:  当松开某个键盘时
  8. onTrackballEvent: 当发生轨迹球事件时
  9. onTouchEvent: 当发生触屏事件时
  10. onWindowFocusChanged(boolean):当该组件得到、失去焦点时
  11. onAtrrachedToWindow():当把该组件放入到某个窗口时
  12. onDetachedFromWindow():当把该组件从某个窗口上分离时触发的方法
  13. onWindowVisibilityChanged(int):当包含该组件的窗口的可见性发生改变时触发的方法

3、效果图展示

4、代码展示

在java代码中我加了很多注释,方便进行理解、学习。

布局文件

 1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     android:id="@+id/container"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:orientation="vertical">
 6
 7     <sample.sdk.qy.com.androiddemo.Customize
 8         android:layout_width="match_parent"
 9         android:layout_height="match_parent"
10         android:layout_margin="20dp"
11         />
12
13 </LinearLayout>

自定义控件类

 1 public class Customize extends View {
 2     private final static String TAG = Customize.class.getSimpleName();
 3     private Paint mPaint;
 4     private RectF oval;
 5
 6     public Customize(Context context) {
 7         super(context);
 8         init();
 9     }
10
11     public Customize(Context context, AttributeSet attrs) {
12         super(context, attrs);
13         init();
14     }
15
16     public Customize(Context context, AttributeSet attrs, int defStyleAttr) {
17         super(context, attrs, defStyleAttr);
18         init();
19     }
20
21     private void init(){
22         mPaint = new Paint();
23         mPaint.setAntiAlias(true);
24         oval=new RectF();
25     }
26     @Override
27     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
28         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
29         int widthMode = MeasureSpec.getMode(widthMeasureSpec);
30         int widthSize = MeasureSpec.getSize(widthMeasureSpec);
31         int heightMode = MeasureSpec.getMode(heightMeasureSpec);
32         int heightSize = MeasureSpec.getSize(heightMeasureSpec);
33         switch (widthMode) {
34             case MeasureSpec.EXACTLY:
35                 break;
36             case MeasureSpec.AT_MOST:
37                 break;
38             case MeasureSpec.UNSPECIFIED:
39                 break;
40         }
41     }
42
43     @Override
44     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
45         super.onLayout(changed, left, top, right, bottom);
46
47     }
48
49     @Override
50     protected void onDraw(Canvas canvas) {
51         super.onDraw(canvas);
52         //设置演颜色
53         mPaint.setColor(Color.GREEN);
54         // FILL填充, STROKE描边,FILL_AND_STROKE填充和描边
55         mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
56         //获取控件的宽度和高度
57         int with = getWidth();
58         int height = getHeight();
59         //设置圆的半径
60         float radius = with / 4;
61         //画圆,设置颜色
62         canvas.drawCircle(with / 2, with / 2, radius, mPaint);
63         mPaint.setColor(Color.BLUE);
64         //用于定义的圆弧的形状和大小的界限
65         oval.set(with / 2 - radius, with / 2 - radius, with / 2
66                 + radius, with / 2 + radius);
67         //根据进度画圆弧
68         canvas.drawArc(oval, 270, 90, true, mPaint);
69         //画出另一个圆弧
70         mPaint.setColor(Color.YELLOW);
71         canvas.drawArc(oval, 360, 120, true, mPaint);
72     }
73 }

MainActivity类

 1 public class MainActivity extends Activity {
 2
 3     @Override
 4     protected void onCreate(Bundle savedInstanceState) {
 5         super.onCreate(savedInstanceState);
 6         setContentView(R.layout.activity_main);
 7
 8     }
 9
10 }

原文地址:https://www.cnblogs.com/QY-admin/p/10021735.html

时间: 2024-11-04 20:54:05

Android学习(十)—— Android自定义控件的相关文章

Android学习十---Android Camera

Android camera用来拍照和拍摄视频的先看一下最后实现的效果图             最后的效果图 一.准备 在你的应用程序上使用android拍照设备,需要考虑以下几个方面 1. 是否是一定需要camera 如果需要,那么就无法安装在没有摄像头的设备. 需要在mainfest 中声明 <uses-permission android:name="android.permission.CAMERA" /> <uses-feature android:nam

[Android学习笔记]Android中多线程开发的一些概念

线程安全: 在多线程的情况下,不会因为线程之间的操作而导致数据错误. 线程同步: 同一个资源,可能在同一时间被多个线程操作,这样会导致数据错误.这是一个现象,也是一个问题,而研究如何解决此类问题的相关工作就叫做线程同步. android中,处理线程同步的手段就是:锁 一般分为公平锁和非公平锁: synchronized(内部锁,互斥锁):synchronized是JVM提供的线程同步机制,如果出现问题,JVM能捕获异常,并释放资源,具体实现机制需要查看JVM源码 synchronized的使用特

android学习笔记--android启动过程之init.rc文件浅析

1.  init.rc文件结构文件位置:init.c  : /system/core/initinit.rc  : /system/core/rootdir 首先init.rc文件是以模块为单位的,每个模块里的内容都是一起执行的,模块分为3种类型:on.service.import.我们可以看下init.rc文件是怎么写的:1.import import /init.usb.rc import /init.${ro.hardware}.rc import /init.trace.rc 上面的内容

Android学习——在Android中使用OpenCV的第一个程序

刚开始学习Android,由于之前比较熟悉OpenCV,于是就想先在Android上运行OpenCV试试 =================================================================================== 1.环境配置 JDK Eclipse ADT CDT Android SDK Android NDK cygwin OpenCV for Android 2.4.9 这部分网上很多,我就不再赘述了,可以参考:http://bl

[Android学习笔记]Android向下兼

Android向下兼容的思路:使用高版本的API,在运行时判断真实运行平台的API版本,根据不同版本做不同的处理 关键类:Build.class里面定义了API版本相关信息 内部类:VERSION定义当前系统的版本信息,其中包含SDK版本信息Build.VERSION.SDK_INT可以获取到当前运行的系统的SDK版本号 内部类:VERSION_CODES定义了各个版本的枚举信息 适配时: if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONE

android学习十八(Service服务的基本用法)

定义一个服务 在项目中定义一个服务,新建一个ServiceTest项目,然后在这个项目中新增一个名为MyService的类,并让它继承自Service,完成后的代码如下所示: package com.jack.servicetest; import android.app.Service; import android.content.Intent; import android.os.IBinder; public class MyService extends Service { @Over

android学习十九(WebView的用法)

android提供了一个WebView控件,借助它我们就可以在自己的应用程序中嵌入一个浏览器,从而轻松的展示各种各样的网页.下面来学习下简单的用法.新建一个WebViewTest项目,然后修改activity_main.xml中的代码,如下所示: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/

android学习十四(android的接收短信)

收发短信是每个手机基本的操作,android手机当然也可以接收短信了.android系统提供了一系列的API,使得我们可以在自己的应用程序里接收和发送短信. 其实接收短信主要是利用我们前面学过的广播机制.当手机接收到一条短信的时候,系统会发出一条值为andorid.provider.Telephony.SMS_RECEIVED的广播,这条广播里携带着与短信相关的所有数据.每个应用程序都可以在广播接收器里对它进行监听,收到广播时在从中解析出短信的内容即可. 下面我们来个具体的例子实践下吧,新建一个

android学习十二(android的Content Provider(内容提供器)的使用)

文件存储和SharePreference存储以及数据存储一般为了安全,最好用于当前应用程序中访问和存储数据.内容提供器(Content Provider)主要用于在不同的应用程序之间实现数据共享的功能,它提供了一套完整的机制,允许一个程序访问另一个程序中的数据,同时还能保证被访问数据的安全性.目前使用内容提供器是android实现跨程序共享数据的标准方式.内容提供器可以选择只对一部分数据进行共享,从而保证我们的程序中的隐私数据不会有泄漏的风险. 内容提供器的用法一般有两种,一种是使用现有的内容提

android学习十(android的文件存储)

在android系统中主要提供了三种方式用于简单的实现数据持久化功能,即文件存储,SharePreference存储以及数据库存储.当然还可以把数据保存到SD卡中. 文件存储是android中最基本的一种数据存储方式,它不对存储的内容进行任何的格式话处理,所有数据都是原封不动地保存到文件当中的,因而比较适合用于存储一些简单的文本数据或二进制数据. Context类中提供了一个openFileOutput()方法,可以用于将数据存储到指定的文件中.这个方法接收两个参数,第一个参数是文件的名,在创建