Seven, graphics and image processing

2019-06-06

Android graphics processing Overview

  • Static graphics: Generally these graphics files to add as a resource file to the project can be. Drawable then processed by various classes.
  • Dynamic Graphics Processing: the code needed to draw stop. It relates to the canvas Canvas, Paint and other types of brushes.
15569173-60dbb25b4125c152.png
image.png

2D categories:

  • android.graphics
  • android.graphics.drawable
  • android.graphics.drawable.shapes
  • android.view.animation
    3D类:
  • android.opengl

ImageView display picture method
setImagexxx (), for example:

  • setImageResource(int resId)
  • setImageDrawable(Drawable drawable)
  • setImageBitmap(Bitmap bm)

Bitmap and BitmapFactory:
BitmapFactory create Bitmap, Bitmap object is because there is no recovery and lead to OutOfMemory error, whether isRecycled () judgment has been recovered, recycle () to force a recovery target their own
case:


public class MainActivity extends Activity
{
    String[] images = null;
    AssetManager assets = null;
    int currentImg = 0;
    ImageView image;
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        image = (ImageView) findViewById(R.id.image);
        try
        {
            assets = getAssets();
            // 获取/assets/目录下所有文件
            images = assets.list("");
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        // 获取next按钮
        final Button next = (Button) findViewById(R.id.next);
        // 为next按钮绑定事件监听器,该监听器将会查看下一张图片
        next.setOnClickListener(new OnClickListener()
        {
            @Override
            public void onClick(View sources)
            {
                // 如果发生数组越界
                if (currentImg >= images.length)
                {
                    currentImg = 0;
                }
                // 找到下一个图片文件
                while (!images[currentImg].endsWith(".png")
                        && !images[currentImg].endsWith(".jpg")
                        && !images[currentImg].endsWith(".gif"))
                {
                    currentImg++;
                    // 如果已发生数组越界
                    if (currentImg >= images.length)
                    {
                        currentImg = 0;
                    }
                }
                InputStream assetFile = null;
                try
                {
                    // 打开指定资源对应的输入流
                    assetFile = assets.open(images[currentImg++]);
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
                BitmapDrawable bitmapDrawable = (BitmapDrawable) image
                    .getDrawable();
                // 如果图片还未回收,先强制回收该图片
                if (bitmapDrawable != null
                        && !bitmapDrawable.getBitmap().isRecycled()) // ①
                {
                    bitmapDrawable.getBitmap().recycle();
                }
                // 改变ImageView显示的图片
                image.setImageBitmap(BitmapFactory
                    .decodeStream(assetFile)); // ②
            }
        });
    }
}
15569173-bb4ba17bd92dcf32.png
image.png

Drawing: Canvas, Paint

Canvas graphics transformation method provided

