Android Question Tall canvas in ScrollView

DIYRicey

Member
Licensed User
Longtime User
I am trying to develop an app (for bell-ringers) that requires a vertical scrollable display of rows of characters, lines. etc. The rows are only 12 characters wide, but there may be thousands of rows. The approach I would like to take is to draw all the rows onto the panel/canvas of a ScrollView in one go, having made the panel height sufficient to accommodate the whole thing. This works for a limited number of rows but, depending on which device I use as a test bed, soon reach a limit, with a java error message such as java.lang.RuntimeException: Canvas: trying to draw too large(111804480bytes) bitmap. (This is on a device with a screen width of 720 pixels, trying to draw 1300 rows, each just under 30 pixels high.)
I have tried drawing a subset of the rows onto a smaller canvas/panel, and redrawing as the scroll reaches its limits. I've managed to get it to work but the action is rather clunky, especially when scrolling toward the top.
I have seen the HugeImageView post at https://www.b4x.com/android/forum/threads/b4x-hugeimageview-show-very-large-images.132905/ This looks like a solution, but, as a hobbyist coder, I don't understand it!
I need help with understanding the principle behind HugeImageView. I only need vertical scrolling. I don't need pinch/zoom. I only need Android.
It would also be helpful to know how to interrogate the device to see how big a canvas it can accommodate so that I could adapt the size.
 

Brian Dean

Well-Known Member
Licensed User
Longtime User
You have got on to the wrong track in trying to deal with images. You should be using some form of scroll view - you are right there - with each row that you are drawing being one line entry in the scroll view. You will easily be able to deal with thousands of rows before reaching any limit, well over 5040 for example.

If nobody else comes forward I would be happy to draft our something to get you started, but unfortunately I cannot make a start on it just now. I am a bell-ringer myself, as you might have gathered. If you give me an outline of what you want I would be happy to help out.
 
Upvote 0

DIYRicey

Member
Licensed User
Longtime User
Thank you, Brian, for your thoughts.

The reason I have used images is so that I can position the data (horizontally) in a flexible way. I also want to draw lines on the data and other shapes.

The USP of the app is that it allows a user to 'ring' a bell in real time, by tapping a panel. They have to try and keep time with the other bells, and if they ring early or late the position of their bell is displaced by the amount of the error. The idea is that the user can use the app not only to learn a method, but to develop listening skills in order to ring in time with the other bells.

The images below show the kind of thing I want to display. The first image is just a diagram of the Plain Bob Doubles method. In the second image the user has rung bell 5 early on the second row shown. It has been printed to the left of where it should have been, and a red shaded rectangle highlights the error. A bit later the bell is rung late and a green rectangle shows the error. The RMS value of the errors accrued is given when the ringing finishes, as feedback on how well they have done.
1000013343.png
1000013344.png



I had almost finished, accepting the limitation to the number of rows - in the region of 1200 - but then tested the app on an ancient tablet, running SDK21 (Android 5.0.1), and the scrollview refused even to show.
 
Upvote 0

Brian Dean

Well-Known Member
Licensed User
Longtime User
Here is a very quick demo - you should just look at it as a "proof-of-concept". It consists of a single scroll view that displays 5040 rows of Plain Hunt on twelve.

If this is a step in the right direction for you but you need more then come back to me. If it is not helpful then let me know and I will try something else.
 

Attachments

  • Rows.zip
    11.3 KB · Views: 6
Upvote 0

DIYRicey

Member
Licensed User
Longtime User
Thanks so much! Yes, 5040 rows of Plain Hunt 12. Neat. I shall see if I can get my head around CustomListView and PreoptimizedCLV.
However, I don't think it would be possible to draw a line to show the path of one of the bells, would it? It's crucial to be able to do that.
 
Upvote 0

Brian Dean

Well-Known Member
Licensed User
Longtime User
Well - this is embarrassing! I did not see your post #3, made yesterday afternoon, until this morning, even though I was checking throughout yesterday evening on more than one device and could see that you were active on the forum. I have seen this effect before, and I think that it is because you are not a licenced user and your posts are moderated and therefore delayed. (I also think that making a small donation to AnywhereSoftware, proving that you are a real person, will remove this limitation).

Anyway, you must have thought that my reply was rubbish, but that might not be entirely the case. The solution to your problem is "tiling". That is the technique used in mapping to show a limitless two-dimensional surface. You are working in only one dimension, so let's think again of my CLV example. My demo displayed a possibly infinite series of layouts. Each layout contained twelve labels, but it could just have easily displayed an image. If each image displayed a single lead of a method then the CLV would scroll through a complete course, and even wrap back to the start. So that would have been a possible solution to the problem that you set in post #1.

However your first post did not include the requirement that the User can interact with the display. The way to do this is usually to add a transparent panel overlaying the scrollview to intercept touch actions. This is how mapping apps work, and they, of course, are working in two dimensions. You seem to have already developed that part of your app, and you obviously know what you are doing even if you call yourself a "hobbyist". But I would suggest that a possible path for you is to look closer at mapping and draughting apps and how they draw polygons on a scrolling surface. Of course, you have already invested a great deal of time in your app and it might be difficult to implement what might be a major change in its architecture.

Edit : Another passing thought . . .
. . . tested the app on an ancient tablet, running SDK21 (Android 5.0.1) . . .
According to Google 90% of Android devices are running Android 11 or above and more than two thirds are running Android 13 or 14. I don't think that you have to worry about your app running on Android 5. But that might not be your real problem, of course.
 
Last edited:
Upvote 0

Brian Dean

Well-Known Member
Licensed User
Longtime User
I have had a chance now to think more about your problem and to understand better what you want to achieve, and how you want to do it. If you are testing your app on different devices then I guess that you must be coming to the end of its development and what I am going to suggest here may be too radical a change. However other people might look at these posts in the future and benefit from different ideas so I am going to suggest what I think would be a solution.

Here is an app that I wrote a few of years ago . . .

Pixel 8a 3.jpg



It is a record of daily steps. The view at the bottom left is a regular scrollview - not a CLV. I have been collecting data for nearly three years so the scrollview has over 1000 rows. As I scroll through the dates the graph at the top scrolls left and right smoothly and in perfect unison - except that it does not scroll. I monitor the ScrollChanged event from the scroll view and on every movement redraw the graph completely. Note : I do not mean that the graph updates on every row change - it updates on every touch movement on the scrollview - very smooth. If I knew how to post a video I would.

Imagine that we transfer this design concept to your app, with the canvas containing the graph rotated and moved to overlay the scrollview. The scrollview would be scrolled automatically in time with a soundtrack - you must be doing something like that already - now that action also needs to redraw the canvas. There would be very little drawing to do - just a few rectangles - and we are anyway not scrolling quickly. Time would not be a problem. You are already collecting the striking data from each row to compute the RMS value so this would allow the user to scan backwards through their performance as well.

As I said, I know that this might be a significant design change but I am sure that it would work. You do not need a large canvas, you just need to redraw the canvas content to match the scroll position of the change list. I am still not clear how the scrolling graphic of the method is created in your current app but I don't think that you are using a scrollview, and you do say that it is "clunky". I think you should seriously consider using a scrollable view and using a "tiled" set of images.
 
Upvote 0
Top