Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to use PhotoView to implement avatar / circle clipping control in Android

2025-01-16 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)05/31 Report--

This article mainly introduces "how to use PhotoView in Android to achieve avatar / circular clipping control" related knowledge, Xiaobian through the actual case to show you the process of operation, the method of operation is simple and fast, practical, I hope that this "how to use PhotoView in Android to achieve avatar / circular clipping control" article can help you solve the problem.

The code is as follows:

Public class CircleCropView extends View {public final int CIRCLE_MARGIN = 50; public CircleCropView (Context context) {super (context);} public CircleCropView (Context context, @ Nullable AttributeSet attrs) {super (context, attrs);} public CircleCropView (Context context, @ Nullable AttributeSet attrs, int defStyleAttr) {super (context, attrs, defStyleAttr);} @ RequiresApi (api = Build.VERSION_CODES.LOLLIPOP) public CircleCropView (Context context, @ Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {super (context, attrs, defStyleAttr, defStyleRes) } @ Override protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure (widthMeasureSpec, widthMeasureSpec);} @ RequiresApi (api = Build.VERSION_CODES.O) @ Override protected void onDraw (Canvas canvas) {canvas.save (); Path path = new Path (); Rect viewDrawingRect = new Rect (); getDrawingRect (viewDrawingRect); float radius = viewDrawingRect.width () / 2-CIRCLE_MARGIN; path.addCircle (viewDrawingRect.left + radius + CIRCLE_MARGIN, viewDrawingRect.top + radius + CIRCLE_MARGIN, radius, Path.Direction.CW) Paint outsidePaint = new Paint (); outsidePaint.setAntiAlias (true); outsidePaint.setARGB (151,0,0,0); canvas.clipPath (path, Region.Op.DIFFERENCE); canvas.drawRect (viewDrawingRect, outsidePaint); canvas.restore ();}}

SquarePhotoView just changes the length and width based on PhotoView. You can rewrite the onMeasure method:

Override protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure (widthMeasureSpec, widthMeasureSpec);}

So the most critical step now is to get the Drawable or Bitmap of the current image display area from PhotoView. After a cursory glance at PhotoView's functions, I couldn't find anything that could be used. The stupid way to solve the first pit is to get plenty of food and clothing yourself-just take the bitmap of the original image, then ask PhotoView for the deformation matrix of the current picture, and get the corresponding bitmap through the matrix step by step.

In fact, there is no problem with the way of thinking, but the second pit has appeared again. The deformation matrix here, my earliest Baidu result is getSuppMatrix, I did not take a closer look at the source code, but according to my observation, I guess it should be corresponding to the latest gesture deformation result (uncertain = =, it may also be the wrong result caused by the synthesis of other pits). In short, I finally checked the source code for a while, and finally decided to use getDisplayMatrix.

This is followed by the third pit, which is used to when there are too many holes. At first, I thought the XY displacement in the matrix was the displacement of the center of the display area relative to the center of the original image, that is, if there was only a zoom operation, the displacement should be 0. But in fact, through the clipping results of special positions (such as four vertices), the XY displacement here actually shows the displacement of the point in the upper-left corner of the region relative to the origin (that is, the upper-left corner of the original image). To put it simply, the displacement can be used as the coordinates of the upper-left corner of the final display area.

Then I ushered in the fourth pit. In retrospect, this hole is actually very simple and should not have fallen into it, but I was really panicked before I figured it out at that time (alas). The problem with this pit is that the values in Matrix are based on gestures, that is, based on screen pixels (in other words, based on the actual images displayed). When cropping the bitmap, it is based on the pixels of the original image. Then there is also a problem with the zoom ratio caused by the normal display. For example, the original image is 3000x4000, and because the screen resolution is 1080mm 1920, then the picture is actually scaled down when it is displayed, the ratio is 9x25. Therefore, in the process of cutting, the displacement needs to be magnified by 25,000,9 times to restore.

Here is the key code for the cropping section (finally, there is no circle cut, just shown in CIrcleImageView):

Fun cropImage () {var degree = ImageUtils.readPictureDegree (imagePath) var bitmap = ImageUtils.getRotatedBitmap (BitmapFactory.decodeFile (imagePath), degree) var width: Int = 0 var startX: Int = 0 var startY: Int = 0 if (bitmap.width < bitmap.height) {startY = (bitmap.height-bitmap.width) / 2 width = bitmap.width} else {startX = (bitmap.width-bitmap.height) / 2 width = bitmap.height} var matrix = Matrix photo_preview.getDisplayMatrix (matrix) / / get the deformation matrix Directly fetch scaleX or translationX without var values = FloatArray (9, {0.0f}) matrix.getValues (values) var expWidth = Math.round (bitmap.width * values [0]) / / scale x var expHeight = Math.round (bitmap.height * values [4]) / / scale y var bitmap1 = Bitmap.createScaledBitmap (bitmap, expWidth, expHeight) False) val ratio = width * 1.0f / photo_preview.width startX = Math.round (startX * values [0]-values [2] * ratio) startY = Math.round (startY * values [4]-values [5] * ratio) var bitmap2 = Bitmap.createBitmap (bitmap1, startX, startY, width, width, null, false) saveImage (bitmap2)}

Here are a few more holes to explain:

You need to pay attention to the angle when reading bitmap. This is what I found when I was cutting local pictures and online pictures, some of them were positive and some of them were turned 90 degrees. Every phone is not necessarily the same, so just to be on the safe side, you need to get the angle you need to rotate from the EXIF information of the picture, and then deal with it further.

I am here because the final display is a square, and the scaleType chosen is centerCrop. So the default is to show the middle piece. So the origin of the cut also needs to start from the upper left corner of the square. Here is to calculate the origin coordinates in two cases:

Var startX: Int = 0 var startY: Int = 0 if (bitmap.width < bitmap.height) {startY = (bitmap.height-bitmap.width) / 2 width = bitmap.width} else {startX = (bitmap.width-bitmap.height) / 2 width = bitmap.height} about "how to use PhotoView to achieve avatar / circular clipping control in Android", thank you for reading. If you want to know more about the industry, you can follow the industry information channel. The editor will update different knowledge points for you every day.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report