Android Dynamic Drawing implementation

Source: Internet
Author: User
Tags semaphore

Always wanted to achieve a dynamic drawing function, that is, given a few pictures after a picture of the order of the picture. Don't understand, first.

This can do a lot of things, such as the history of Baidu Map Mapping, guide the interface to do similar animation effects.

Before I considered using Surfaceview to implement this function, think about it, to achieve this effect, you need to open a sub-thread to control the drawing time interval, in order to achieve this gradually drawing effect. Do it, find it difficult to achieve with Surfaceview, Surfaceview in the canvas and view of the canvas, a difference is that the view of the canvas is only a canvas, and then continue to operate on this canvas, All of your drawings are on a canvas, but Surfaceview is not, surfaceview each time through Holder.lockcanvas () is a new canvas, through the Holder.unlockcanvasandpost ( Canvas) will overwrite the previous canvas, meaning that what is drawn behind will obscure what was drawn in front of it, and the other difference is that Surfaceview can draw in a child thread, but it does not appear immediately after drawing. This is only visible after holder.unlockcanvasandpost (canvas), which is significantly different from the canvas in view. Based on the above two differences, I ended up using a custom view to draw with the canvas in view.

To draw a step:
(1) Drawing an incoming image
(2) Draw the line between the first image and the second image, this step is divided into two small steps
A, starting from the center of the first map to increase the fixed step, draw again and again, until close to the center point of the second picture
B, a after the drawing is complete, redraw a line, the path is consistent with the path of a, and a drawn line is erased
(3) Repeat (1), (2) step, and note that the last picture is drawn without having to draw the line again.

The need to constantly control the time interval during the drawing process also means that new sub-threads need to be opened constantly, which is very memory-intensive and can easily cause memory overflow, so here I use a thread pool to manage threads.

Code:

Create a new project Animationview

Create a new class Animationview inherit view
Add a constructor to open our thread pool in the constructor.

