Android读书笔记之2D图形&&动画技术

时间:2023-02-06 23:29:16

绘图技术:

2DAndroid基本组件构成

3D:通过OpenGL ES技术实现

 

两种图形引擎技术:SkiaView及其子类通过它画出来的)和OpenGL ES

 

2D绘制技术:

画布与画笔:(CanvasPaint

Paint常用方法:

setColor(int color):设置颜色

setAlpha(int a):设置透明度(0~255

setStyle:设置样式

setTextAlign:设置文本对齐方式

setTextSize:设置文本的字号

Canvas常用绘图方法:

drawPoint 绘制单个点

drawPoints 绘制多个点

drawLine 绘制单条线

drawLines 绘制多条线

drawText 绘制文本

drawArc 绘制弧线

drawRect 绘制矩形

drawBitmap 绘制图像

 

实例:绘制点和线

private class MyView extends View {

public MyView(Context context) {

super(context);

}

@Override

public void onDraw(Canvas canvas) {

float x = 0.0f, y = 100.0f;

int height = 100;

//创建画笔对象

Paint paint = new Paint();

//设置画笔颜色

paint.setColor(Color.RED);

//设置笔的粗细

paint.setStrokeWidth(5.0f);

// 在画布上画线

canvas.drawLine(x, y, x + canvas.getWidth() - 1, y, paint);

canvas.drawLine(x, y + height - 1, x + canvas.getWidth(), y+ height - 1, paint);

//重新设置画笔

paint.setColor(Color.BLACK);

paint.setStrokeWidth(10.0f);

// 准备100个数据

float[] pts = new float[100];

for (int i = 0; i < 100; i = i + 2) {

pts[i] = i * 5;

pts[i + 1] = i * 15;

}

// 在画布上画点

canvas.drawPoints(pts, 20,10, paint);

}

}

 

绘制矩形:

 private class MyView extends View {

        public MyView(Context context) {

            super(context);

        }

 

        @Override

        public void onDraw(Canvas canvas) {

            //创建画笔

            Paint paint = new Paint();

            //设置画笔颜色

            paint.setColor(Color.RED);

 

            Rect r1 = new Rect(100, 100, 600, 500);

            //绘制矩形

            canvas.drawRect(r1, paint);

 

            paint.setColor(Color.BLUE);

            RectF r2 = new RectF(200.0f, 900.0f, 600.0f, 600.0f);

            canvas.drawRect(r2, paint);

        }

    }

 

绘制弧线:

drawArc(RectF oval,float startAngle,float sweepAngle,boolean useCenter,Paint paint)

Oval 弧形边界

startAngle 圆弧开始的角度

sweepAngle 圆弧扫过的角度(顺时针为正,单位是度)

 

 

 

 

代码:

 private class MyView extends View {

        public MyView(Context context) {

            super(context);

        }

 

        @Override

        public void onDraw(Canvas canvas) {

            // 创建画笔

            Paint paint = new Paint();

            // 开启抗锯齿效果

            paint.setAntiAlias(false);

            paint.setColor(Color.BLUE);

 

            RectF oval1 = new RectF(100.0f, 100.0f, 500.0f, 500.0f);

            canvas.drawRect(oval1, paint);

 

            paint.setColor(Color.RED);

            // 绘制360度的圆

            canvas.drawArc(oval1, 0, 360, true, paint);

 

            paint.setColor(Color.BLUE);

            RectF oval2 = new RectF(100.0f, 700.0f, 400.0f, 1000.0f);

            // 绘制90135度的圆弧,包含圆心

            canvas.drawArc(oval2, 90, 135, true, paint);

 

            RectF oval3 = new RectF(500.0f, 700.0f, 800.0f, 1000.0f);

            // 绘制90135度的圆弧,不包含圆心

            canvas.drawArc(oval3, 90, 135, false, paint);

        }

    }

 

绘制位图:

两种方式获得位图(Bitmap)对象:

使用BitmapFactory获得位图:BitmapFactory工厂从资源文件中创建位图

使用BitmapDrawable获取位图:通过资源id获得输入流,再创建位图(麻烦)

 

public class MainActivity extends AppCompatActivity {

 

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(new MyView(this));

    }

    private class MyView extends View {

        public MyView(Context context) {

            super(context);

        }

        @Override

        public void onDraw(Canvas canvas) {

            //创建Bitmap对象

            Bitmap bitmap = BitmapFactory.decodeResource(getResources(), 

R.drawable.cat);

            //创建画笔对象

            Paint paint = new Paint();

            //绘制位图

            canvas.drawBitmap(bitmap, 180, 60, paint);

        }

    }

}

 

位图变化:

涉及矩阵(Matrix)类

 

三种变换常用方法:

setScale(float sx,float sy,float px,float py):设置缩放矩阵

s为缩放比例,p为缩放中心点坐标)

