📜 ⬆️ ⬇️

Test Pass Library



Not always just to use. It was with such a thought that the writing of the library for Android and the subsequent writing of this article began. Suddenly someone come in handy. Under the cut that eventually turned out.

Introduction


One long winter evening, my friends and I had an argument about how to implement one of the necessary functionals. It was necessary to write * something * that could:


As the most active, I was impatient to try my hand, and on the very first night a view was written, which based on the formula tree drew a formula. Friends looked at this case and put forward more demands.
')

The good fellow got upset, scratched his little head and sat down to write the library. And to make it even more interesting, I set myself an additional condition:


PS


There will not be a phased schedule of how to write a library and how to publish it - on the Internet, including Habré, there are already instructions on this. I will talk a little about my logic, about the problems and difficulties that I encountered and how I solved them. To some, this will seem trivial, to someone wrong - I do not pretend to make the right decision and I’ll take all the comments. I hope that this article or library will be useful to someone. The github link will be at the end. In the description of the repository there is a link to the demo library and instructions for it.

Stage One - Tree Drawing


By this stage, I had my initial demo, requirements and firm confidence that everything will work out. First of all, it was decided to take up drawing, and leave the conversion from string to tree for last.

And so, the logic of the tree is:

A sheet is a set of characters. For example, a multiplication sign or some number. The sheet knows about its size, about whether there is someone after it, and how to arrange them in relation to itself. I have identified several types.

  1. Constable sheet. These are +, -, * and numbers. This sheet has a single height and length, depending on the internal text. Everything behind it is drawn on the same axis with it. That is, the center of this sheet along the Y axis coincides with the center along the Y axis of everything that is behind it.

  2. Changeable sheet. It is the same as constable, only it has a state of empty and full. Height is a single unit. The width is taken not by its insides, but by the longest text of all the sheets being changed and moved.

  3. Movable sheet. Looks like a changeable, only to it the state is visible, invisible, moves.

  4. Power sheet. It has the width of the size of what should be in degree. And its peculiarity is that everything behind it draws not on the same axis with the previous sheet. The bottom edge of the whole subsequent area should be shifted to the floor of the block relative to the previous sheet. It sounds muddled, but you just have to put the number in the degree. (22) The degree is drawn on the floor row above. But unlike this degree, in my number to the degree does not decrease in font. This sheet knows who is next in the drawing degree, and who is next, after the drawing degree. That is, in the formula (2 ^ (1 + 3) -4), the sign of the degree knows about "1" and about "-".

  5. Division sheet. As the name implies, this is a sheet denoting division. It is drawn in 4 stages. A line is drawn along the center, as long as the larger of the numerator and denominator lengths. The numerator is drawn so that it is pressed to the line with the lower edge and is located in the center of the entire length of the line (in case the denominator is longer). The denominator is drawn so that it is pressed with the top edge to the line and is located centrally from the entire length of the line (in case the numerator is longer). And at the end of the drawing is transferred to those sheets that go after the division.



For logic to work, each sheet must be able to:

  1. Tell your length and height
  2. Say the length and height of yourself and what is behind it. Not just the next leaf, but the entire leaf branch. That is, in the formula 2 + 3-4, the sign “+” knows the dimensions of the part “+ 3-4”. This helps determine the size of the entire formula.
  3. To say how much he needs to move from the center along the Y axis (the rule is introduced specifically for the Power sheet)
  4. To be able to draw yourself and correctly transfer the coordinates for drawing to all your descendants.

Stage Two - Scaling Blocks and Text


In order to fill the resolved area as much as possible, there is a scaling stage before drawing. The principle is simple. I have a single unit, on the basis of which all calculations are carried out and the variable responsible for how many times it is necessary to increase the scale. The scaling logic is as follows: we get the size of the formula, compare it with the size of the available area, change the scaling factor.

And then I ran into a small problem. The width of the text increases in proportion to the textSize attribute. That is, suppose we had a block of text with a width of y and textSize x. If we increase the textSize by 2 times - the width of the block will not be equal to 2 * y. In this regard, the scaling value constantly fluctuated in close values, which is why the picture was “shaken” when redrawing. To solve this problem, I have seen 2 ways:

  1. It was possible before each step to reset the value of scaling to the initial value. But the option did not suit me, t to then the size error in width would be too large.

  2. To set the formula before each step of scaling in the same conditions. For this, I added 0.5 to the coefficient and rounded it up.

Going through the second method, I ran into a problem in the very first calculation, when the coefficient is still 1. To solve this, at first, I did the calculation using the second method 2 times, but this affected performance. To avoid the second extra calculation, it was decided to keep the previous value and compare it with the new one. If they are the same, then it makes no sense a second time. Thinking again, I rendered the recalculation to the onSizeChanged method, and also additionally called when setting a new formula / sheets for movement.

Stage Three - Movement


Everything is very simple here. A little trick was adopted. Instead of moving the sheet that we selected, we hide it and start a new one, the coordinates of which are constantly changing when an onTouchEvent is triggered. When MotionEvent.ACTION_DOWN is triggered, we are looking for whether our contact has hit the moving sheet, hide it, and copy the value into the sheet that we are moving. When MotionEvent.ACTION_UP is triggered, we run through the tree and see if we intersect with any Changeable sheet.

Stage Four - Parser


Here in some measure the decision in the forehead. To begin, it was determined 2 specials. character. The first one points to those blocks that will become Changeable. The second symbol, a pair, indicates the area that should be defined as Constable or Changeable without internal transformations (for example, the division symbol). We get a string, delete all spaces that are not included in the area allocated to the second spec. symbol, transform the division signs and begin to read character by character. To make it easier to convert everything, the division signs from the form 2/3 are converted to / (2) (3).

Stage Five - Customization


For ease of customization, almost all the variables that appear in the drawing or parser code are in separate fields of the classes. In this connection, you can successfully change almost everything that you see.

Conclusion


As it turned out, this library is quite suitable for “formulas” not only mathematical, but also, for example, for checking knowledge of vocabulary words. I would also like to add for the future, for those who decide to write their own libraries too - in android studio there is a creation of a module library, and remove everything from the application tag in the library manifest. If you have any questions, I will be happy to answer. All comments and suggestions I will consider.

→ Library on github

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


All Articles