private void Startexecutor () {executorthread = new Thread () {@Overridepublic void Run () {//TODO auto-generated method Stu Bsuper.run (); Looper.prepare (); threadhandler = new Handler () {@Overridepublic void Handlemessage (Message msg) {//TODO auto-generated m Ethod stubsuper.handlemessage (msg); Executorservice.execute (Gettask ()); try {semaphore.acquire ();} catch ( Interruptedexception e) {//TODO auto-generated catch Blocke.printstacktrace ();} try {thread.sleep;} catch (Interruptedexception E1) {e1.printstacktrace ();}}}; Handlersemaphore.release (); Looper.loop ();}}; Executorthread.start ();}
Public Animationview (Context context) {super (context);//TODO auto-generated constructor Stubstartexecutor ();} Public Animationview (context context, AttributeSet Attrs) {Super (context, attrs);//TODO Auto-generated constructor Stubstartexecutor ();} Public Animationview (context context, AttributeSet attrs, int defstyleattr) {Super (context, attrs, defstyleattr);//TODO Auto-generated constructor Stubstartexecutor ();}

About thread pooling There's not much to talk about, but if you want to know something, you can look at my other article. Probe into the thread pool, semaphore, Looper and cache of Android
Add two methods for adding a task and removing a task
Private synchronized void AddTask (Runnable r) {if (Threadhandler = = null) try {handlersemaphore.acquire ();} catch (Interru Ptedexception e) {//TODO auto-generated catch Blocke.printstacktrace ();} Task.add (R); Threadhandler.obtainmessage (). Sendtotarget ();} Private synchronized Runnable Gettask () {return Task.removefirst ();}

Add a method to add a picture and location to our custom view
public void addimagedata (int id, rect rect) {ImageData data = new ImageData ();d Ata.setid (ID);d ata.setrect (rect); List.add (data);}
ImageData is a custom class

Package Com.example.animationview;import Android.graphics.rect;public class ImageData {private int id;private rect rect ;p ublic int getId () {return ID;} public void setId (int id) {this.id = ID;} Public Rect GetRect () {return rect;} public void SetRect (rect rect) {this.rect = rect;}}
Overwrite OnDraw function

@Overrideprotected void OnDraw (canvas canvas) {//TODO auto-generated method Stubsuper.ondraw (canvas); if (this.list! = Nu ll && this.list.size ()! = 0) {//Paint for (int i = 0; I <= index; i++) {canvas.save (); ImageData data = This.list.g ET (i); Bitmap Bitmap = Bitmapfactory.decoderesource (Getresources (), Data.getid ()), Canvas.drawbitmap (Bitmap, New Rect (0, 0, Bitmap.getwidth (), Bitmap.getheight ()), Data.getrect (), New Paint ()), Canvas.restore (); invalidate (); bitmap = null;} if (isdrawbitmap && index <= this.list.size ()//2)//Judging after there is no figure, there is a picture line {Isdrawbitmap = False;isdrawstep = True;iss Endstephandler = True;stepstartx = 0;stepstarty = 0;} Draw Intermediate steps if (isdrawstep) {ImageData data1 = this.list.get (index); ImageData data2 = this.list.get (index + 1); if (stepstartx = = 0 && Stepstarty = = 0) {Stepstartx = Data1.getrect (). CenterX (); stepstarty = Data1.getrect (). CenterY (); stepx = (( float) (Data2.getrect (). CenterX ()-Data1.getrect (). CenterX ()))/16;stepy = ((float) (Data2.getrect (). cEntery ()-Data1.getrect (). CenterY ())/16;stependx = stepstartx + Stepx;stependy = Stepstarty + stepy;} Canvas.save (); Paint paint = new paint ();p aint.setstrokewidth (3);p Aint.setstyle (Style.stroke);p Aint.setantialias (true); Paint.setcolor (color.red); Canvas.drawline (Stepstartx, Stepstarty, Stependx, Stependy,paint); Canvas.restore (); Invalidate (); System.out.println ("Math:" + Math.Abs (Double) (Stependx-data2.getrect (). CenterX ())) + "" + Math.Abs ((double) step X); if (Math.Abs (double) (Stependx-data2.getrect (). CenterX ())) <= Math.Abs ((double) stepx) && Math.Abs (( Double) (Stependy-data2.getrect (). CenterY ())) <= Math.Abs ((double) stepy)//Draw line {Isstopdrawstep = True;if ( Issendstephandler) {Issendstephandler = False;addtask (new Runnable () {@Overridepublic void Run () {//TODO auto-generated Method Stubhandler.obtainmessage (2). Sendtotarget (); Semaphore.release ();});}} else {//Draw intermediate step if (issendstephandler) {Issendstephandler = False;addtask (new Runnable () {@Overridepublic voID run () {//TODO auto-generated method Stubhandler.obtainmessage (1). Sendtotarget (); Semaphore.release ();}});}} Draw line for (int i = 0; I <= lineindex; i++) {ImageData data1 = This.list.get (i); ImageData data2 = This.list.get (i + 1); St Artx = Data1.getrect (). CenterX (); starty = Data1.getrect (). CenterY (); endx = Data2.getrect (). CenterX (); EndY = Data2.getrect (). CenterY (); Canvas.save (); Paint paint = new paint ();p aint.setstrokewidth (3);p Aint.setstyle (Style.stroke);p Aint.setantialias (true); Paint.setcolor (color.red); Canvas.drawline (StartX, Starty, EndX, EndY, paint); Canvas.restore (); invalidate (); if ( Isstopdrawstep && (Recodelineindex! = Lineindex)) {Recodelineindex = Lineindex;isdrawstep = false; Isstopdrawstep = false;}} if (isdrawline && lineindex <= this.list.size ()-2) {isdrawline = False;addtask (new Runnable () {@Overridepubli c void Run () {//TODO auto-generated method stubhandler.obtainmessage (0). Sendtotarget (); Semaphore.release ();}});}}

Here is the key code, inside I made a simple comment, I can also see that I used a lot of Boolean variables to control the drawing frequency, have to do so, because we do not do the view is constantly in the refresh, do not control, will produce a lot of empty tasks, Using thread pool management can be difficult to see, if you switch the thread pool to a normal sub-thread, you will find that your program is likely to crash in less than 5 seconds, and the crash is due to a memory overflow.

Complete code for Animationview

Package Com.example.animationview;import Java.util.linkedlist;import Java.util.list;import Java.util.concurrent.executorservice;import Java.util.concurrent.executors;import Java.util.concurrent.Semaphore ; 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.graphics.paint.style;import Android.graphics.rect;import Android.os.handler;import Android.os.Looper; Import Android.os.message;import Android.util.attributeset;import Android.view.view;public class AnimationView Extends View {Private Boolean Isdrawbitmap = True, Isdrawline = false;private Boolean isdrawstep = False;private Boolean I Sstopdrawstep = false;private Boolean issendstephandler = false;private int recodelineindex = -1;private List<ImageDat a> list = new linkedlist<imagedata> ();p rivate int index = 0, Lineindex = -1;//bitmap index private float StartX = 0, Starty = 0, ENdX, endy;//draw line start, pitch private float stepstartx, Stepstarty, stepx, Stepy, Stependx, stependy;private executorservice execut Orservice = Executors.newfixedthreadpool (3);p rivate Semaphore handlersemaphore = new Semaphore (0);p rivate Semaphore semaphore = new Semaphore (3);p rivate linkedlist<runnable> task = new linkedlist<runnable> ();p rivate Handler Threadhandler;private Thread executorthread;private Handler Handler = new Handler () {@Overridepublic void Handlemessage (  Message msg) {//TODO auto-generated Method Stubsuper.handlemessage (msg); switch (msg.what) {Case 0:isdrawbitmap = true;if (Index < List.size ()-1) index++;break;case 1:issendstephandler = true;stependx + Stepx;stependy + = Stepy;break;case 2:isdrawline = true;if (Lineindex < List.size ()-2) Lineindex++;break;}}; Public Animationview (Context context) {super (context);//TODO auto-generated constructor Stubstartexecutor ();} Public Animationview (context context, AttributeSet Attrs) {Super (context, attrs);//TODO Auto-generated constructor Stubstartexecutor ();} Public Animationview (context context, AttributeSet attrs, int defstyleattr) {Super (context, attrs, defstyleattr);//TODO Auto-generated constructor Stubstartexecutor ();} private void Startexecutor () {executorthread = new Thread () {@Overridepublic void Run () {//TODO auto-generated method Stu Bsuper.run (); Looper.prepare (); threadhandler = new Handler () {@Overridepublic void Handlemessage (Message msg) {//TODO auto-generated m Ethod stubsuper.handlemessage (msg); Executorservice.execute (Gettask ()); try {semaphore.acquire ();} catch ( Interruptedexception e) {//TODO auto-generated catch Blocke.printstacktrace ();} try {thread.sleep;} catch (Interruptedexception E1) {e1.printstacktrace ();}}}; Handlersemaphore.release (); Looper.loop ();}}; Executorthread.start ();} Private synchronized void AddTask (Runnable r) {if (Threadhandler = = null) try {handlersemaphore.acquire ();} catch (Interru Ptedexception e) {//TODO auto-generated catch Blocke.printstacktrace ();} TaSk.add (R); Threadhandler.obtainmessage (). Sendtotarget ();} Private synchronized Runnable Gettask () {return Task.removefirst ();} public void addimagedata (int id, rect rect) {ImageData data = new ImageData ();d Ata.setid (ID);d ata.setrect (rect); List.add (data);} @Overrideprotected void OnDraw (canvas canvas) {//TODO auto-generated method Stubsuper.ondraw (canvas); if (this.list! = Nu ll && this.list.size ()! = 0) {//Paint for (int i = 0; I <= index; i++) {canvas.save (); ImageData data = This.list.g ET (i); Bitmap Bitmap = Bitmapfactory.decoderesource (Getresources (), Data.getid ()), Canvas.drawbitmap (Bitmap, New Rect (0, 0, Bitmap.getwidth (), Bitmap.getheight ()), Data.getrect (), New Paint ()), Canvas.restore (); invalidate (); bitmap = null;} if (isdrawbitmap && index <= this.list.size ()//2)//Judging after there is no figure, there is a picture line {Isdrawbitmap = False;isdrawstep = True;iss Endstephandler = True;stepstartx = 0;stepstarty = 0;} Draw Intermediate steps if (isdrawstep) {ImageData data1 = this.list.get (index); ImageData data2 = This.list.get (Index + 1); if (Stepstartx = = 0 && Stepstarty = = 0) {Stepstartx = Data1.getrect (). CenterX (); stepstarty = Data1.getr ECT (). CenterY (); stepx = ((float) (Data2.getrect (). CenterX ()-Data1.getrect (). CenterX ()))/16;stepy = ((float) ( Data2.getrect (). CenterY ()-Data1.getrect (). CenterY ())/16;stependx = stepstartx + Stepx;stependy = StepStartY + StepY;} Canvas.save (); Paint paint = new paint ();p aint.setstrokewidth (3);p Aint.setstyle (Style.stroke);p Aint.setantialias (true); Paint.setcolor (color.red); Canvas.drawline (Stepstartx, Stepstarty, Stependx, Stependy,paint); Canvas.restore (); Invalidate (); System.out.println ("Math:" + Math.Abs (Double) (Stependx-data2.getrect (). CenterX ())) + "" + Math.Abs ((double) step X); if (Math.Abs (double) (Stependx-data2.getrect (). CenterX ())) <= Math.Abs ((double) stepx) && Math.Abs (( Double) (Stependy-data2.getrect (). CenterY ())) <= Math.Abs ((double) stepy)//Draw line {Isstopdrawstep = True;if ( Issendstephandler) {Issendstephandler = False;addtask(New Runnable () {@Overridepublic void Run () {//TODO auto-generated method Stubhandler.obtainmessage (2). Sendtotarget (); Semaphore.release ();}});}} else {//Draw intermediate step if (issendstephandler) {Issendstephandler = False;addtask (new Runnable () {@Overridepublic void Run () {//TOD O auto-generated Method Stubhandler.obtainmessage (1). Sendtotarget (); Semaphore.release ();}});}} Draw line for (int i = 0; I <= lineindex; i++) {ImageData data1 = This.list.get (i); ImageData data2 = This.list.get (i + 1); St Artx = Data1.getrect (). CenterX (); starty = Data1.getrect (). CenterY (); endx = Data2.getrect (). CenterX (); EndY = Data2.getrect (). CenterY (); Canvas.save (); Paint paint = new paint ();p aint.setstrokewidth (3);p Aint.setstyle (Style.stroke);p Aint.setantialias (true); Paint.setcolor (color.red); Canvas.drawline (StartX, Starty, EndX, EndY, paint); Canvas.restore (); invalidate (); if ( Isstopdrawstep && (Recodelineindex! = Lineindex)) {Recodelineindex = Lineindex;isdrawstep = false; Isstopdrawstep = false;}} if (Isdrawline &&Amp Lineindex <= this.list.size ()-2) {isdrawline = False;addtask (new Runnable () {@Overridepublic void Run () {//TODO Auto -generated method Stubhandler.obtainmessage (0). Sendtotarget (); Semaphore.release ();}});}}}
This defines the Animationview, then how to use it? It is simple, can be added to the layout file, or can be easily used directly in the code.

Used in Layout files

Fragment_main.xml

<relativelayout xmlns:android= "http://schemas.android.com/apk/res/android"    xmlns:tools= "http// Schemas.android.com/tools "    android:layout_width=" match_parent "    android:layout_height=" Match_parent "    tools:context= "Com.example.animationview.mainactivity$placeholderfragment" >    < Com.example.animationview.AnimationView        android:id= "@+id/animationview"        android:layout_width= "Match_ Parent "        android:layout_height=" Match_parent "/></relativelayout>
Package Com.example.animationview;import Android.graphics.rect;import Android.os.bundle;import Android.support.v7.app.actionbaractivity;public class Mainactivity extends Actionbaractivity {private AnimationView view; @Overrideprotected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate); Setcontentview (R.layout.fragment_main); init ();} private void Init () {//TODO auto-generated method Stubview = (Animationview) Findviewbyid (R.id.animationview); View.addimagedata (R.drawable.xin11, New rect (0, 0, 300)); View.addimagedata (R.drawable.xin16, New rect (, 150, (View.addimagedata (r.drawable.xin17, New Rect), View.addimagedata (r.drawable.xin2, New), and the Rect (100, 850, 200, 950)) View.addimagedata (R.drawable.xin5, New Rect);}}
Use directly in your code
Package Com.example.animationview;import Android.graphics.rect;import Android.os.bundle;import Android.support.v7.app.actionbaractivity;public class Mainactivity extends Actionbaractivity {@Overrideprotected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate); Animationview view = new Animationview (this), View.addimagedata (R.drawable.xin11, New Rect (0, 0, 100, 100)); View.addimagedata (R.drawable.xin16, New rect), View.addimagedata (r.drawable.xin17, New rect (300), (View.addimagedata, r.drawable.xin2, New Rect), View.addimagedata (R.drawable.xin5,.), and the New Rect (850, max, 950)); Setcontentview (view);}}
SOURCE download




Android Dynamic Drawing implementation

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.