setRotate(float degrees,float px,float py):设置旋转矩阵

degrees为旋转度数,p为旋转中心坐标)

setTranslate(float dx,float dy):设置平移矩阵

dxx方向平移距离,dyy方向平移距离)

 

实例:位图变化

public void onDraw(Canvas canvas) {

Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.cat);

 

Matrix matrix = new Matrix();

matrix.setScale(0.8f, 0.8f, 40, 40);

matrix.setRotate(40, 300, 600);

matrix.postTranslate(100, 200);

 

//创建画笔对象

Paint paint = new Paint();

//绘制位图

canvas.drawBitmap(bitmap, matrix, paint);

}

 

 

调用Android照相机

指定意图:android.media.action.IMAGE_CAPTURE

对应常量:MediaStore.ACTION_IMAGE_CAPTURE

注【摄像】:

指定意图:android.media.action.VIDEO_CAPTURE

对应常量:MediaStore.ACTION_VIDEO_CAPTURE

 

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE)

startActivityForResult(intent,REQ_CODE_DATA);//REQ_CODE_DATA = 100

 

Protected void onActivityResult(int requestCode,int resultCode,Intent data){

//TODO

}

实例代码:实现两种情况(将图片保存起来;直接使用返回的数据)

  //返回数据的请求编码

    private final static int REQ_CODE_DATA = 100;

    //保存文件的请求编码

    private final static int REQ_CODE_SAVE = 101;

    //保存的图片文件路径,位于SD卡中

    private final static String FILE_PATH = "/mnt/sdcard/test.jpg";

 

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

 

        Button buttonTake = (Button) findViewById(R.id.buttonTake);

        buttonTake.setOnClickListener(new View.OnClickListener() {

            @Override

            public void onClick(View v) {

                //定义访问照相机意图

                Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

                //启动意图,返回请求编码为REQ_CODE_DATA

                startActivityForResult(intent, REQ_CODE_DATA);

            }

        });

 

 

 

 

 

 

 

 

        Button buttonTakeSave = (Button) findViewById(R.id.buttonTakeSave);

        buttonTakeSave.setOnClickListener(new View.OnClickListener() {

            @Override

            public void onClick(View v) {

                //定义访问照相机意图

                Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

                //创建访问文件的URI

                Uri uri = Uri.fromFile(new File(FILE_PATH));

                //设置意图附加信息

                intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);

                //启动意图,返回请求CodeREQ_CODE_SAVE

                startActivityForResult(intent, REQ_CODE_SAVE);

            }

        });

    }

 

    @Override

    protected void onActivityResult(int requestCode, int resultCode, Intent data) {

        super.onActivityResult(requestCode, resultCode, data);

 

        ImageView imageView = (ImageView) findViewById(R.id.imageView);

        Bitmap bitmap = null;

        if (resultCode == Activity.RESULT_OK) {

            switch (requestCode) {

                case REQ_CODE_DATA: // 判断请求编码是否为REQ_CODE_DATA

                    Bundle extras = data.getExtras();

                    bitmap = (Bitmap) extras.get("data");

                    imageView.setImageBitmap(bitmap);

                    break;

                case REQ_CODE_SAVE: // 判断请求编码是否为REQ_CODE_DATA

                    try {

                        InputStream is = new FileInputStream(FILE_PATH);

                        bitmap = BitmapFactory.decodeStream(is);

                        imageView.setImageBitmap(bitmap);

                    } catch (Exception e) {

                        e.printStackTrace();

                    }

            }

        }

    }

注册:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

<uses-permission android:name="android.permission.CAMERA" />

 

Android动画技术:

渐变动画:对Android的视图增加渐变动画效果。

帧变化:显示res资源目录下有序的图片

渐变动画:

透明度渐变动画。

平移动画。

缩放动画。

旋转动画。

所有动画都有两种方式实现,编程实现,XML实现

编程实现:

1.实例化动画类:Animation

2.设置动画属性

3.调用动画startAnimation()方法开始动画

