I have an activity with a scrollable view. I also have containers that all have the same structure - consist of imageButton and also several textViews that serve as a description. The whole thing looks like that:
The problem is that there are around 30 elements with the same structure and when each one of them has so many textViews I get the warning -
Layout has more than 80 views, bad for performance.
The reason why I have so many views is because of the different formatting of the different words. How would it be possible to reduce the views and still get the same formatting?
P.S. I already read that how to resolve "Layout has more than 80 views, bad for performance"? . But this doesn't help me, since all the information that I have, should be static and always visible.
You will want to set up your layout using a RecyclerView.
If your app needs to display a scrolling list of elements based on large data sets (or data that frequently changes), you should use RecyclerView.
Android Developer Guide has some pretty good documentation on how to set this up. Also, here is a video tutorial on RecyclerView by SlideNerd. He has a pretty good series for android developers.
In addition to what J. Jefferson said about RecyclerView. As you mentioned in your initial post:
The reason why I have so many views is because of the different
formatting of the different words. How would it be possible to reduce
the views and still get the same formatting?
You can do different text formatting without creating a separate textview. Have a look at the following https://stackoverflow.com/a/41953808/8312634
Related
For the development of my app, I realized I needed a complicated view (let's call it foo), it contains three ImageButtons, a progress bar, and three TextViews, all of which are dynamically changed by interacting with the same view's elements. To make this work, I extended foo from RelativeLayout, dynamically created the sub-views then added them to foo (this.addView(...)).
What I planned to do next was add them dynamically to a ScrollView. I did this and put three foos for testing. The result was extreme lag. I'd press an ImageView (which should change its image on press), and it would take 2 seconds to do so.
My final aim would be to support 50 of these foos at a time and have them work smoothly, with the user having the option of loading more (without overwriting the previous ones) if he/she so chooses. All interactions will use the internet (I dunno if that's relevant), but the testing was done with all the network tasks commented out.
My questions are thus:
Is the strategy I was using (ScrollView & add foos to them) viable, and the lag is from some other issue (the specific code in question, in which case I'll provide some code)? Or is it really a bad idea to do that?
What would be the best way to reach my goal here (assuming 1 is bad)?
What I already know:
I've researched my problem a bit, and most online sources recommend using a ListView. I didn't read much into it but from what I got:
I'd have to redo the design using xml rather than dynamically
The different components and their values will be stored each on it's own array which is extremely unacceptable in my situation (changing the sub-view's values should be done very simply and should not appear in the main activity)
I can't (or it's difficult to) set OnClickListener's for the different sub-views (as only the main foo view will get one)
I also tried this method (ScrollView and add to Views) with another View and had 20 of them run at the same time seamlessly, but that one had been extended from View and only used canvas to draw text with no sub-views.
Thanks in advance.
This is not a code problem, I interpret the guidelines as that being OK.
I've been researching a way of building an infinitely scrolling calendar-like view in Android, but I've reached an impasse.
Right now my dilemma is that most of the similar views available have their children placed relative each other in a recurring style. With this I mean:
item 4 comes after item 3, which comes after item 2, and there is constant padding/margin between all items.
What I need is a way to produce an infinitely long scrollable view that may, or may not, contain items. The items should be placed at variable positions within the view. The best way I can describe a similar looking view is a one-day calendar-like view that is infinitely scrollable.
So far my best two bets are using the new RecyclerView with a custom LayoutManager (this seems very complex and still not perfectly documented by Google though). I like this approach because, among other things, it is optimized for displaying large sets in a limited view.
My other solution would be to build a completely custom View. However, with that solution I loose the adapter unless I build a container view (which is probably more complex than building a layout manager).
How would you go about solving such a problem? Tips are appreciated, I don't need code examples, just ideas which path is the best to solve this problem.
Thanks.
Apologies if I've misunderstood the guidelines
Edit: How I resolved this problem
My first solution to use RecyclerView with a special Decorator seemed promising, but it remained a "hack" so we decided not to go for that solution since we were afraid of the complications that it would create down the line.
To solve the problem I went with a SurfaceView instead of an Adapter, this means having to rewrite all the adapter-functionality for my SurfaceView but it seemed to be the best way of solving this issue of very custom drawing and layout managing for my use-case.
It still would be nice to build a custom Viewgroup that can handle this kind of layout problems.
ListView and ListAdapter are based on a fixed list, so the current infinite-scrollers just keep adding more and more data to the end of the list.
But what you want is scroller similar to Google's Calendar app which has a bi-directional infinite scroller. The problem with using ListView and ListAdapter in this case is that if you add data to the front of the list, the index of any one item changes so that the list jumps.
If you really start thinking about this from the MVC perspective, you realize that ListAdapter does not provide a model that fits this need.
Instead of having absolute indexing (i.e. 1, 2, 3, 4, etc), what you really want is relative indexing, so instead of saying "Give me the item at index 42" you want to say "here's an item, give me the five items before it". Or you have something like a calendar date which is absolute; yet — unlike your device's memory — it has effectively no beginning or end, so what you really want here is a "window" into a section of that data.
A better data model for this would be a kind of double-ended queue that is partly a LRU cache. You place a limit on the number of items in the structure. Then as prior items are loaded (user is scrolling up) the items at back end are pushed off, and when subsequent items are added (user is scrolling down), items at the front are pushed off.
Also, you would have a threshold where if you got within a few items of of one edge of the structure, a "loadNext" or "loadPrevious" event would fire and invoke a callback that you set up to push more data onto the edge of the structure.
So once you've figured out that your model is completely different, you realize that even RecyclerView isn't going to help you here because it's tied to the absolute indexing model. You need some sort of custom ViewGroup subclass that recycles item views like a ListView, but can adapt to the double-ended queue. And when you search code repos for something like this, there's nothing out there.
Sounds like fun. I'll post a link when I get a project started. (Sadly, it won't be done in any timely manner to help you right now, sorry.)
Something that might help you a little sooner: look at Google's Calendar implementation and see how they did it: Google Calendar Git repo
What you may be searching for is a FragmentStatePagerAdapter , where you can implement a swiped view, meaning when the user (for example)swipes to the right, a completely new view is displayed.
Using a FragmentStatePagerAdapter , you can handle a huge amount of views without overflowing the memory, because this specific PagerAdapter only keeps the views' states and is explicitly meant to handle large sets of views.
Keeping your example of a calendar, you can implement swiped navigation between for example weeks and generate the week views on demand while only keeping for example the year and the week's number as identifiers.
There are plenty of online tutorials for Android, maybe you have a look at this one
When you are working with a long, big list, certainly one should use ListView because it handles cell recycling.
Notice here, for example Can i use nested linearlayouts instead of list view, for a big list? the OP is asking about ListView verses a dynamic LinearList -- the answer is "have to use a ListView, because of recycling"
Now, say you are making a short list -- imagine say a popup with only 10 or 20 items. It may even fit all on the one screen, so there's no recycling.
In fact, is there any difference between using a ListView and just using a LinearLayout, and dynamically populating the little views inside it?
It seems to me that the latter is in many cases much simpler, more elegant, and easier to work with. But I could well be missing something that seasoned Android engineers know about.
Should I just use an ordinary LinearList (populate it dynamically) for lists where recycling is not relevant? What's the usual, and why? Cheers!
{Incidentally, for popup cases, is there some better, lightweight method for "choose one from a popup-list" that I'm too silly to know about?! :) )
ListView(and other lists) supports very useful idea: splitting data and view. These parts could be changed at any time so it's important to support flexibility. And it could be solved by special mediator object: Adapter. Adapter roughly speaking says how to fill your view with particular data item.
So I'm sure that if you decide to use LinearLayout sooner or later you will implement you own Adapter.
If you used dynamic linear view then rendering the view will take more time as compare to listview. In listview we are rendering views which are visible only but if you used dynamic linear view then its problem.
I'm looking to create a music app and I'd like to make a GridView similar to what Google Play uses where they inject elements that will span rows and columns like the Soilwork album does in this screenshot:
I've thought about using a ListView and populating rows with custom elements, but I couldn't think of a good way to use that with ViewHolder pattern, or really a way to make that reusable and account for differing number of items in width based on screen size (for example, the grid is only two items wide on phones, and "large" items span both columns and only one row).
I've also thought about using a ScrollView filled with custom ViewGroups, but that seems to run into the same issues I previously mentioned.
I next thought about using GridLayout, but that doesn't accept ListAdapters, and doesn't seem tuned to the kind of usage I'm looking at (nor does it seem to scroll)
I'd greatly appreciate if anyone could give me somewhere to start on this, or could point me to a library that does this. I've already checked out StaggeredGridView but it doesn't seem to accomplish what I'd like. My ideal solution would be a view which lays out items on an even grid like GridView and accepts view from a ListAdapter, also like GridView, but allow for elements to span, using the single cell constraint of GridView as the default behaviour.
Cheers.
EDIT
I have a perfectly functioning GridView as shown below, but I'd like to make items at regular intervals (every nth item) span more than one column and/or row, as shown in the previous screenshot.
Check out Parchment. GridDefinitionView may help you achieve the UI you are looking to build.
Android 2.3.3
I have an activity where I display "Device's Contacts" in my custom view(imageview, 3 textboxes, checkbox) inside a ListView. What I want to do is, display two listviews with both showing alternate contacts (Splitting the listview into two) side by side. This is because, I want to utilize space on landscape mode of larger displays.
I haven't seen many questions on SO and somewhere I have read that, this approach will mess up scrolling of listviews and will get messy.
So, can someone explain why/how would it get messy and is there another way to use the space in larger displays in my scenario.
Thanks.
This sounds like exactly what the Building a Dynamic UI with Fragments android tutorial was designed to address.
As #ooops mentions you will need to put each ListView within its own container. In the tutorial I linked to, they accomplished this by using 2 Fragment instances, each that loaded different content. Whether you copy their example and use the <fragment> tab (admitidly I don't remember which API level that works on) or use a different container like a regular LinearLayout you should be able to acomplish this easily.
You could do this, but each ListView should be in it's own container.
For examlple How to use multiple listviews in a single activity on android?
But be aware that #Rarw is more correct in the way of good programming practice. Fragments are recommended for such purpose.