  • rotate (float degrees, float px, float py): performing a rotation of the Canvas
  • scale (float sx, float sy, float px, float py): perform scaling on Canvas
  • translate (float dx, float dy) : Canvas move
    the brush on the Canvas: Paint
  • Paint class mainly used to set the drawing style, including color pen, brush stroke thickness, fill style.

Case, run again:


public class MyView extends View
{
    public MyView(Context context, AttributeSet set)
    {
        super(context, set);
    }
    @Override
    // 重写该方法,进行绘图
    protected void onDraw(Canvas canvas)
    {
        super.onDraw(canvas);
        // 把整张画布绘制成白色
        canvas.drawColor(Color.WHITE);
        Paint paint = new Paint();
        // 去锯齿
        paint.setAntiAlias(true);
        paint.setColor(Color.BLUE);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(4);
        int viewWidth = this.getWidth();
        // 绘制圆形
        canvas.drawCircle(viewWidth / 10 + 10, viewWidth / 10 + 10
            , viewWidth / 10, paint);
        // 绘制正方形
        canvas.drawRect(10 , viewWidth / 5 + 20 , viewWidth / 5 + 10
            , viewWidth * 2 / 5 + 20 , paint);
        // 绘制矩形
        canvas.drawRect(10, viewWidth * 2 / 5 + 30, viewWidth / 5 + 10
            , viewWidth / 2 + 30, paint);
        RectF re1 = new RectF(10, viewWidth / 2 + 40
            , 10 + viewWidth / 5 ,viewWidth * 3 / 5 + 40);
        // 绘制圆角矩形
        canvas.drawRoundRect(re1, 15, 15, paint);
        RectF re11 = new RectF(10, viewWidth * 3 / 5 + 50
            , 10 + viewWidth / 5 ,viewWidth * 7 / 10 + 50);
        // 绘制椭圆
        canvas.drawOval(re11, paint);
        // 定义一个Path对象,封闭成一个三角形
        Path path1 = new Path();
        path1.moveTo(10, viewWidth * 9 / 10 + 60);
        path1.lineTo(viewWidth / 5 + 10, viewWidth * 9 / 10 + 60);
        path1.lineTo(viewWidth / 10 + 10, viewWidth * 7 / 10 + 60);
        path1.close();
        // 根据Path进行绘制,绘制三角形
        canvas.drawPath(path1, paint);
        // 定义一个Path对象,封闭成一个五角形
        Path path2 = new Path();
        path2.moveTo(10 + viewWidth / 15, viewWidth * 9 / 10 + 70);
        path2.lineTo(10 + viewWidth * 2 / 15, viewWidth * 9 / 10 + 70);
        path2.lineTo(10 + viewWidth / 5, viewWidth + 70);
        path2.lineTo(10 + viewWidth / 10, viewWidth * 11/10 + 70);
        path2.lineTo(10 , viewWidth + 70);
        path2.close();
        // 根据Path进行绘制,绘制五角形
        canvas.drawPath(path2, paint);
        // ----------设置填充风格后绘制----------
        paint.setStyle(Paint.Style.FILL);
        paint.setColor(Color.RED);
        // 绘制圆形
        canvas.drawCircle(viewWidth * 3 / 10 + 20, viewWidth / 10 + 10
            , viewWidth / 10, paint);
        // 绘制正方形
        canvas.drawRect(viewWidth / 5 + 20 , viewWidth / 5 + 20
            , viewWidth * 2 / 5 + 20 , viewWidth * 2 / 5 + 20 , paint);
        // 绘制矩形
        canvas.drawRect(viewWidth / 5 + 20, viewWidth * 2 / 5 + 30
            , viewWidth * 2 / 5 + 20 , viewWidth / 2 + 30, paint);
        RectF re2 = new RectF(viewWidth / 5 + 20, viewWidth / 2 + 40
            , 20 + viewWidth * 2 / 5 ,viewWidth * 3 / 5 + 40);
        // 绘制圆角矩形
        canvas.drawRoundRect(re2, 15, 15, paint);
        RectF re21 = new RectF(20 + viewWidth / 5, viewWidth * 3 / 5 + 50
            , 20 + viewWidth * 2 / 5 ,viewWidth * 7 / 10 + 50);
        // 绘制椭圆
        canvas.drawOval(re21, paint);
        // 定义一个Path对象,封闭成一个三角形
        Path path3 = new Path();
        path3.moveTo(20 + viewWidth / 5, viewWidth * 9 / 10 + 60);
        path3.lineTo(viewWidth * 2 / 5 + 20, viewWidth * 9 / 10 + 60);
        path3.lineTo(viewWidth * 3 / 10 + 20, viewWidth * 7 / 10 + 60);
        path3.close();
        // 根据Path进行绘制,绘制三角形
        canvas.drawPath(path3, paint);
        // 定义一个Path对象,封闭成一个五角形
        Path path4 = new Path();
        path4.moveTo(20 + viewWidth *4 / 15, viewWidth * 9 / 10 + 70);
        path4.lineTo(20 + viewWidth / 3, viewWidth * 9 / 10 + 70);
        path4.lineTo(20 + viewWidth * 2 / 5, viewWidth + 70);
        path4.lineTo(20 + viewWidth * 3 / 10, viewWidth * 11/10 + 70);
        path4.lineTo(20 + viewWidth / 5 , viewWidth + 70);
        path4.close();
        // 根据Path进行绘制,绘制五角形
        canvas.drawPath(path4, paint);
        // ----------设置渐变器后绘制----------
        // 为Paint设置渐变器
        Shader mShader = new LinearGradient(0, 0, 40, 60
            , new int[] {Color.RED, Color.GREEN, Color.BLUE, Color.YELLOW }
            , null , Shader.TileMode.REPEAT);
        paint.setShader(mShader);
        //设置阴影
        paint.setShadowLayer(25 , 20 , 20 , Color.GRAY);
        // 绘制圆形
        canvas.drawCircle(viewWidth / 2 + 30, viewWidth / 10 + 10
            , viewWidth / 10, paint);
        // 绘制正方形
        canvas.drawRect(viewWidth * 2 / 5 + 30 , viewWidth / 5 + 20
            , viewWidth * 3 / 5 + 30 , viewWidth * 2 / 5 + 20 , paint);
        // 绘制矩形
        canvas.drawRect(viewWidth * 2 / 5 + 30, viewWidth * 2 / 5 + 30
            , viewWidth * 3 / 5 + 30 , viewWidth / 2 + 30, paint);
        RectF re3 = new RectF(viewWidth * 2 / 5 + 30, viewWidth / 2 + 40
            , 30 + viewWidth * 3 / 5 ,viewWidth * 3 / 5 + 40);
        // 绘制圆角矩形
        canvas.drawRoundRect(re3, 15, 15, paint);
        RectF re31 = new RectF(30 + viewWidth *2 / 5, viewWidth * 3 / 5 + 50
            , 30 + viewWidth * 3 / 5 ,viewWidth * 7 / 10 + 50);
        // 绘制椭圆
        canvas.drawOval(re31, paint);
        // 定义一个Path对象,封闭成一个三角形
        Path path5 = new Path();
        path5.moveTo(30 + viewWidth * 2/ 5, viewWidth * 9 / 10 + 60);
        path5.lineTo(viewWidth * 3 / 5 + 30, viewWidth * 9 / 10 + 60);
        path5.lineTo(viewWidth / 2 + 30, viewWidth * 7 / 10 + 60);
        path5.close();
        // 根据Path进行绘制,绘制三角形
        canvas.drawPath(path5, paint);
        // 定义一个Path对象,封闭成一个五角形
        Path path6 = new Path();
        path6.moveTo(30 + viewWidth * 7 / 15, viewWidth * 9 / 10 + 70);
        path6.lineTo(30 + viewWidth * 8 / 15, viewWidth * 9 / 10 + 70);
        path6.lineTo(30 + viewWidth * 3 / 5, viewWidth + 70);
        path6.lineTo(30 + viewWidth / 2, viewWidth * 11/10 + 70);
        path6.lineTo(30 + viewWidth * 2 / 5 , viewWidth + 70);
        path6.close();
        // 根据Path进行绘制,绘制五角形
        canvas.drawPath(path6, paint);
        // ----------设置字符大小后绘制----------
        paint.setTextSize(48);
        paint.setShader(null);
        // 绘制7个字符串
        canvas.drawText(getResources().getString(R.string.circle)
            , 60 + viewWidth * 3 / 5, viewWidth / 10 + 10, paint);
        canvas.drawText(getResources().getString(R.string.square)
            , 60 + viewWidth * 3 / 5, viewWidth * 3 / 10 + 20, paint);
        canvas.drawText(getResources().getString(R.string.rect)
            , 60 + viewWidth * 3 / 5, viewWidth * 1 / 2 + 20, paint);
        canvas.drawText(getResources().getString(R.string.round_rect)
            , 60 + viewWidth * 3 / 5, viewWidth * 3 / 5 + 30, paint);
        canvas.drawText(getResources().getString(R.string.oval)
            , 60 + viewWidth * 3 / 5, viewWidth * 7 / 10 + 30, paint);
        canvas.drawText(getResources().getString(R.string.triangle)
            , 60 + viewWidth * 3 / 5, viewWidth * 9 / 10 + 30, paint);
        canvas.drawText(getResources().getString(R.string.pentagon)
            , 60 + viewWidth * 3 / 5, viewWidth * 11 / 10 + 30, paint);
    }
}

//布局
<org.crazyit.image.MyView  
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content"
    />

Path class
case testing:


public class MainActivity extends Activity
{
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(new MyView(this));
    }
    class MyView extends View
    {
        float phase;
        PathEffect[] effects = new PathEffect[7];
        int[] colors;
        private Paint paint;
        Path path;
        public MyView(Context context)
        {
            super(context);
            paint = new Paint();
            paint.setStyle(Paint.Style.STROKE);
            paint.setStrokeWidth(4);
            // 创建并初始化Path
            path = new Path();
            path.moveTo(0, 0);
            for (int i = 1; i <= 40; i++)
            {
                // 生成40个点,随机生成它们的Y坐标,并将它们连成一条Path
                path.lineTo(i * 20, (float) Math.random() * 60);
            }
            // 初始化7个颜色
            colors = new int[] { Color.BLACK, Color.BLUE, Color.CYAN,
                Color.GREEN, Color.MAGENTA, Color.RED, Color.YELLOW };
        }
        @Override
        protected void onDraw(Canvas canvas)
        {
            // 将背景填充成白色
            canvas.drawColor(Color.WHITE);
            // -----------下面开始初始化7种路径效果----------
            // 不使用路径效果
            effects[0] = null;
            // 使用CornerPathEffect路径效果
            effects[1] = new CornerPathEffect(10);
            // 初始化DiscretePathEffect
            effects[2] = new DiscretePathEffect(3.0f, 5.0f);
            // 初始化DashPathEffect
            effects[3] = new DashPathEffect(new float[] { 20, 10, 5, 10 },
                    phase);
            // 初始化PathDashPathEffect
            Path p = new Path();
            p.addRect(0, 0, 8, 8, Path.Direction.CCW);
            effects[4] = new PathDashPathEffect(p, 12, phase,
                    PathDashPathEffect.Style.ROTATE);
            // 初始化ComposePathEffect
            effects[5] = new ComposePathEffect(effects[2], effects[4]);
            effects[6] = new SumPathEffect(effects[4], effects[3]);
            // 将画布移动到(8、8)处开始绘制
            canvas.translate(8, 8);
            // 依次使用7种不同路径效果、7种不同的颜色来绘制路径
            for (int i = 0; i < effects.length; i++)
            {
                paint.setPathEffect(effects[i]);
                paint.setColor(colors[i]);
                canvas.drawPath(path, paint);
                canvas.translate(0, 60);
            }
            // 改变phase值,形成动画效果
            phase += 1;
            invalidate();
        }
    }
}