四个基本类:

AlphaAnimation

TranslateAnimation

ScaleAnimation

RotateAnimation

AnimationSet是几个动画的集合

XML实现:放在资源目录/res/anim/目录下

<alpha xmlns:android="http://schemas.android.com/apk/res/android"

android:duration="5000"

android:fromAlpha="1.0"

android:toAlpha="0.0" />

<scale xmlns:android="http://schemas.android.com/apk/res/android"

    android:duration="5000"

    android:fromXScale="1.0"

    android:fromYScale="1.0"

    android:pivotX="50%"

    android:pivotY="50%"

    android:toXScale="2.0"

    android:toYScale="2.0" />

<rotate xmlns:android="http://schemas.android.com/apk/res/android"

    android:duration="5000"

    android:fromDegrees="0.0"

    android:pivotX="50%"

    android:pivotY="50%"

    android:toDegrees="360" />

<translate xmlns:android="http://schemas.android.com/apk/res/android"

    android:duration="1500"

    android:fromXDelta="0"

    android:fromYDelta="0"

    android:toXDelta="50"

    android:toYDelta="50" />

实例:渐变动画

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

Button alphaButton = (Button) findViewById(R.id.alpha_button);

alphaButton.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

//1. 编程实现

//Animation anim = new AlphaAnimation(1.0f, 0.0f);

//anim.setDuration(5000);

///2.XML实现

//从动画XML文件中加载动画对象

Animation anim = AnimationUtils.loadAnimation(MainActivity.this,

R.anim.alpha_anim);

View view = findViewById(R.id.imageView);

//在视图view上设置并开始动画

view.startAnimation(anim);

}

});

Button translateButton = (Button) findViewById(R.id.translate_button);

translateButton.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

//从动画XML文件中加载动画对象

Animation anim = AnimationUtils.loadAnimation(MainActivity.this,

R.anim.translate_anim);

View view = findViewById(R.id.imageView);

//在视图view上设置并开始动画

view.startAnimation(anim);

}

});

Button scaleButton = (Button) findViewById(R.id.scale_button);

scaleButton.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

//从动画XML文件中加载动画对象

Animation anim = AnimationUtils.loadAnimation(MainActivity.this,

R.anim.scale_anim);

View view = findViewById(R.id.imageView);

//在视图view上设置并开始动画

view.startAnimation(anim);

}

});

Button rotateButton = (Button) findViewById(R.id.rotate_button);

rotateButton.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

//从动画XML文件中加载动画对象

Animation anim = AnimationUtils.loadAnimation(MainActivity.this,

R.anim.rotate_anim);

View view = findViewById(R.id.imageView);

//在视图view上设置并开始动画

view.startAnimation(anim);

}

});

}

 

动画插值器(interpolator

Interpolator是一个接口,主要是对动画播放速度和时间进行控制

(相当于一个属性)

Android.interpolator = “@android:anim/accelerate_interpolator”//加速度播放

属性值:

LinearInterpolator 线性播放,均匀播放

AccelerateInterpolator 动画加速播放

DecelerateInterpolator 动画减速播放

AccelerateDecelerateInterpolator 先加速后减速播放

CycleInterpolator 重复播放

PathInterpolator 路径插值器

BounceInterpolator

OvershootInterpolator

AnticipateInterpolator

AnticipateOvershootInterpolator

注:CycleInterpolator插值器很特殊,需要单独的插值器XML

AndroidCycles = “10”

 

使用动画集:

XML实现:

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

<set xmlns:android="http://schemas.android.com/apk/res/android">

    <alpha xmlns:android="http://schemas.android.com/apk/res/android"

        />

    <rotate xmlns:android="http://schemas.android.com/apk/res/android"

         />

</set> 

 

 

 

代码实现:

AnimationSet set = new AnimationSet(true);// 加速度是否一样

set.addAnimation(animRotate);

set.addAnimation(animScale);

set.addAnimation(animAlpha);

// 启动动画

rlRoot.startAnimation(set);

 

帧动画:

//ToggleButton点击事件的内容

imgView.setBackgroundResource(R.drawable.frame_animation);

//imgView.setVisibility(ImageView.GONE);

 

AnimationDrawable frameAnimation = (AnimationDrawable) imgView.getBackground();

if (frameAnimation.isRunning()) {

frameAnimation.stop();

} else {

frameAnimation.stop();

frameAnimation.start();

    }