Android: Why does EditText make scrolling slow? - android

I created a scrollable custom ViewGroup which has several >200 EditTexts in it (not all of them are shown at the same time - I am using a recycler). The problem I am having is that the scrolling is very slow.
Interestingly, I don't have the problem if I do one of the following
1) disable the editText [editText.setEnabled(false)]
or
2) If I change the view from EditText to TextView
Any ideas on what the issue could be?

EditText is huge. Take a look especially at all those methods it inherits.
Why don't you try using just one EditText with 199 custom TextViews or a large grid of rectangles drawn within a Canvas? You could always customize your TextViews (or your drawn grid of rectangles) to make them look like edit boxes, but only use one EditText for the cell that has the focus itself.
That's even how Excel works for some of the functionality it has. It can edit a cell directly (yes), but it also has a static cell on the upper left of the Excel spreadsheet to show you the content of a formula (that may already be rendered as a view within the focused cell itself). You could do something similar yourself. You could extend an EditText to do all the hard stuff, like auto-complete, etc, but you could just draw the text inside the rectangle that has focus (or insert it inside the particular TextView that has focus).
Take a look at this example:
https://github.com/dennis-sheil/android-spreadsheet
He seems to be using mostly TextViews (although TextViews are heavy too, I'm starting to think that the Canvas may be better for something like this, and that everything could be simulated with the drawing method, by everything I mean the blinking cursor, the highlighting of the cell, the character by character typing, etc). With the Canvas at least, you can easily tell it what part needs to be drawn, and what part is off the screen and doesn't need to be drawn, so you're less likely to get into memory problems.

It can be issue with focusing the EditText during the scroll or you create too much objects and it is slow. Use ListView with EditText. Recycle views using viewHolder pattern. It will be smooth but I'm not sure if it is what you are looking for.

Related

Alternative to ListView that avoids EditText focus issues?

Situation
Need to present text files as a list of editable sentences or phrases as shown in the example below, for the purpose of a speech therapy tool. This was relatively easy.
The colored flags can be added, removed, or dragged to new positions as needed, and can be set to snap-to-character or snap-to-word (they will also eventually display data).
This was achieved by sub-classing EditText, to take advantage of all the in-built features like word-wrapping, spell-checking, text-selection etc.
Problem
The number of phrases or sentences in a document can be large, so using a simple LinearLayout in a ScrollView to display them is no good in this case.
To efficiently display my FlaggedEditText widgets the solution needs to take advantage of view recycling, so ListView is an obvious consideration. But as shown by the number of S.O. questions out there, ListView and EditText don't play nice together.
The requirements of the list are that:
FlaggedEditText widgets get focused when touched (the item containing the FlaggedEditText also gets selected).
Notification when an item in the list has been edited (including which item).
Standard gestures such as fling.
I've tried out numerous approaches suggested in the many S.O. questions over the past few days, to try and bend ListView to my requirements, but all seem to have their own short comings and result in hacky, messy code.
Questions
Does anyone know of any existing alternatives to the standard Android ListView out there, that are more EditText friendly?
Alternatively, does anyone have a clean, efficient, definitive approach to getting EditText working as desired in the standard ListView?
Finally, I'm considering sub-classing AdapterView to make my own FlaggedEditText specific ListView alternative. But if the issues stem from AdapterView of which ListView is also an indirect subclass, then I'd be wasting my time. Has anyone already been down this path?
Edit
Jim's excellent response below, and a recent viewing of Romain Guy and Adam Powell's old Google I/O 2010 presentation The world of ListView have suggested a possible solution.
In the I/O talk I was reminded that they convert views to bitmaps for some of their optimizations. Since only one EditText at a time can ever be focused for editing, I'm thinking I can sub-class ListView to provide an interface which, if ChoiceMode is single, will give the Rect of the selected Item and bitmaps of the ListView regions above and below the selected item. This could then be used to temporarily overlay the ListView with a vertical LinearLayout containing the "above" bitmap, an active FlaggedEditText and the "below" bitmap.
In this way, the FlaggedEditText widgets can effectively act as non-focusable EditText's in the ListView, but when an Item is selected, interaction is with the temporary overlay.
The "above" and "below" bitmaps could also easily be tinted to suggest inactivity.
Additional
In fact, I've just realized I probably don't even need the Rect of the selected Item from the interface. The "above" and "below" bitmaps and a FlaggedEditText using the same LayoutParams as per the ListView should be enough.
Many of the answers out there do not seem to describe the core issues surrounding this "problem" and why it is not "solved." The "problem" you face is that an EditText can expand and/or scroll, along with your ListView. Also, the expanding soft keyboard forces the ListView to redraw causing problems with keeping track of the focused item. And when an item is focused and has dynamic content, UX confusion can occur with touch gestures (e.g. if you touch an item in an EditText like the cursor and then swipe, did you want the cursor to move? Or the entire list?) It can lead to a lot of user frustration.
I'm sure you've seen this post:
Issues focusing EditTexts in a ListView (Android)
This creates problems in correctly displaying the elements within the ListView, problems with recycling properly (the redraw) and problems with gaining focus correctly. It is possible that creating a custom class that extends AdapterView will work, but it will probably still feel like a hack, and probably will not work as you want it to or it will be a large effort.
You will need to do a lot of backend measuring of the fonts, images and "visible" (or partially visible) items in the custom object that also account for the keyboard animation and dual scrolling (the ListView can scroll and so can the EditText - or the EditText will change in size, forcing the parent custom AdapterView to determine if it should also scroll and whether views have become visible or invisible as a result of adding or removing text/images from the focused object).
If you make assumptions like "the EditText will never be larger than X height" then you may get it to work, but obviously that is a very customized solution, which is why it is not easily implemented and isn't supported generically.
Also, you will need to make UX decisions about how to handle a focused item that has scrolled off the screen (you can track it easily, but if it scrolls back onto the screen, but it can interrupt user expectations about how swipe and touch gestures are handled - for example, does the cursor in the EditText move or does the entire list? if an image is touched, does a swipe move the image or does it scroll the list? You can assume it is not focused, but then a "redraw" event can make it lose focus unexpectedly, like the current ListView implementation.) In other words, you are likely to end up with many unanticipated odd UX issues...
Your best solution will probably be to use a dialog pop-up as mentioned in the post I referenced above. Or, when an item is tapped to be edited, you could have a layout appear above or below the ListView. You may possibly get the ListView to scroll and lock to it - to have it appear as if it were in the ListView - but again, that would be hard with the soft keyboard changing the usable portion of the screen - you can expect "drag" or a slow feel to the "snap" effect. And you will need a "done" button...
To get your custom EditText to work with this suggestion, in the ListView you could disable it and make it non-focusable, then place an empty layout over the entire EditText that captures and processes the touch/fling/swipe events. This "invisible" layout may be the only option you really have.
In other words, you should probably plan to change your UI/UX rather than try to force Android to figure out how to handle several dynamic, and possibly conflicting or unpredictable, aspects of the UX interaction of these layouts.

Android ListView for showing lyrics

I am trying to make a ListView for showing lyrics. I have very little experience with making custom compound views. So I would like to know what my approach should be to make this view. The ListView must have these features
auto-scrolling based on the song (the timing information will be stored in the list adapter)
highlighting the current line which is being played on the audio
indentation on some lines to make it look more like a nicely formatted poem
users should not be able to scroll the list when the song is playing (i.e. the list is being auto-scrolled) but it should be scrollable when the song is paused
I don't know if the view should extend list view or not. If not then what should it extend and what should be my approach?
Frankly, I really don't have enough information to answer this completely, but this is what I would do:
If it were up to me, since you don't want a scroll capability at all (you want to make it appear as if it is scrolling, not to actually allow the user to scroll), I would not use any of the complex views like ListView or ScrollView, I would just write a custom view, simply extending View. I would override it's onDraw() method and use Canvas.drawText(...) to draw the words, having two different Paints, one for the current word and another for all other words. As for the "scrolling" effect, you can keep a number that represents the current top line that you can see, and add one to this number when you want to scroll to the next line. However to make it smooth you can manipulate where exactly you start drawing the texts and move it slowly upwards, so that it would appear that everything is scrolling down.
** Maybe it would be better to use SurfaceView here instead of just View, especially if you want a background image and smooth blending and better a look, since SurfaceView is much better for complex drawings **
If that is too complicated for you and you want to use existing views entirely without doing any of the drawing yourself, I would recommend a vertical ScrollView, you fill the ScrollView with horizontal LinearLayouts for each line, and each of those is filled with TextViews for every specific word. You can programatically build the TextViews and the LinearLayouts. Use ScrollView's scrollTo(...) or SmoothScrollTo(...) to scroll to the right location. You can prevent the user from scrolling by capturing all the motion events before they are used to scroll.
Both approaches will of course require you to maintain some form of data structure to hold the times each word is selected.

Android - Create Text Box object, like the one that microsoft word provides

This one bothers me for quite a while. I have an app where the user paints some objects with fingers. One is supposed to be a Text Box, a rectangular where the user can input text, like the one word provides (http://www.techrepublic.com/i/tr/cms/contentPics/r00319991202jod05_01.gif)
I do not need the text to be painted dynamically, I launch another activity where the user adds text and I catch the text on activity result. But I need the user to be able to reshape the object and it should handle all the cases like:
i. Box too narrow for the text -> get the last words to another line
ii. Box too narrow for some single words -> split the words
I want to handle this exactly like word text box handles it. I thought it could me by dynamically making a textView, but it seems impossible. I posted a question here Android - create TextView (or EditText) programmatically and set it in a specific place on the screen giving coordinates (mostly about textView) but I had no luck, drawTextOnPath can work for i but it is very hard to implement ii and show text in a smooth way.
I know we are not supposed to ask the same thing twice, but I do it to explain in a new way what I need, which leads to a different question. Thanks to everybody in advance.
Moving the Text around can be done easily by dragging the view in onTouchEvent.
Scaling the text can be done using two finger gesture. Just like the zoom feature in Webview. You should increase the textsize of the TextView on zoom-in and decrease on zoom-out.
Update:
Resize the TextView itself when two finger gesture is on. That will automatically re-flow the text appropriately. TextView can be resized by calling setHeight and setWidth.
Declare a LinearLayout with TextView as the only child.
Inflate this layout when needed and set the margins for the textview to position it appropriately.
When resizing just change the height and width of the textview.

Scrolling text display in Android

Android newbie here. I know I can use TextView for scrolling text display but my question is a little different.
I want to show step by step details of moves in a game in a box on a View. It should be something similar to the scrolling text you see on most poker games. The requirements are you should be able to scroll through it to see the entire game moves. I am drawing the entire View using draw() and so was wondering how to get TextView on there. Can I add it to the View and position it myself in code? From what I see it seems like I should add TextView through the XML for the Activity. Is there another way around it or may be is there another widget I can use to solve my problem?
Thanks,
P
You could try using a FrameLayout and overlay a TextView over your custom drawn view. It may be difficult to position the TextView precisely. Alternately you could extend ViewGroup and manage the view layout however you want.

Handling an embedded view inside a ListView?

I have a quite problematic UI layout to implement, and I'm not sure if it's even possible using standard UI widgets. It looks something like this:
Picture 1
The green, lined thing is supposed to be a ListView, and the red rectangle is another View. This red View should be scrolled with the ListView, as if it's part of it. Some list-elements should also be narrower, because that embedded View gets in their way. Could you please recommend any ideas? Can this be done somehow with the Android UI framework? I was thinking about some kind of a floating View above the ListView, which reacts to the List's scrolling events too, but it doesn't seem like an elegant solution.
Thanks
I don't think you can accomplish that easily with a ListView. You could do the overlay using a FrameLayout, but it would be very awkward to get it to stay probably aligned as the user scrolls.
How many elements are you talking about?
I would probably use a LinearLayout within a ScrollPane to simulate the ListView.
Or, a TableLayout where the overlayed view is contained within a single, complex row.
I would set the green rows that the red block overlap and the red block as one big view in the listview. So the items in your listview would be (for the example pic) two green rows, then the view of three green rows and the overlapping red block, and then the remainder of the green rows.
Trying to have the red block on an overlay that scrolls with the listview sounds like more trouble than it's worth.

Categories

Resources