动画与图形——画布与绘制

绘制几何图形

“如何在手机上绘制2D圈形呢? "这是许多android游戏开发都是常提到的问题,在android SDK当中,并没有JavaGraphics2D的函数可以使用,而是使用android.graphics底下的类来绘制20向量图。这个package提供了许多在手机上绘制图形的类与方法其中Canvas上而Paint(Android graphics Paint)类则像是彩色铅笔,给予不同的调协,即可绘制不同颜色
不同种类效果的向量图形。

本例将运用Paint对象(绘笔)的设置值不同,在Cavas(画布)上绘制空心、实心及渐变色的多种几何多形。

自定义一个View类继承View,并重写onDraw方法

package com.example.animateandview;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.Shader;
import android.view.View;

public class MyView extends View {
    public MyView(Context context) {
        super(context);
    }

    //会在主键加载时调用
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //设置画布颜色为白色
        canvas.drawColor(Color.WHITE);
        Paint paint=new Paint();//创建画笔
        //去锯齿
        paint.setAntiAlias(true);
        //设置画笔颜色
        paint.setColor(Color.RED);
        //设置画笔风格(空心、实心) STROKE:空心
        paint.setStyle(Paint.Style.STROKE);
        //设置画笔宽度
        paint.setStrokeWidth(3);
        //画一个空心圆 参数(圆心x,圆心y,半径r,paint)
        canvas.drawCircle(40,40,30,paint);
        //画一个空心正方形 参数(left,top,right,buttom,)
        canvas.drawRect(10,90,70,150,paint);
        //长方形
        canvas.drawRect(10,170,70,200,paint);
        //椭圆形
        RectF re=new RectF(10,220,70,250);
        canvas.drawOval(re,paint);
        //三角形
        Path path=new Path();
        path.moveTo(10,330);
        path.lineTo(70,330);
        path.lineTo(40,270);
        path.close();
        canvas.drawPath(path,paint);
        //梯形
        Path path1=new Path();
        path1.moveTo(10,410);
        path1.lineTo(70,410);
        path1.lineTo(55,350);
        path1.lineTo(25,350);
        path1.close();
        canvas.drawPath(path1,paint);
        //实心
        paint.setStyle(Paint.Style.FILL);
        paint.setColor(Color.BLUE);
        //画一个实心圆 参数(圆心x,圆心y,半径r,paint)
        canvas.drawCircle(120,40,30,paint);
        //画一个实心正方形 参数(left,top,right,buttom,)
        canvas.drawRect(90,90,150,150,paint);
        //长方形
        canvas.drawRect(90,170,150,200,paint);
        //椭圆形
        RectF re1=new RectF(90,220,150,250);
        canvas.drawOval(re1,paint);
        //三角形
        Path path2=new Path();
        path2.moveTo(90,330);
        path2.lineTo(150,330);
        path2.lineTo(120,270);
        path2.close();
        canvas.drawPath(path2,paint);
        //梯形
        Path path3=new Path();
        path3.moveTo(90,410);
        path3.lineTo(150,410);
        path3.lineTo(135,350);
        path3.lineTo(105,350);
        path3.close();
        canvas.drawPath(path3,paint);
        //绘制渐变色
        Shader shader=new LinearGradient(0,0,100,100,new int[]{
                Color.RED,Color.GREEN,Color.BLUE,Color.YELLOW},null,Shader.TileMode.REPEAT);
        paint.setShader(shader);
        //画一个渐变圆 参数(圆心x,圆心y,半径r,paint)
        canvas.drawCircle(200,40,30,paint);
        //画一个渐变正方形 参数(left,top,right,buttom,)
        canvas.drawRect(170,90,230,150,paint);
        //长方形
        canvas.drawRect(170,170,230,200,paint);
        //椭圆形
        RectF re2=new RectF(170,220,230,250);
        canvas.drawOval(re2,paint);
        //三角形
        Path path4=new Path();
        path4.moveTo(170,330);
        path4.lineTo(230,330);
        path4.lineTo(200,270);
        path4.close();
        canvas.drawPath(path4,paint);
        //梯形
        Path path5=new Path();
        path5.moveTo(170,410);
        path5.lineTo(230,410);
        path5.lineTo(215,350);
        path5.lineTo(185,350);
        path5.close();
        canvas.drawPath(path5,paint);
        //文字
        paint.setTextSize(24);
        canvas.drawText("圆形",240,50,paint);
        canvas.drawText("正方形",240,120,paint);
        canvas.drawText("长方形",240,190,paint);
        canvas.drawText("椭圆形",240,250,paint);
        canvas.drawText("三角形",240,320,paint);
        canvas.drawText("梯形",240,390,paint);
    }
}

显示文件修改setContentView

setContentView(new MyView(this));

android u3d 图片 android绘制3d图形_android u3d 图片


问题:有个问题就是,渐变色只显示圆形和椭圆,多边形和文字不显示

