Basic functions of Android PhotoView

During the Android development process, PhotoView must have been used to realize the function of image display. In the latest version of sdk (android-23), there is a native photoView, and the code implementation is also very simple, and the logic is very clear. In actual work, the requirements we encounter may be slightly different from the existing functions of these photoviews, which need to be modified or redeveloped. This article briefly introduces the related technologies involved in photoview in android-23. I believe readers will find that it is actually very simple after reading it. The following are the implementation ideas and steps

  • 1 Customize a View

By customizing the view, inheriting the View, setting the drawable by providing a public interface method for the outside world, or providing a custom attribute to set the drawable in the layout file. In the onDraw method, draw the drawable to the canvas.

  • 2 Display drawable for the first time

When the picture is displayed for the first time, it is generally displayed in the center of the screen, and at least the x-axis or y-axis direction occupies the entire screen. How to achieve?

For a drawable, you can get its original width and height:

int drawableWidth = mDrawable.getIntrinsicWidth();
int drawableHeight = mDrawable.getIntrinsicHeight();

Then save the original width and height to a RectF object:

private RectF mTmpRectSrc = new Rect();   
mTmpRectSrc.set(0, 0, drawableWidth, drawableHeight);

After the custom view is measured, it will have a width and height:

int viewWidth = getWidth();
int viewHeight = getHeight();

Save the width and height of the view into a RectF object:

private RectF mTmpRectDst = new RectF();
mTmpRectDst.set(0, 0, viewWidth, viewHeight);

At this time, a transformation matrix from mTmpRectSrc to mTmpRectDst can be calculated:

private Matrix mDrawMatrix = new Matrix();
mDrawMatrix.setRectToRect(mTmpRectSrc, mTmpRectDst, Matrix.ScaleToFit.CENTER);

The Matrix.scaleToFit.CENTER parameter ensures that the image can finally be: centered and displayed on the screen, and at least the x-axis or y-axis direction fills the screen.

Finally, in the onDraw method, combined with the mDrawMatrix mentioned above, the drawable can be drawn on the canvas:

@Override  
protected void onDraw(Canvas canvas) {  
    super.onDraw(canvas);  
    if (mDrawable != null) {  
        int saveCount = canvas.getSaveCount();  
        canvas.save();  
        canvas.concat(mDrawMatrix);  
        mDrawable.draw(canvas);  
        canvas.restoreToCount(saveCount);  
    }  
}
  • 3 How to get the implementation display area of ​​drawable

The above mentioned two RectF areas, and a matrix. They are:

mTmpRectSrc: drawable original rectangular area

mTmpRectDst: view displays a rectangular area

mDrawMatrix: transformation matrix from mTmpRectSrc to mTmpRectDst

How to get the actual display area of ​​the picture after matrix transformation? It should be noted here that mTmpRectDst is not the display area of ​​the picture, this rectangular area is only used to limit the display area of ​​the picture, and the final display area is not him. The method is very simple:

private RectF mTranslateRect = new Rect();
mDrawMatrix.mapRect(mTranslateRect, mTmpRectSrc);

Then through mTranslateRect, you can get the letf/top/right/bottom of the rectangular area of ​​the finally displayed image

  • 4 Recognize pinch and slide gestures

We can identify gestures such as sliding and zooming in the onTouchEvent method by ourselves. But friends, do you feel that these judgment logics are cumbersome to implement by themselves, and it is difficult to ensure that the logic is perfect. In fact, the android system provides two useful auxiliary classes to help us do these things:

GestureDetector
ScaleGestureDetector

GestureDetector can be used to identify sliding (scroll), ScaleGestureDetector can be used to identify scaling (scale)

Let's see how to handle scroll.

First set a GestureDetector:

mGestureDetector = new GestureDetector(context, this);

This refers to the implementation class of GestureDetector.OnGestureListener, which can be implemented by view itself. The implemented onScroll method is as follows:

@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
    mDrawMatrix.mapRect(mTranslateRect, mTmpRectSrc);
    distanceX \= -distanceX;
    distanceY \= -distanceY;
    mDrawMatrix.postTranslate(distanceX, distanceY);
    invalidate();
    return true;
}

Directly set the x and y direction offsets passed to us by the interface into the matrix, and then invalidate, and the drawable drawn from the view will move. In practical applications, we can first obtain the actual display rectangular area of ​​the drawable, and then calculate the final offset according to the offsets in the x and y directions, so as to limit that the picture cannot be drawn out of the view display area.

One more step, you need to pass the MotionEvent event to GestureDetector in the onTouchEvent method of the view, so that you can move the picture with your fingers:

@Override
public boolean onTouchEvent(MotionEvent event) {
    mGestureDetector.onTouchEvent(event);
    return true;
}

If this step is missing, GestureDetector will not be able to help us identify related gestures because it cannot touch MotionEvent.

Dealing with scaling is the same, first define the detector:

private ScaleGestureDetector mScaleGestureDetector = new ScaleGestureDetector(context, this);

This is the implementation class of ScaleGestureDetector.OnScaleGestureListener, which can be implemented by view itself. The method implemented is:

@Override
public boolean onScale(ScaleGestureDetector detector) {
    float factor = detector.getScaleFactor();

    mDrawMatrix.mapRect(mTranslateRect, mTmpRectSrc);

    int width = getWidth();
    float centerX;
    if (factor > 1 && mTranslateRect.right - mTranslateRect.left < width) {
        centerX \= mTranslateRect.left \* width / (mTranslateRect.left + width - mTranslateRect.right);
    } else {
        centerX \= detector.getFocusX();
    }

    int height = getHeight();
    float centerY;
    if (factor > 1 && mTranslateRect.bottom - mTranslateRect.top < height) {
        centerY \= mTranslateRect.top \* height / (mTranslateRect.top + height - mTranslateRect.bottom);
    } else {
        centerY \= detector.getFocusY();
    }
    mDrawMatrix.postScale(factor, factor, centerX, centerY);
    invalidate();
    return true;
}

@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
    return true;
}

@Override
public void onScaleEnd(ScaleGestureDetector detector) {
}

First, the onScaleBegin method must return true, otherwise onScale will not be called back. In onScale, you can get the zoom center point, zoom ratio, and the actual display area of ​​the current picture, and calculate a final zoom ratio and center point according to actual needs. Finally, postScale the result to the matrix, invalidate, and after the view is redrawn, you can see the scaling effect

Finally, you need to inform the scaleDetector of the touch time in the onTouchEvent method of the view. Otherwise, scaleDetector will not be able to access related events at all, and will not call back related methods:

@Override
public boolean onTouchEvent(MotionEvent event) {
    mScaleGestureDetector.onTouchEvent(event);
    mGestureDetector.onTouchEvent(event);
    return true;
}
  • 5 summary

Through the above explanation, we can see that as long as we are familiar with the related usage of matrix and rect, the implementation technology of Photoviewer is actually very simple. The common fling and snap animation effects are also implemented in photoview. If readers are interested, they can check the source code and study it by themselves.

I have summarized some core knowledge points of Android , as well as some latest big factory interview questions, knowledge brain maps and video data analysis.

Friends who need it private message 【Learning】 I will share it with you for free, and I hope we can go on together in the future. (Thank you for your support all the time, if you need it, get it yourself)

Just click the QR code below to get it!

Android learning PDF + architecture video + interview documents + source code notes

List of some information:

  • 330-page PDF Android learning core notes (including 8 sections)

  • Android learning system corresponding video

  • Android advanced system corresponding learning materials

  • Android BAT factory interview questions (with analysis)

Guess you like

Origin blog.csdn.net/m0_56255097/article/details/129622870