您的位置:首页 > 移动开发 > Android开发

Android研究院之自定义view

2015-12-14 14:40 435 查看
雨松MOMO带大家盘点Android 中的自定义View界面的绘制

今天我用自己写的一个Demo 和大家详细介绍一个Android中自定义View中的使用与绘制技巧。





1.自定义view绘制字符串

相信在实际开发过程中必然很多地方都须要用到系统字 为什么会用到系统字? 方便 省内存 我相信做过J2ME游戏开发的朋友应该深知内存有多么多么重要 而且使用它还可以带来一个更重要的好处就是很方便的可以实现多国语言的切换 笔者现在在正在做的一个产品就是可以多语言切换的软件 有英语 繁体中文 等等 设想如果使用图片字的话那每个语言都须要出一套图,我用一个例子简单介绍一下绘制字符串。





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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76

package
cn.m15.xys;

import
android.app.Activity;

import android.content.Context;
import
android.graphics.Canvas;

import android.graphics.Color;
import
android.graphics.Paint;

import android.graphics.Paint.FontMetrics;
import
android.os.Bundle;

import android.view.Display;
import
android.view.View;

public
class Font
extends Activity
{

public int
mScreenWidth =
0;
public
int mScreenHeight
= 0;

@Override
protected
void onCreate(Bundle
savedInstanceState)
{

setContentView(new
FontView(this));
// 获取屏幕宽高

Display display
= getWindowManager().getDefaultDisplay();
mScreenWidth
= display.getWidth();

mScreenHeight =
display.getHeight();
super.onCreate(savedInstanceState);

}

class
FontView extends
View {

public final
static String
STR_WIDTH =
"获取字符串宽为:";
public
final static
String STR_HEIGHT
= "获取字体高度为:";

Paint mPaint
= null;

public FontView(Context
context)
{
super(context);

mPaint =
new Paint();
}

@Override

protected void
onDraw(Canvas
canvas)
{
//设置字符串颜色

mPaint.setColor(Color.WHITE);
canvas.drawText("当前屏幕宽"
+ mScreenWidth,
0,
30,
mPaint);

canvas.drawText("当前屏幕高"+
mScreenHeight,
0,
60,
mPaint);
//设置字体大小

mPaint.setColor(Color.RED);
mPaint.setTextSize(18);

canvas.drawText("字体大小为18",
0,
90,
mPaint);
//消除字体锯齿

mPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
canvas.drawText("消除字体锯齿后",
0,
120,
mPaint);

//获取字符串宽度
canvas.drawText(STR_WIDTH
+ getStringWidth(STR_WIDTH),
0,
150,
mPaint);

//获取字体高度
canvas.drawText(STR_HEIGHT
+ getFontHeight(),
0,
180,
mPaint);

//从string.xml读取字符串绘制
mPaint.setColor(Color.YELLOW);

canvas.drawText(getResources().getString(R.string.string_font),
0,
210,
mPaint);
super.onDraw(canvas);

}

/**
* 获取字符串宽

* @param str
* @return

*/
private
int getStringWidth(String
str)
{

return (int)
mPaint.measureText(STR_WIDTH);
}

/*
* 获取字体高度

*/
private
int getFontHeight()
{

FontMetrics fm
= mPaint.getFontMetrics();
return
(int)Math.ceil(fm.descent
- fm.top)
+ 2;

}
}

}

2.绘制无规则几何图形

绘制无规则几何图形似乎在实际工作中很少可以用到 原因是用程序去绘制图形即使在精准再好看也不会有美术出的图片好看 但是使用程序绘制图形作为学习来说却是基础中的基础,所以建议大家都看一看。





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
60
61
62
63
64
65
66
67
68
69
70
71
72

package
cn.m15.xys;

import
android.app.Activity;

import android.content.Context;
import
android.graphics.Canvas;

import android.graphics.Color;
import
android.graphics.Paint;

import android.graphics.Path;
import
android.graphics.RectF;

import android.os.Bundle;
import
android.view.View;

public
class Geometry
extends Activity
{

public int
mScreenWidth =
0;
public
int mScreenHeight
= 0;

@Override

protected void
onCreate(Bundle
savedInstanceState)
{
setContentView(new
GeometryView(this));

super.onCreate(savedInstanceState);

}

class GeometryView
extends View
{
Paint
mPaint =
null;

public
GeometryView(Context
context)
{

super(context);
mPaint
= new
Paint();

mPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
}

@Override

protected void
onDraw(Canvas
canvas)
{
super.onDraw(canvas);

//设置画布颜色 也就是背景颜色

canvas.drawColor(Color.WHITE);

mPaint.setColor(Color.BLACK);
canvas.drawText("绘制无规则几何图形喔!!!",
150,
30,
mPaint);

//绘制一条线

mPaint.setColor(Color.BLACK);
mPaint.setStrokeWidth(4);

canvas.drawLine(0,
0,
100,
100,
mPaint);

//绘制一个矩形
mPaint.setColor(Color.YELLOW);

canvas.drawRect(0,
120,
100,
200,
mPaint);

//绘制一个圆形
mPaint.setColor(Color.BLUE);

canvas.drawCircle(80,
300,
50,
mPaint);

//绘制一个椭圆
mPaint.setColor(Color.CYAN);

canvas.drawOval(new
RectF(300,370,120,100),
mPaint);

//绘制多边形
mPaint.setColor(Color.BLACK);

Path path
= new
Path();
path.moveTo(150+5
, 400
-50);

path.lineTo(150+45,
400 -
50);
path.lineTo(150+30,
460 -
50);

path.lineTo(150+20,
460 -
50);
path.close();

canvas.drawPath(path,
mPaint);

}
}

}