图像绘制

自定义一个View类继承View,并重写onDraw方法

package com.example.animateandview;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.view.View;

public class MyImageView extends View {
    public MyImageView(Context context) {
        super(context);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Paint paint=new Paint();
        Bitmap bitmap= BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher);
        canvas.drawBitmap(bitmap,0,0,paint);

    }
}

修改setContentView

setContentView(new MyView(this));

android u3d 图片 android绘制3d图形_ide_02

SurfaceView

SurfaceView是视图(View)的继承类,这个视图里内嵌了一个专门用于绘制的Surface。你可以控制这个Surface的格式和尺寸SurfaceView控制这个Surface的绘制位置。可以直接从内存或者DMA等硬件接口取得图像数据,是个非常重要的绘图容器。

传统View及其派生类的更新只能在UI线程,然而UI线程还同时处理其他交互逻辑,这就无法保证view更新的速度和帧率了,而SurfaceView可以用独立的线程来进行绘制,因此可以提供更高的帧率。

例如游戏,摄像头取景等场景就比较适合用SurfaceView来实现。写入到Surface的内容可以被直接复制到显存从而显示出来,这使得显示速度会非常快。

package com.example.animateandview;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback {

    private SurfaceHolder holder;
    private MyThread myThread;

    public MySurfaceView(Context context) {
        super(context);
        holder=this.getHolder();
        holder.addCallback(this);//添加回调接口

    }

    //线程内部类
    class MyThread implements Runnable{
        private SurfaceHolder holder;
        public boolean isRun;
        public MyThread(SurfaceHolder holder){
            this.holder=holder;
            isRun=true;
        }
        @Override
        public void run() {
            int count=0;
            Canvas canvas=null;
            while (isRun){
                try {
                    synchronized (holder){//同步块
                        canvas=holder.lockCanvas();//锁定画布
                        canvas.drawColor(Color.WHITE);
                        Paint paint=new Paint();
                        paint.setColor(Color.RED);
                        paint.setStyle(Paint.Style.FILL);
                        paint.setAntiAlias(true);
                        canvas.drawRect(10,10,100,100,paint);
                        paint.setTextSize(24);
                        canvas.drawText("当前是第"+(count++)+"秒",10,150,paint);

                        Thread.sleep(1000);//休眠1秒
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    holder.unlockCanvasAndPost(canvas);//释放
                }
            }
        }
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        myThread=new MyThread(holder);
        myThread.isRun=true;
        new Thread(myThread).start();
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        myThread.isRun=false;
    }
}

修改setContentView

setContentView(new MySurfaceView(this));

android u3d 图片 android绘制3d图形_ide_03

SurfaceView实现视频播放
package com.example.animateandview;

import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;

import java.io.IOException;

public class Main5Activity extends AppCompatActivity implements SurfaceHolder.Callback {

    private SurfaceView surfaceView;
    private SurfaceHolder holder;
    private MediaPlayer player;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main5);
        surfaceView=findViewById(R.id.surfaceView);
        holder=surfaceView.getHolder();
        holder.addCallback(this);
        holder.setFixedSize(320,220);//设置分辨率,不设置即为视频默认分辨率
    }

    public void playClick(View view){
        player.start();
    }

    public void pauseClick(View view){
        player.pause();
    }

    public void stopClick(View view){
        player.stop();
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        player=new MediaPlayer();
        player.setAudioStreamType(AudioManager.STREAM_MUSIC);
        player.setDisplay(holder);
        String path= Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES)+"/2.mp4";
        try {
            player.setDataSource(path);//设置播放视频源
            player.prepare();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        if (player!=null){
            if (player.isPlaying()){
                player.stop();
                player.release();
            }
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (player!=null){
            if (player.isPlaying()){
                player.stop();
                player.release();
            }
        }
    }
}

设置权限,之前忘记设置,导致找不到文件,视频无法播放

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

android u3d 图片 android绘制3d图形_android u3d 图片_04

Draw 9-patch

与传统的png格式图片相比,9.png 格式图片在图片四周有一圈一个像素点组成的边沿,该边沿用于对图片的可扩展区和内容显示区进行定义。这种格式的图片在android环境下具有自适应调节大小的能力。

运行android SDK中tools路径下的draw9patch工具:
给.9图片划线,指的是通过划线,决定图片的可拉伸区域和显示文本信息的区域。其中,上方和左 方的线是控制图片的可拉伸区域的,也就是说,上方的线控制图片横向可拉伸,左侧的线控制纵向可拉伸。下方的线和右侧的线控制图片的文本区域,也就是说,如果图片上有text,就会杷位置控制在下方和右侧的线围城的区域里。

如果想制除划线,按住shift+鼠标左键,删除划线。

现在因为draw9patch已经被广泛使用,已经在android studio里了。

android u3d 图片 android绘制3d图形_android_05