anim
单词:
Point:点
Line:线
Paint :绘画,画笔
Stroke:笔锋
rectangle(矩形)面
argtangel:弧度 canvas.drawArc(oval, 0, 90, true, paint)
RectF:圆外切矩形
平移translate,
缩放scale,
旋转rotate,
倾斜skelton
一、画点
无论通过画布画什么,点,线,面,第一步都是继承我们的view,继承view同时把我们的paint画笔这个类直接通过构造方法实例化
public class MyView extends View {
Paint paint = null;
public MyView(Context context) {
super(context);
paint = new Paint();
}
/**
* 画任何是这个方法
*/
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
}
1、Paint 属性
paint.setColor(Color.RED);
// 设置笔锋的宽度
paint.setStrokeWidth(5.0f);
2、画点
前面二个参数是坐标,后面是画笔
canvas.drawPoint(10.0f, 20.0f, paint);
二、画线
前面二个参数是开始坐标,后面二个参数是结束坐标
canvas.drawLine(10, 10, 50, 50, paint);
1、取屏幕的宽度和高度
这里补充一点,屏幕的状态栏和标题栏在2.2是像素一共是50px
/**
* 通过方法取宽度高度,这里用画布去取屏幕的宽度和高度
*/
int width = canvas.getWidth();
int height = canvas.getHeight();
canvas.drawLine(0, 0, width, height - 50, paint);
三、画面
canvas.drawRect(30, 30, 80, 160, paint);
四、画文字
canvas.drawText("陈奕迅", 100, 100, paint);
五、画弧形
/**
* 画弧形
*/
paint.setStrokeWidth(5.0f);
paint.setColor(Color.RED);
//全屏抗锯齿,AntiAlias:修正偏移量
paint.setAntiAlias(true);
//设置只有笔锋,不填充
paint.setStyle(Style.STROKE);
RectF oval = new RectF(50, 50, 150, 150);
canvas.drawArc(oval, 0, 90, true, paint);
六、画圆形
canvas.drawCircle(200, 200, 40, paint);
七、画三角形
画三角形通过path这个类来实现,了解我们平时画三角形都是从一个点到另外一个点到最后一个点,因此保证点的连续
/**
* 三角形
* path:路径
*
* 了解moveTo是移动,lineTo绘制其中一条边
*/
//这里了解工具path,如果draw完成不了的,我们就使用这个方法
Path path = new Path();
//代表把画笔移动到我们起始图形的坐标点
path.moveTo(100, 50);
//把起笔坐标和终点坐标连起来
path.lineTo(50, 180);
path.lineTo(150, 180);
path.lineTo(100, 50);
paint.setAntiAlias(true);
canvas.drawPath(path, paint);
八、画特效文字
/**
* path:绘制特效文字
*/
Path myTextPath = new Path();
//这里path可以添加我们需要的形状,等会文字就摆放到我们的添加图形的周围
//最后一个参数文字摆放按顺还是逆dir:diraction
myTextPath.addCircle(100, 100, 50, Direction.CW);
canvas.drawTextOnPath("陈奕迅", myTextPath, 0, 10, paint);
九、画图片
/**
* 图片的绘制
* Bitmap
*/
BitmapFactory bitmapFactory = new BitmapFactory();
Bitmap bitmap = bitmapFactory.decodeResource(getResources(), R.drawable.img1);
canvas.drawBitmap(bitmap, 100, 100, paint);
1、添加图片运动
/**
* 图片在二维平面的操作:平移translate,缩放scale,旋转rotate,倾斜skelton
*/
Matrix matrix = new Matrix();
//平移
matrix.setTranslate(0, 20);
//旋转
matrix.setRotate(45);
//缩放
matrix.setScale(0.5f, 0.5f);
canvas.drawBitmap(bitmap, matrix, paint);
十、裁切图片
/**
* 裁剪我们的图片
*
* bitmap.getwidth:取图片的宽
* bitmap.getHeight:取图片高
*/
Bitmap bitmap2 = bitmap.createBitmap(bitmap, 0, 0, 30, 30);
canvas.drawBitmap(bitmap2, 100, 100, paint);
十一、图片的四种特效
这里的图片的四种特效可以用代码实现,也可以通过我们的配置文件中,新建anim的文件夹,然后在这个文件里面添加我们的图片特效
1、translate平移
1、四个参数:开始坐标,结束坐标,以及动画时间
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXDelta="20"
android:fromYDelta="50"
android:toXDelta="150"
android:toYDelta="220"
android:duration="5000" />
2、AnimationUtils
这里用到AnimationUtils这个类中loadAnimation这个方法,第一个是本Context,第二个是对应的资源文件,当然后面的我们的三种动画同样利用这种方式来加载
//平移
private TranslateAnimation ts;
ts =
(TranslateAnimation)AnimationUtils.loadAnimation(MyTweenActivity.this, R.anim.mytranslate);
3、startAnimation
iv.startAnimation(animationSequence );
2、Rotate旋转
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="0"
android:toDegrees="180"
android:duration="5000" />
3、Scale缩放
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="5000"
android:fromXScale="1"
android:fromYScale="1"
android:pivotX="0.5"
android:pivotY="0.5"
android:toXScale="2"
android:toYScale="2" />
4、Alpha淡入淡出
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:fromAlpha="1.0"
android:toAlpha="0.3"
android:duration="5000" />
5、动画组合
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<translate
android:duration="5000"
android:fromXDelta="20"
android:fromYDelta="50"
android:toXDelta="150"
android:toYDelta="220" />
<alpha
android:duration="5000"
android:fromAlpha="1.0"
android:toAlpha="0.3" />
</set>
6、顺序组合
动画先后播放
android:startOffset="3001" 了解这个属性,这个当前面的播放完毕后,从前面播放完毕后一秒毫秒开始下一个动画
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<translate
android:duration="3000"
android:fromXDelta="20"
android:fromYDelta="50"
android:toXDelta="80"
android:toYDelta="120" />
<alpha
android:duration="5000"
android:fromAlpha="1.0"
android:startOffset="3001"
android:toAlpha="0.3" />
</set>
十二、图片gif效果
1、按钮监听器图片跑动
设置资源文件对应的动画图片
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
<item android:drawable="@drawable/tuzi001" android:duration="50" />
<item android:drawable="@drawable/tuzi002" android:duration="50" />
<item android:drawable="@drawable/tuzi003" android:duration="50" />
<item android:drawable="@drawable/tuzi004" android:duration="50" />
<item android:drawable="@drawable/tuzi005" android:duration="50" />
<item android:drawable="@drawable/tuzi006" android:duration="50" />
<item android:drawable="@drawable/tuzi007" android:duration="50" />
<item android:drawable="@drawable/tuzi008" android:duration="50" />
</animation-list>
按钮监听器
bt.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
iv.setBackgroundResource(R.anim.frame_animset_anim);
AnimationDrawable frameAnimal = (AnimationDrawable) iv.getBackground();
if(frameAnimal.isRunning()){
frameAnimal.stop();
}else{
frameAnimal.stop();
frameAnimal.start();
}
}
});
2、直接图片跑动
这里是重点,用到定时器,不过这里定时器不能设置的太久,一般都是很小的一个毫秒数
特别注意:第一种方式,通过计时器,不过这里貌似有问题,只有设置时间为0
public class MainActivity extends Activity {
private ImageView iv = null;
private MyFrameTask frameTask;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
iv = (ImageView) this.findViewById(R.id.iv);
Timer timer = new Timer();
frameTask = new MyFrameTask();
timer.schedule(frameTask, 20);
}
/**
* 这里相当于一个线程
*/
class MyFrameTask extends TimerTask {
@Override
public void run() {
iv.setBackgroundResource(R.anim.frame_animset_anim);
AnimationDrawable frameAnimal = (AnimationDrawable) iv.getBackground();
frameAnimal.start();
}
}
}
十三、转动风扇
1、一定记住自动刷新,这样才能完成风扇的转动
下面这个是继承view的类,这里负责画图
public class MyFanView extends View {
Paint paint = null;
int n = 0;
int speed = 5;
public MyFanView(Context context) {
super(context);
paint = new Paint();
}
@Override
protected void onDraw(Canvas canvas) {
RectF oval = new RectF(0, 0, 230, 240);
paint.setColor(Color.BLUE);
canvas.drawArc(oval, n, 60, true, paint);
paint.setColor(Color.GREEN);
canvas.drawArc(oval, n + 120, 60, true, paint);
paint.setColor(Color.RED);
canvas.drawArc(oval, n + 240, 60, true, paint);
super.onDraw(canvas);
}
public void move() {
n += speed;
super.invalidate();// 刷新一次窗口视图
}
}
2、这个是Activity中的方法,这来注意了这线程是主线程,有点类似我们的cpu的双核来完成这个线程的任务
public class MainActivity extends Activity {
MyFanView fanView = null;
Runnable myRun = new Runnable() {
@Override
public void run() {
fanView.move();
//通过视图的post方法来开启线程
fanView.post(myRun);
System.out.println(Thread.currentThread().getName());
}
};
@Override
protected void onResume() {
fanView.post(myRun);
super.onResume();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
fanView = new MyFanView(getApplicationContext());
setContentView(fanView);
}
@Override
protected void onDestroy() {
fanView.removeCallbacks(myRun);
super.onDestroy();
}
}
十四、surfaceview
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MySurfaceView surfaceView = new MySurfaceView(this);
setContentView(surfaceView);
}
/**
* SurfaceView动画制作:
* 1、添加监听器SurfaceHolder SurfaceHolder:Surface持有者,补做Surface对象产生和销毁的事件。
* 2、自己制作动画制作的绘制方法
* 3、使用Thread启动和停止完成在Surface对象上的绘图操作。
* 4、必须通过Surface启动和销毁的间隔时间控制动画播放速度。
*
*/
public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback , Runnable{
Context context = null;
SurfaceHolder surfaceHolder = null;
Canvas canvas = null;
Paint paint = null;
boolean isStop = true;
//设置小球起始的坐标
int startX = 0;
public MySurfaceView(Context context) {
super(context);
this.context = context;
//SurfaceView和监听器SurfaceHolder.Callback绑定
surfaceHolder = this.getHolder();
surfaceHolder.addCallback(this);
//响应用户在窗口的触摸事件
setFocusable(true);
setFocusableInTouchMode(true);
paint = new Paint();
}
/**
* Surface对象创建事件
*/
@Override
public void surfaceCreated(SurfaceHolder holder) {
isStop = true;
new Thread(this).start();
}
/**
* Surface切换(Change)事件
*/
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
/**
* Surface对象实例销毁事件
*/
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
isStop = false;
}
/**
* 实现线程,子线程在surfaceview对象上绘图
*/
@Override
public void run() {
while(isStop){
//必须设置每秒25个surfaceview对象绘图
//1、得到画一个小球需要多长的时间
long startTime = System.currentTimeMillis();
synchronized (surfaceHolder) {
myDraw();
}
long endTime = System.currentTimeMillis();
long diffTime = endTime - startTime;
/**
* 理解这里的算法:中间是我们自己写的方法myDraw(),加上同步块,由方法可以确认开始时间和结束时间这样
*
* 能确定画一次图的时间,然后通过控制线程的yield()方法,当我们的时间执行的时间的多少就能控制这里的速度,因为每次
*
* 画图都是在坐标上控制的
*/
while(diffTime <= 40){
diffTime = (int)(System.currentTimeMillis()-startTime);
//子线程切换到主线程完成View绘制
Thread.yield();
}
}
}
public void myDraw(){
/**
* 画图,然后由线程调用,这个图必须画到surface上
*
* canvas:整个窗口
*
* SurfaceHolder获取Surface所代表窗口
*/
try {
canvas = surfaceHolder.lockCanvas();
//设置surface的背景色,重新绘制surface的背景色,才有了一块画布,才能出来
//这里的canvas画布就是surfaceview
canvas.drawColor(Color.WHITE);
paint.setColor(Color.BLACK);
//每次向右移动10个像素
startX= startX+10;
if(canvas != null){
//surface对象已经实例化
canvas.drawCircle(startX, 120, 10, paint);
}
} catch (Exception e) {
e.printStackTrace();
}finally{
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
雷电飞机背景
public class AnimationView extends SurfaceView implements Callback {
Context ctxt = null;
Canvas canvas = null;
Paint paint = null;
SurfaceHolder surfaceHolder = null;
Bitmap bitmap01 = null;
Bitmap bitmap02 = null;
boolean isStop = false;
MyThread thread = null;
int backY01 = 0;
int backY02 = 0;
int screenWidth = 0;
int screenHeight = 0;
public AnimationView(Context context, int width, int height) {
super(context);
ctxt = context;
this.screenWidth = width;
this.screenHeight= height;
paint = new Paint();
surfaceHolder = this.getHolder();
surfaceHolder.addCallback(this);
bitmap01 = ReadBitMap(ctxt,R.drawable.map_0);
bitmap02 = ReadBitMap(ctxt,R.drawable.map_1);
backY01 = 0;
backY02 = -screenHeight;
}
class MyThread extends Thread{
@Override
public void run() {
while (isStop) {
long startTime = System.currentTimeMillis();
try {
synchronized (surfaceHolder) {
canvas = surfaceHolder.lockCanvas();
Draw();
}
} catch (Exception e) {
// TODO: handle exception
}finally{
surfaceHolder.unlockCanvasAndPost(canvas);
}
long endTime = System.currentTimeMillis();
int diffTime =
(int)(endTime-startTime);
while (diffTime < 200) {
diffTime = (int)(System.currentTimeMillis()-startTime);
Thread.yield();
}
}
super.run();
}
}
public void Draw(){
renderBack();
updateBack();
}
public void renderBack(){
canvas.drawBitmap(bitmap01, 0, backY01, paint);
canvas.drawBitmap(bitmap02, 0, backY02, paint);
}
public void updateBack(){
backY01+=10;
backY02+=10;
if (backY01 == screenHeight) {
backY01 = -screenHeight;
}
if (backY02 == screenHeight) {
backY02 = -screenHeight;
}
}
public Bitmap ReadBitMap(Context context, int resId) {
BitmapFactory.Options opt =
new BitmapFactory.Options();
opt.inPreferredConfig = Bitmap.Config.RGB_565;
opt.inPurgeable = true;
opt.inInputShareable = true;
// 获取资源图片
InputStream is =
context.getResources().openRawResource(resId);
return BitmapFactory.decodeStream(is, null, opt);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
isStop = true;
thread = new MyThread();
thread.start();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
isStop = false;
}
}