Graphic effects processing

Matrix is ​​a matrix tools provided by Android, it does not in itself or components of image transformation (translation, rotation, scale, skew), it may be combined to control conversion pattern, and the other component API.

A control step using the Matrix transform image or components as follows:

  • Matrix object acquisition, the new Matrix object can be created and can be directly encapsulated within other objects Matrix;
  • Matrix calling method translation, rotation, scaling, skewing, and the like;
  • Matrix transformation of the program made or applied to the specified image components.

Animation

Two ways to animate ways:

  • Frame by frame animation --Frame.
    A chronological, last played aligned picture. Similar to the movie release

  • --Tween tween animation.
    Animate objects in the scene by constantly doing image transformation (translation, scaling, rotating)

View case


public class MainActivity extends Activity
{
    // 记录蝴蝶ImageView当前的位置
    private float curX = 0;
    private float curY = 30;
    // 记录蝴蝶ImageView下一个位置的坐标
    float nextX = 0;
    float nextY = 0;
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        // 获取显示蝴蝶的ImageView组件
        final ImageView imageView = (ImageView)
                findViewById(R.id.butterfly);
        final Handler handler = new Handler()
        {
            @Override
            public void handleMessage(Message msg)
            {
                if (msg.what == 0x123)
                {
                    // 横向上一直向右飞
                    if (nextX > 320)
                    {
                        curX = nextX = 0;
                    }
                    else
                    {
                        nextX += 8;
                    }
                    // 纵向上可以随机上下
                    nextY = curY + (float) (Math.random() * 10 - 5);
                    // 设置显示蝴蝶的ImageView发生位移改变
                    TranslateAnimation anim = new TranslateAnimation(
                            curX, nextX, curY, nextY);
                    curX = nextX;
                    curY = nextY;
                    anim.setDuration(200);
                    // 开始位移动画
                    imageView.startAnimation(anim); // ①
                }
            }
        };
        final AnimationDrawable butterfly = (AnimationDrawable)
                imageView.getBackground();
        imageView.setOnClickListener(new OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                // 开始播放蝴蝶振翅的逐帧动画
                butterfly.start();  // ②
                // 通过定制器控制每0.2秒运行一次TranslateAnimation动画
                new Timer().schedule(new TimerTask()
                {
                    @Override
                    public void run()
                    {
                        handler.sendEmptyMessage(0x123);
                    }
                }, 0, 200);
            }
        });
    }
}

Reproduced in: https: //www.jianshu.com/p/c72946de1043

Guess you like

Origin blog.csdn.net/weixin_33735077/article/details/91113636