3.图片的绘制以及旋转缩放的实现

在这点上Android 确实比J2ME 强大很多 手机游戏开发最痛苦的是什么?? 是游戏引擎的开发,但是工程师会把大部分时间浪费在对坐标上,如果写引擎的时候没有把自适应考虑周全后期会非常痛苦,现在手机屏幕分辨率是各式各样 内存大小也是各式各样 所以可见自适应屏幕算法有多么的重要。





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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172

package
cn.m15.xys;

import
android.app.Activity;

import android.content.Context;
import
android.graphics.Bitmap;

import android.graphics.BitmapFactory;
import
android.graphics.Canvas;

import android.graphics.Matrix;
import
android.graphics.Paint;

import android.os.Bundle;
import
android.view.View;

import android.view.View.OnClickListener;
import
android.widget.Button;

import android.widget.LinearLayout;

public class
Image extends
Activity {
ImageView
imageView =
null;

@Override

protected void
onCreate(Bundle
savedInstanceState)
{
imageView
= new
ImageView(this);

setContentView(R.layout.image);
LinearLayout
ll =
(LinearLayout)
findViewById(R.id.iamgeid);

ll.addView(imageView);
// 向左移动

Button botton0
= (Button)
findViewById(R.id.buttonLeft);
botton0.setOnClickListener(new
OnClickListener()
{

@Override
public
void onClick(View
arg0)
{

imageView.setPosLeft();
}

});

// 向右移动
Button
botton1 =
(Button)
findViewById(R.id.buttonRight);

botton1.setOnClickListener(new
OnClickListener()
{
@Override

public void
onClick(View
arg0)
{
imageView.setPosRight();

}
});

// 左旋转
Button
botton2 =
(Button)
findViewById(R.id.buttonRotationLeft);

botton2.setOnClickListener(new
OnClickListener()
{
@Override

public void
onClick(View
arg0)
{
imageView.setRotationLeft();

}
});

// 右旋转

Button botton3
= (Button)
findViewById(R.id.buttonRotationRight);
botton3.setOnClickListener(new
OnClickListener()
{

@Override
public
void onClick(View
arg0)
{

imageView.setRotationRight();
}

});

// 缩小
Button
botton4 =
(Button)
findViewById(R.id.buttonNarrow);

botton4.setOnClickListener(new
OnClickListener()
{

@Override
public
void onClick(View
arg0)
{

imageView.setNarrow();
}

});

// 放大
Button
botton5 =
(Button)
findViewById(R.id.buttonEnlarge);

botton5.setOnClickListener(new
OnClickListener()
{

@Override
public
void onClick(View
arg0)
{

imageView.setEnlarge();
}

});

super.onCreate(savedInstanceState);

}

class ImageView
extends View
{
Paint
mPaint =
null;

Bitmap bitMap
= null;
Bitmap
bitMapDisplay
= null;

int m_posX
= 120;
int
m_posY =
50;

int m_bitMapWidth
= 0;
int
m_bitMapHeight
= 0;

Matrix mMatrix
= null;
float
mAngle =
0.0f;

float mScale
= 1f;//1为原图的大小

public ImageView(Context
context)
{
super(context);

mPaint =
new Paint();
mPaint.setFlags(Paint.ANTI_ALIAS_FLAG);

bitMap =
BitmapFactory.decodeResource(this.getResources(),
R.drawable.image);

bitMapDisplay =
bitMap;
mMatrix
= new
Matrix();

// 获取图片宽高
m_bitMapWidth
= bitMap.getWidth();

m_bitMapHeight =
bitMap.getHeight();
}

// 向左移动

public void
setPosLeft()
{
m_posX
-= 10;

}

// 向右移动
public
void setPosRight()
{

m_posX +=
10;
}

// 向左旋转

public void
setRotationLeft()
{
mAngle--;

setAngle();
}

// 向右旋转

public void
setRotationRight()
{
mAngle++;

setAngle();
}

// 缩小图片

public void
setNarrow()
{
if
(mScale
> 0.5)
{

mScale -=
0.1;
setScale();

}
}

// 放大图片

public void
setEnlarge()
{
if
(mScale
< 2)
{

mScale +=
0.1;
setScale();

}
}

// 设置缩放比例

public void
setAngle()
{
mMatrix.reset();

mMatrix.setRotate(mAngle);
bitMapDisplay
= Bitmap.createBitmap(bitMap,
0,
0,
m_bitMapWidth,

m_bitMapHeight,
mMatrix,
true);
}

// 设置旋转比例

public void
setScale()
{
mMatrix.reset();

//float sx X轴缩放
//float sy Y轴缩放

mMatrix.postScale(mScale,
mScale);
bitMapDisplay
= Bitmap.createBitmap(bitMap,
0,
0,
m_bitMapWidth,

m_bitMapHeight,
mMatrix,
true);
}

@Override

protected void
onDraw(Canvas
canvas)
{
super.onDraw(canvas);

canvas.drawBitmap(bitMapDisplay,
m_posX,
m_posY,
mPaint);
invalidate();

}
}

}

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

