Android自定义View过程解析

时间:2021-10-13 09:14:28

android自定义的view,主要是继承view,然后实现ondraw这个方法,来进行绘制。

  • 1. 编写自己的自定义view
  • 2. 加入逻辑线程
  • 3. 提取和封装自定义view
  • 4. 利用xml中定义样式来影响显示效果

一、编写自定义的view
1.在xml中使用自己的view

?
1
2
3
4
5
6
<!-- 可以使用view的公共属性,例如背景 -->
<com.niuli.view.myview
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:background="#ffff00"
 />

2.通过继承view,然后实现ondraw来实现方法

?
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public class myview extends view {
 
 bitmap bitmap;
 
 public myview(context context) {
  super(context);
  /**
   * getresources()可以获取当前资源内的资源
   */
  bitmap = bitmapfactory.decoderesource(getresources(), r.drawable.ic_launcher);
 }
 
 public myview(context context, attributeset attrs) {
  super(context, attrs);
  bitmap = bitmapfactory.decoderesource(getresources(), r.drawable.ic_launcher);
 }
 /**
  * 绘制是通过canvas来承载,其就相当于一块画布
  * 更多的学习将在不断的做小东西中更新
  */
 @override
 protected void ondraw(canvas canvas) {
  super.ondraw(canvas);
  /**
   * paint相当于一只画笔,可以画文字,几何图形,bit图片等
   */
  paint paint = new paint();
  //设置绘制的颜色,是否空心之类的都是对画笔的设计
  paint.setcolor(color.blue);
 
  //绘画文字
  paint.settextsize(30);
  canvas.drawtext("这是一个自定义view", 0, 30, paint);
  //绘画直线
  canvas.drawline(0, 60, 100, 60, paint);
  //绘画圆角矩形方法之一
  //设置空心
  paint.setstyle(paint.getstyle().stroke);
 
  rectf rec = new rectf(0, 90, 100, 190);
  canvas.drawroundrect(rec, 20, 20, paint);
  //绘制图片
  canvas.drawbitmap(bitmap, 0, 350, paint);
 }
 
}

效果

Android自定义View过程解析

二、自定义的view+线程的使用控制
绘制文字,和圆形,通过线程控制使得其能在屏幕中移动

?
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
public class myviewtwo extends view {
 
 //定义画笔
 private paint paint = new paint();
 private int x;
 private float sweepangle;
 private control thread;
 private random random = new random();
 
 public myviewtwo(context context, attributeset attrs) {
  super(context, attrs);
 }
 
 public myviewtwo(context context) {
  super(context);
 }
 
 @override
 protected void ondraw(canvas canvas) {
  paint.settextsize(80);
  //绘制文字
  canvas.drawtext("七夕快乐", x, 70, paint);
  //绘制图形
  rectf rect = new rectf(0 ,80 ,100, 160);
  canvas.drawarc(rect, 0, sweepangle, true, paint);
 
  //启动线程
  if (thread ==null) {
   thread = new control();
   thread.start();
  }
 }
 public class control extends thread{
  @override
  public void run() {
   while(true){
    x +=3;
    sweepangle++;
    if (x>getwidth()) {
     x = (int) (0 - paint.measuretext("七夕快乐"));
    }
    //控制圆的的旋转
    if (sweepangle>360) {
     sweepangle = 0;
    }
    //设置画笔颜色
    paint.setargb(255, random.nextint(255), random.nextint(255), random.nextint(255));
 
    //相当于刷新画布
    postinvalidate();
 
    try {
     sleep(30);
    } catch (interruptedexception e) {
     e.printstacktrace();
    }
   }
  }
 }

效果 

 Android自定义View过程解析

三、封装移动程序,模块化思想
封装主要是使用抽象方法,子类继承后只要实现这些方法即可运行起来,大大简化了程序

?
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public abstract class myviewtwo extends view {
 
 private control thread;
 
 public myviewtwo(context context, attributeset attrs) {
  super(context, attrs);
 }
 
 public myviewtwo(context context) {
  super(context);
 }
 //封装,构造画面,子类继承后需要重写
 protected abstract void drawsub(canvas canvas);
 
 @override
 protected final void ondraw(canvas canvas) {
 
  //启动线程
  if (thread ==null) {
   thread = new control();
   thread.start();
  }else {
   drawsub(canvas);
  }
 }
 //封装移动方法,子类继承后需要重写
 protected abstract void move();
 
 public class control extends thread{
  @override
  public void run() {
   while(true){
    move();
    //相当于刷新画布
    postinvalidate();
 
    try {
     sleep(30);
    } catch (interruptedexception e) {
     e.printstacktrace();
    }
   }
  }
 }
 
}

四、使用xml中定义样式影响显示效果
1、第一步就是在value文件夹中建立自己的样式文件

?
1
2
3
4
5
6
7
<?xml version="1.0" encoding="utf-8"?>
<resources>
 <declare-styleable name="numtext">
  <attr name="linenum" format="integer"/>
  <attr name="xscroll" format="boolean" />
 </declare-styleable>
</resources>

2、xml中先要加入命名空间,然后就可以直接使用属性

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<framelayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 xmlns:nt="http://schemas.android.com/apk/res/com.jikexueyuan.myview"
 android:id="@+id/container"
 android:layout_width="match_parent"
 android:layout_height="match_parent" >
 
 <com.jikexueyuan.myview.v4.numtext
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  nt:linenum="6"
  nt:xscroll="true"/>
 
</framelayout>

3、代码中要有相应的解析xml中定义的这个元素

?
1
2
3
4
5
6
7
8
public numtext(context context, attributeset attrs) {
  super(context, attrs);
 
  typedarray ta = context.obtainstyledattributes(attrs, r.styleable.numtext);
  linenum = ta.getint(r.styleable.numtext_linenum, 1);
  xscroll = ta.getboolean(r.styleable.numtext_xscroll, false);
  ta.recycle();
 }

主要就是利用以上方法和xml中定义元素值进行曝光相关联。

以上就是本文的全部内容,希望对大家的学习有所帮助。