📜 ⬆️ ⬇️

Android component from scratch - 2 - Magnifier for image

From time to time on the Internet, mainly on the sites of various stores and marketplaces, we are confronted with a software magnifying glass that allows us to examine in more detail photos of various goods (something similar is implemented on the site www.ebay.com ). Creating a magnifying glass for the Android platform, we will do (especially for beginners).

Task: Develop a component-magnifier for a more detailed consideration of photos. Initially, the screen shows a picture whose dimensions are proportional to the screen of the device (the picture is shown on the screen in full). When you touch your finger on the screen, the picture should increase and show this area relative to the touch; P.

Training


Create a new project and the “PZoom” class, use the View class as an ancestor.
We are interested in the following functions:
PZoom - class constructor;
onDraw - the drawing function, is called every time it is necessary to redraw the component;
onTouchEvent - the function of tracking external events, is called each time the user presses the screen with the finger and hits the component, as well as when he leads his finger over the component and also presses the finger.
Simplify your task, we will use only one image previously placed in the Drawable folder with the name “img” (the more the picture is, the more visual effect you will get). At the beginning of the class we will declare a new object of type Drawable.
private Drawable image; //   

Next, in the constructor, put the desired image in the image and set the frame:
 image = context.getResources().getDrawable(R.drawable.img); image.setBounds(0, 0, image.getIntrinsicWidth(), image.getIntrinsicHeight()); 

Now re-create the drawing procedure:
  @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.save(); //    (,   .....) image.draw(canvas); //      canvas.restore(); //  ,      } 

Go to the main class of the application and modify the class constructor as follows:
  @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(new PZoom(this)); } 

These actions create the Pzoom class and define it as the main one, that is, now only this component will be displayed on the screen.
Now, if you run the application, you will see on the screen only a part of the downloaded picture, since it does not fit completely on the screen (the picture is larger than the screen).
')

Functional


To begin with, we will do so that by default the picture is placed in the middle of the screen and its dimensions are proportional to the screen. To do this, we write a separate function SetCenter, which determines the position of the picture on the surface, as well as the correct multiplier for the proportion.
We declare additional variables at the beginning of the class:
  int X = 0,Y = 0; //     float scale = 0; //    int pX = 0, pY = 0; //     int dWidth = 0, dHeight = 0; //   

Now the body of the function itself (there is no sense to chew on it, this is elementary mathematics):
  void SetCenter(){ //     if(dWidth>dHeight) // scale = (float)dHeight/image.getIntrinsicHeight(); else scale = (float)dWidth/image.getIntrinsicWidth(); //    if((dWidth-image.getIntrinsicWidth()*scale)>0){ X = (int)((dWidth-(image.getIntrinsicWidth()*scale))/2/scale); Y = 0; } else { X = 0; Y = (int)((dHeight-(image.getIntrinsicHeight()*scale))/2/scale); } } 

Now we add the widget's drawing function:
 @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.save(); //    (,   .....) if (dWidth==0){ //        dWidth = canvas.getWidth(); dHeight = canvas.getHeight(); } if (pX==0) { //    SetCenter(); //      } canvas.scale(scale, scale); // ZooM canvas.translate(X,Y); //   image.draw(canvas); //      canvas.restore(); //  ,      } 

At the beginning, there is a data availability check in the variable size of the widget; if they are equal to zero, then we know the dimensions of the widget. Next, there is a data availability check in the variable position of the cursor, if it is even zero (the user's finger is not on the widget) then we start the function of centering the picture. After that, the image is resized in accordance with the stretch value. Then the map is shifted. At the end, the picture is drawn and the matrices are reset.
Moving on to the most important thing - changing the size and position of the image relative to the pressed finger. First of all, you should override the finger positioning procedure on the onTouchEvent screen:
  @Override public boolean onTouchEvent(MotionEvent event) { //   pX=(int) event.getX(); //   X pY=(int) event.getY(); //   Y int Action=event.getAction(); //  //   if (Action==MotionEvent.ACTION_UP){ pX = 0; pY = 0; } invalidate(); //   return true; } 

I will not describe, who are interested then refer to the first article. It remains to create a procedure for calculating the new position of the image on the screen, it will look like this:
  void NewPosition(){ scale = 1; //    //          X = (int)((float)-image.getIntrinsicWidth()*((float)pX/dWidth)+((float)dWidth*((float)pX/dWidth))); Y = (int)((float)-image.getIntrinsicHeight()*((float)pY/dHeight)+((float)dHeight*((float)pY/dHeight))); //         if (X>0) X=0; if (Y>0) Y=0; } 

Slightly changing the rendering function of the video view, namely, if the variable position of the cursor is not empty, then we calculate the new position:
 if (pX==0) { //    SetCenter(); //      } else { NewPosition(); //      } 

If everything is done correctly, then when you click on the picture, it will increase and move around the screen relative to the user's finger. Have a good test!

The final view of the magnifying class picture:
 package com.gc986.photozoom; import android.content.Context; import android.graphics.Canvas; import android.graphics.drawable.Drawable; import android.view.MotionEvent; import android.view.View; public class PZoom extends View { private Drawable image; //   int X = 0,Y = 0; //     float scale = 0; //    int pX = 0, pY = 0; //     int dWidth = 0, dHeight = 0; //   public PZoom(Context context) { super(context); //     image = context.getResources().getDrawable(R.drawable.img); image.setBounds(0, 0, image.getIntrinsicWidth(), image.getIntrinsicHeight()); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.save(); //    (,   .....) if (dWidth==0){ //        dWidth = canvas.getWidth(); dHeight = canvas.getHeight(); } if (pX==0) { //    SetCenter(); //      } else { NewPosition(); //      } canvas.scale(scale, scale); // ZooM canvas.translate(X,Y); //   image.draw(canvas); //      canvas.restore(); //  ,      } /** */ void SetCenter(){ //     if(dWidth>dHeight) // scale = (float)dHeight/image.getIntrinsicHeight(); else scale = (float)dWidth/image.getIntrinsicWidth(); //    if((dWidth-image.getIntrinsicWidth()*scale)>0){ X = (int)((dWidth-(image.getIntrinsicWidth()*scale))/2/scale); Y = 0; } else { X = 0; Y = (int)((dHeight-(image.getIntrinsicHeight()*scale))/2/scale); } } /**   */ void NewPosition(){ scale = 1; //    //          X = (int)((float)-image.getIntrinsicWidth()*((float)pX/dWidth)+((float)dWidth*((float)pX/dWidth))); Y = (int)((float)-image.getIntrinsicHeight()*((float)pY/dHeight)+((float)dHeight*((float)pY/dHeight))); //         if (X>0) X=0; if (Y>0) Y=0; } @Override public boolean onTouchEvent(MotionEvent event) { //   pX=(int) event.getX(); //   X pY=(int) event.getY(); //   Y int Action=event.getAction(); //  //   if (Action==MotionEvent.ACTION_UP){ pX = 0; pY = 0; } invalidate(); //   return true; } } 

So it should happen ideally - http://youtu.be/GHB91_RzORY
The archive of the example with all the comments can be downloaded from the following link - http://www.anprog.com/documents/Photo_Zoom.zip

Source: https://habr.com/ru/post/191898/


All Articles