<?xml
version="1.0"
encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/iamgeid"

android:orientation="vertical"
android:layout_width="fill_parent"

android:layout_height="fill_parent"
>

<Button
android:id="@+id/buttonLeft"
android:layout_width="fill_parent"
android:layout_height="wrap_content"

android:text="图片向左移动"
/>

<Button
android:id="@+id/buttonRight"
android:layout_width="fill_parent"
android:layout_height="wrap_content"

android:text="图片向右移动"
/>

<Button
android:id="@+id/buttonRotationLeft"
android:layout_width="fill_parent"
android:layout_height="wrap_content"

android:text="图片左旋转"
/>

<Button
android:id="@+id/buttonRotationRight"
android:layout_width="fill_parent"
android:layout_height="wrap_content"

android:text="图片右旋转"
/>

<Button
android:id="@+id/buttonNarrow"
android:layout_width="fill_parent"
android:layout_height="wrap_content"

android:text="图片缩小"
/>

<Button
android:id="@+id/buttonEnlarge"
android:layout_width="fill_parent"
android:layout_height="wrap_content"

android:text="图片放大"
/>

</LinearLayout>

4.播放frame动画

做游戏的话播放动画可就是必不可少的元素 帧动画帧动画 顾名思义是一帧一帧的播放 。 实际在开发中为了节省内存美术会把人物的图片切成一小块一小块然后由程序根据编辑器生成的点把图片在拼接起来这样就可以做到用更少的图片去实现更多的动画效果因为不太方便介绍图片编辑器 这个demo我只给大家简单的介绍一下播放动画的原理 后期我会深入讲解。

如图所示这个小人一直在行走 实际上是4张图片在来回切换 每张图片延迟500毫秒 后播下一张 以此类推。






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

package
cn.m15.xys;

import
android.app.Activity;

import android.content.Context;
import
android.graphics.Bitmap;

import android.graphics.BitmapFactory;
import
android.graphics.Canvas;

import android.graphics.Color;
import
android.graphics.Paint;

import android.os.Bundle;
import
android.view.View;

public
class FramAnimation
extends Activity
{

public final
static int
ANIM_COUNT =
4;

@Override
protected
void onCreate(Bundle
savedInstanceState)
{

setContentView(new
FramView(this));
super.onCreate(savedInstanceState);

}

class
FramView extends
View {

Bitmap[]
bitmap =
new Bitmap[ANIM_COUNT];
Bitmap
display =
null;

Paint paint
= null;
long
startTime =
0;

int playID
= 0;

public FramView(Context
context)
{
super(context);

for (int
i =
0;
i <
ANIM_COUNT;
i++)
{
bitmap[i]
= BitmapFactory.decodeResource(this.getResources(),
R.drawable.hero_a
+ i);

}
display
= bitmap[0];
paint =
new Paint();

startTime =
System.currentTimeMillis();
}

@Override
protected void
onDraw(Canvas
canvas)
{
super.onDraw(canvas);
paint.setColor(Color.WHITE);

canvas.drawText("播放动画中...",
100,
30,
paint);
long
nowTime =
System.currentTimeMillis();

if (nowTime
- startTime
>= 500)
{
startTime=nowTime;

playID++;
if
(playID
>= ANIM_COUNT)
{

playID =
0;
}

canvas.drawBitmap(bitmap[playID],
100,
100,
paint);
}

invalidate();
}

}

}

最后如果你还是觉得我写的不够详细 看的不够爽 不要紧我把源代码的下载地址贴出来 欢迎大家一起讨论学习

雨松MOMO希望可以和大家一起进步。

下载地址:http://vdisk.weibo.com/s/a9iGZ

本文固定链接: http://www.xuanyusong.com/archives/34 转载请注明:
雨松MOMO 2012年04月25日 于
雨松MOMO程序研究院 发表
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: