I am engaged in writing a corporate program, one of its functions is the imposition of an arbitrary text on a new photo. To do this, use ImageView to display the image itself and TextView to determine the location of the text, as well as its size, color, etc.
Screenshot of the example: wrong text positioning

Faced 2 problems:

1) The position of the text along the Y axis is incorrectly determined. I visited various methods, stopped at such a function (I submit the coordinates of TextView in x and y, using the function getX () and getY (), respectively):

private float[] getXY(ImageView iv, Bitmap bm, float x, float y){ float projectedX = (float) ((double)x * ((double)bm.getWidth()/(double)iv.getWidth())); float projectedY = (float) ((double)y * ((double)bm.getHeight()/(double)iv.getHeight())); return new float[]{projectedX, projectedY}; } 

Tried through the matrix, the result is even worse. Can anyone come across? How to align the Y axis so that it corresponds to the coordinates.

2) As you can see in the image, the text size in TextView is larger than that drawn with Canvas, I understand that the resolution of the image itself plays a role there, but is there a way to maintain the correct proportion of the text? So that the size of the text on the preview corresponds to the drawn size.

    2 answers 2

    The fact is that the getX () and getY () functions return the position on the screen! This means that you get a position on Y, taking into account the toolbar and bar status. From the docks:

    It is possible to retrieve getLeft () and getTop (). The rectangle representing the view. The rectangle represents the view. Relative to its parent. For instance, when it comes to its direct parent. In addition, several convenience methods are offered to avoid unnecessary computations, namely getRight () and getBottom (). Return to the bottom of the rectangle. For instance, calling getRight () is like the following computation: getLeft () + getWidth ()

    transfer:

    You can get the View location by calling the getLeft () and getTop () methods. The first one returns the left edge, or X, of the coordinate of the rectangle representing the View. The latter returns the top edge, or Y, of the coordinates of the rectangle representing the View. These methods return the position of the View relative to its View ancestor (container). For example, when getLeft () returns 20, it means that View is 20 pixels to the right of the left edge of its View ancestor. In addition, several convenient methods are proposed to avoid unnecessary calculations, namely getRight () and getBottom (). These methods return the coordinates of the right and bottom edges of the rectangle representing the View. For example, the getRight () call is similar to the following expression: getLeft () + GetWidth ()

    You'd better put ImageView and TextView in one container (for example, RelativeLayout) and use these methods to get the coordinate in the current image. You should consider the scaleType that you specified for the ImageView, since This affects the display of the original image and this is a starting point in your calculations. To draw text on an image, rather simple geometric calculations are used, which simply need to be properly organized. And with the size of the text you correctly noticed, you need to take into account the resolution of the image and the current size, and then convert the size of the text according to the formula (which can be inferred, but you need to do this).

    PS

    You have no problems along the X axis because you have a twist most likely on the right edge, which is why getX () == getLeft ().

    • Hello! Thanks for the answer. All this is in the container. This is the hierarchy <LinearLayout> <FrameLayout id = root> <ImageView> <TextView> </ FrameLayout> </ LinearLayout>. Those. everything is already in the container - evansir
    • @evansir, well, now use the methods getLeft () (instead of getX ()) and getTop () (instead of getY ()). Then, for positioning the image on the canvas, calculate realX = realWidth / currentWidth * getLeft () for realY in the same way, but with height, where realX is the X position on the real image, realWidth is the real image width, currentWidth is the current image width in View, getLeft () - X position at TextView - Vitalii Obideiko
    • Please update your answer with the addition of an example for calculating Y coordinates and text size. - evansir pm
    • getTop gives a completely wrong result - evansir
    • @evansir, there are two options, either you don’t understand how it works and what comes back, or you made a mistake in the calculations. I hope that you understand that what getTop () returns to you is not a position on the canvas for text by Y, but only an indent in pixels from the top edge of the container, and then you have to calculate the position of the text on the canvas yourself from this data and depending on what the coordinate system is. - Vitalii Obideiko

    Using foreign resources - figured out. The point is that the Canvas uses the given Y position and writes the text above it. Any TextView has internal padding, which raises the position even higher, although visually it is not noticeable. Those. To get at least an approximate position of the text to our TexView, you need to use the following function:

     public float[] getPosition(ImageView imageView, TextView textView) { Matrix matrix = new Matrix(); imageView.getImageMatrix().invert(matrix); Rect bounds = new Rect(); textView.getPaint().getTextBounds(textView.getText().toString(), 0, textView.getText().length(), bounds); float[] coord = {textView.getX(), textView.getY()+bounds.height()}; matrix.mapPoints(coord); return coord; } 

    So far, I have not achieved the best, but the difference is not critical, because it is quite suitable for most cases.

    To draw text proportional to what we see in TextView, you need to multiply the size in pixels by the scalefactor, which is - (float)bitmap.getWidth() / (float) imageview.getWidth() .

    And to draw text, use StaticLayout.