I can not figure out how to implement a cyclical scrolling scale. I draw it in customview:

public void onDraw(Canvas canvas){ startingPoint = mainPoint; counter = 0; for (int i = 1;; i++) { if (startingPoint > screenSize) { break; } if(i % 4 == 0) { size = scaleHeight / 4; counter = counter + 1; } else { if(i % 2 == 0) { size = scaleHeight / 8; } else { size = scaleHeight / 16; } } canvas.drawLine(startingPoint, endPoint - size, startingPoint, endPoint, rulerPaint); if (i % 4 == 0) { String c = Integer.toString(counter); canvas.drawText(c, startingPoint, endPoint - (size + 20), textPaint); } startingPoint = startingPoint + pxmm; } 

I limit it to eleven long divisions: enter image description here

But I need an endless scale:

enter image description here

Suppose you can remove the check of the counter value in the onDraw method, but how will this affect the performance? Even if I put its value 1000, the "jerking" is already noticeable when scrolling. Here is my onScroll:

 public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { mainPoint = mainPoint - distanceX; invalidate(); return true; } 

And onMeasure:

 protected void onMeasure(int w, int h) { DisplayMetrics metrics = new DisplayMetrics(); ((Activity)getContext()).getWindowManager().getDefaultDisplay().getMetrics(metrics); h = metrics.heightPixels / 5; w = metrics.widthPixels; setMeasuredDimension(w, h); scaleHeight = h; scaleWidth = w; screenSize = w; endPoint = h; midScreenPoint = w / 2; pxmm = screenSize / 28; } 

How are such tasks implemented?

    2 answers 2

    It is necessary to draw a scale from the beginning of the screen to its end. Those. the cycle should not be on a scale, but on the screen width. And in the cycle, to keep the counter on the scale, as soon as it reaches 11, reset it.

    This approach makes it easy to draw and scale with offset, simply assign the offset to the scale counter at the beginning and ready. Scrolling will not be necessary.

    • Removed from checking out of the loop counter. Now it draws a scale to the width of the screen: screenSize - this is it (determined in onMeasure, the method itself added to the question). All the same, the further I scroll to the right, the more twitching the scrolling. Or is this the norm? - Alexey
    • I did not understand the second part of your answer. Could you please in more detail? - Alexey
    • You do not need scrolling with standard tools, customview should not go beyond the screen, just catch onTouch , determine where the user scrolls and draws the visible part of the scale. The standard scroll will slow down with the current approach, you can hardly do anything with it. - Eugene Krivenja

    In the current implementation, the following happens:

    • mainPoint initialized to zero.
    • in onScroll mainPoint changes to the value of -distanceX , respectively, when scrolling in the positive direction along the X axis, the value of mainPoint will decrease.

    That is, at some point the value of mainPoint will assume -1000 .
    But at the same time, the value returned from getScrollX() will be just 1000 , since View will be scrolled to just this value.

    The onDraw method onDraw that the View coordinates are as follows: (l, t, r, b) == (0, 0, getMeasuredWidth(), getMeasuredHeight()) and the loop in onDraw will draw the ruler from -1000 to getMeasuredWidth() each time - because of this, and there are lags and twitching. So that they do not need to draw a line not from -1000 , but from 0 .

    Actually, this is probably what Evgeny meant.

    How can I fix it:

    In onDraw get the value from getScrollX() (or take the same mainPoint ) and calculate the label of the ruler in the zero coordinate. In my example with 1000 and the value of pxmm suppose 24 turns out that in the zero coordinate of the label of the ruler will be 41,6(6) . Accordingly, the label of the ruler 41 and 41,5 will be out of sight, and the value 42 will just be drawn with a shift of 42 * 24 - 1000 = 8 pixels from the left edge of the screen.

    The only thing is that it is necessary to draw a bit not from scratch, but from a negative value, because the label may be outside the screen, and the figure itself may partially fall on the screen. In principle, in order not to bother too much, you can start drawing from a value of 41 * 24 - 1000 = -16 pixels, that is, shifting the ruler by one division to the left side of the screen.