[declaration]
First of all, this series of articles are based on their own understanding and practice. You are welcome to correct what may be wrong.
Secondly, this is an introductory series, and the knowledge involved is limited to enough. There are many blog posts on the Internet for you to learn.
Finally, I hope you can gain something.
text
In android development, the most commonly used way to draw pictures is ImageView and set src. So is there any other scheme to draw pictures?
Of course!!!
Three schemes
1. Set setImageBitmap through Imageview
final String path = Environment.getExternalStorageDirectory().getPath() + File.separator + "Pictures" + File.separator + "tmp.jpg"; Bitmap bitmap = BitmapFactory.decodeFile(path); imageView.setImageBitmap(bitmap);
2. Define Paint and read Bitmap through custom View, and then use Canvas to draw Bitmap in onDraw
public class CustomView extends View { private Paint paint; private Bitmap bitmap; public CustomView(Context context) { this(context,null,0); } public CustomView(Context context, @Nullable AttributeSet attrs) { this(context, attrs,0); } public CustomView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); paint = new Paint(); paint.setAntiAlias(true); paint.setStyle(Paint.Style.STROKE); String path = Environment.getExternalStorageDirectory().getPath() + File.separator + "Pictures" + File.separator + "tmp.jpg"; bitmap = BitmapFactory.decodeFile(path); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if(bitmap!=null&&!bitmap.isRecycled()) { canvas.drawBitmap(bitmap, 0, 0, paint); } } }
3. Through the surfaceview and the SufaceHolder of the surfaceview, get it to the canvas and draw it.
surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() { @Override public void surfaceCreated(SurfaceHolder holder) { if(holder == null){ return; } Paint paint = new Paint(); paint.setAntiAlias(true); // paint.setStyle(Paint.Style.STROKE); String path = Environment.getExternalStorageDirectory().getPath() + File.separator + "Pictures" + File.separator + "tmp.jpg"; Bitmap bitmap1 = BitmapFactory.decodeFile(path); Canvas canvas = null; try { canvas = holder.lockCanvas(); canvas.drawBitmap(bitmap1,0,0,paint); }catch (Exception e){ e.printStackTrace(); } finally { if(canvas!=null){ holder.unlockCanvasAndPost(canvas); } } Log.d(TAG, "surfaceCreated: "); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { Log.d(TAG, "surfaceChanged: format"+format+" w="+width+"h="+height); } @Override public void surfaceDestroyed(SurfaceHolder holder) { Log.d(TAG, "surfaceDestroyed: "); } });
Comparison of advantages and disadvantages of SurfaceView and View and usage scenarios
Through the above example, we can see the difference between the use of SurfaceView and view. View can be drawn directly through the API encapsulated by ImageView or Canvas in view's onDraw. The SurfaceView is drawn through the Canvas through the SurfaceHolder.
Let's talk about the difference between SurfaceView and view
All views in a window share a window, corresponding to a surface (drawing surface). There is a Canvas in the surface, which can be used for drawing. In WMS, only the DecorView of the top Layer can be seen. In WMS, corresponding to WindowState, when app requests to refresh the surface, it will establish a corresponding Layer in the SurfaceFlinger.
advantage:
- It can be drawn in the sub thread – "which is applicable to the passive and frequently refreshed interface, such as video playback or games
- Refreshing only refreshes itself, not all viewHierchy in other views, so as to avoid refreshing the whole viewHierchy,
The performance will be better. - Double buffer mechanism to avoid flicker and improve performance.
Disadvantages:
- The animation of view is not valid for sureface
Turn off the hardware acceleration of all view s in the window to make it opaque.
How to use:
Sureface.CallBack.
Sureface.getHolder
And sureface Lockcavas obtains the canvas, performs the canvas operation, and then sureface Unlock cavasandpost to update the page.
Question:
- Why is surfacetested called when the surfaceView is invisible and re create d when it is visible again?
[answer:]
Because the double buffering mechanism of SurfaceView consumes a lot of memory, Android stipulates that when SurfaceView is not visible, it will be destroyed
SurfaceHolder of Surfaceview to save system resources.
Knowledge supplement
Acquisition of Android 10 + storage permission
When writing the demo, because a picture is read from external storage for drawing, there will be trouble in obtaining external storage permissions. google's acquisition of user permissions is becoming more and more convergent, which is a good thing. The granting of permissions to users can be controlled by themselves, which makes a better guarantee for privacy and security. So how should developers get the user's storage permissions? There are three steps to do:
- Android mainfest is registered in the manifest file
- Application add android:requestLegacyExternalStorage = "true"
- Dynamic acquisition through AppOpsManager
Summary
-
Through this chapter, we learned that the root of drawing pictures is to get Canvas and draw bitmap on it.
You can use the API provided by ImageView; You can customize the View and draw the drawbitmap of canvas in the onDraw method; You can also use the SurfaceView to go through the lockCanvas of the surface when onSurfaceCreate, then draw the drawbitmap of the canvas, and finally draw in the unlockCanvasAndPost. -
The biggest difference between surfaceview and View is that surfaceview has its own separate window and its own independent layer layer in the corresponding WMS. It can be drawn in the sub thread. The refresh will not affect other views in the View tree structure. It is suitable for scenes with passive frequent refresh. The corresponding disadvantage is that the View animation is invalid for the surfaceview, such as moving and zooming. The most obvious performance is that the page is transparent when the animation enters or slides out of the surfaceview page. But in fact, it is possible to turn off the hardware acceleration of View.
-
About the life cycle of SurfaceHolder of surfaceview, the surfaceview is destroyed when it is invisible and re created when it is visible. The reason is that the surfaceview adopts a double buffer mechanism to ensure that the refresh does not flicker. But double buffering consumes more memory than, so android does the above strategy. The permissions of reading sd card content above android 10 are converged by google. First, it is necessary to register in android manifest, and then dynamically obtain it before use. It is also necessary to add it in the Application of android manifest.