Android: load items on listview from a certain point onward - android

I have an activity that load messages from internet. Im downloading this to Sqlite, later add this to adapter.
I want to add on screen from a particular number onwards.
We may think we have added 100 items in arrayList adapter. and just we want to show from 75 onwards. SQLite I can add from the last 25, but can not do so because the adapter arrayList must contain all.
I've overwritten getCount () and return 25 to limit the maximum of items, but it does show the first 25 items, not last 25 items.
I think I must do something in getView(). (method override in adapter)
Any ideas?
*************EDIT.ADD SOLUTION
adapter
#Override
public int getCount() {
if(messagesItems.size() <= maxRowsShow){
return messagesItems.size();
}else{
offset = messagesItems.size() - maxRowsShow;
return maxRowsShow;
}
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
position = position + offset;
...}

I would suggest you do the following.
Get offset of list from where you would like to show list. For eg. 75 from list of 100.
Return offset - list.size() in 'getCount()' of Adapter.
In getView() to get particular item do item = list.get(offset + position)

I have not tried this but maybe you can load all the items in the adapter and then based on their position you can display the one's you need.
I am not sure if this is going to work but atleast you can give it a try.
Thanks

Related

How to display only even position items in ListView?

I am getting data from Database and displaying using a custom list adapter in a ListView. I need to display only even position items in ListView.
i am able to solve this in two ways.
1. sorting data before attaching to adapter, but i want to do those task in getView() method of adapter/by using other available methods in adapter.
2.
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
if( position%2 == 0 ) {
// display
} else {
// not display
}
return view;
in this i am getting alternate view's are empty view's.. i want to avoid these empty view.
i ant to do those all calculations in getView() method, without empty view in the ListView. How i can do this?
I will suggest you to create new List with filtered data and use it in your adapter. Still if you want an alternate solution you can try below code:
#Override
public int getCount() {
int halfCountOfList = itemList.size()/2;
// Add +1 in halfCountOfList if itemList size is odd.
int finalCount = halfCountOfList + itemList.size()%2;
return finalCount;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
Item item = getItem(position*2);
//No need to to check for even item
return view;
}
No, just no. This is a really bad idea.
Don't do this. It makes no sense. Think about it: getView() is called because a View for an item is required. It is too late to make any decision about whether this item needs to be displayed in the ListView or not, it already has to be displayed. What you are trying to do is simply not how ListViews and Adapters are supposed to work.
Just filter the List before passing it to the Adapter, you can modify the List while it is being displayed by exposing it through a getter method on the Adapter and then immediately calling notifyDataSetChanged(). Any other solution which deviates from this or tries to make Adapters work like you expect it would just be a brittle hack and should never be used.
PS: Use a RecyclerView instead of a ListView. It's much better.
If you give a ListView adapter a set of data to display, it's going to try to call getView() on all of the data when it's needed - it doesn't discriminate. The decisions on how to display it are made in the getView() function.
The two are options are to either modify the data set, or only provide full-fledged views to your even index-ed values. Unfortunately, there aren't other ways around this.
Make a another list which contains only even position items in it and pass it on adapter. adapter will call getView method for all items present in list.
make another function in adapter
public int getItemViewType(int position) {
// return a value between 0 and (getViewTypeCount - 1)
return position % 2;
}
After that in GetView() method
int viewType = getItemViewType(position);
switch (viewType) {
case 0:
layoutResource = ;//Even Item
break;
case 1:
layoutResource = ;//Odd Item
break;
}
IF Your data will be of some objectType and the database will return
ArrayList<Object>,
then you can do this
Eg:-
ListView lv; // assign this view to some ListView
final List<Object> listResult; //sorted list returned by database
int len = listResult.size();
for (int i = 1; i <= len; i++) {
if (i % 2 == 0){
Object x = listResult.get(i);
//extract the data you need from the object returned
lv.add(x);
}
}

Hide specific items (set in SharedPreferences) in RecyclerView

I want to filter/hide specific Items in the RecycleView if the item content matches with an preference set in SharedPreferences.
I guess I have to somehow prevent from these specific items from getting inflated in the adapter but I have no idea how.
Any ideas?
Cheers!
An adapter is the Model part of the Model-View-Controller design pattern for using ListView, GridView, and RecyclerView. So you have to think of it this way: The adapter, at any moment, has to reflect what you want to have displayed in the RecyclerView.
So here's an example: Let's say you have four items, and you want to filter the third item because it matches your preference. Your adapter's getCount() method must return 3. For getView(), position == 0 must return the first item view, position == 1 must return your second item view, and position == 2 must return your fourth item view.
It's up to your adapter code to figure out all calculations and offsets to make sure that it is always presenting a consistent state to the view. So for example, let's say you have a String array with the items, and an index dontshow pointing to the array item that shouldn't be displayed. You need to do something like this for getView():
int index = position; // position is input parameter
if (index >= dontshow) {
index++; // skip over the don't-show item
}
String item = items[index];
// now construct your view from this item
And
#Override
public int getCount() {
return items.length - 1;
}
Then when you make changes to your model, calling notifyDataSetChanged() tells the RecyclerView it has to call getCount() and getView() on your adapter all over again to redisplay the changed data.

Listview data model updated but items not displaying

I have searched these forums for nearly 3 hours and seen several similar questions but none of the answers works for me.
I have a single Activity, with several card views. One of the card views has a Spinner with string values and a very simple ListView. The user selects a value from the Spinner, between 1 and 12. The ListView should then display a number of strings equal to the value selected, based on the position in the spinner list. For example, user selects 2nd item in spinner list and the ListView displays 2 strings. I have a custom adapter on the listview. The ListView itself initially displays a single row, which is correct. However, after the user selects a value from the spinner, the listview is not displaying the extra rows, it still only displays one row. The data for the ListView comes from an ArrayList. I have checked the data model of the adapter after the user selects a value and it has the correct number of entries, as does the ArrayList itself, yet no matter what I try the ListView itself still only display the first row. I have tried NotifyDataSetChanged and every variation of Invalidate without success.
The various code samples:
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (parent == spDoseFrequency){
Toast.makeText(this,String.valueOf(position),Toast.LENGTH_SHORT).show();
rebuildReminderTimesList(position + 1);
}
}
private void rebuildReminderTimesList(int numberOfTimes){
Toast.makeText(this,"yup",Toast.LENGTH_SHORT).show();
//reset selected item to position 1
myApp.iSelectedReminderTimeIndex = 0;
//clear array and list, then rebuild with hourly timeslots
iarrTimes = new int[numberOfTimes][2];
liReminderTimes.clear();
int startTime = 8;
for (int i = 0; i < numberOfTimes; i++){
iarrTimes[i][0] = startTime + i;
iarrTimes[i][1] = 0;
liReminderTimes.add(pad(startTime + i) + ":00");
}
//refresh the listview
myAdapter.notifyDataSetChanged();
}
public class ReminderListAdapter extends ArrayAdapter {
List<String> liTimes;
Context ctx;
LayoutInflater inf;
public ReminderListAdapter(Context ctx, List<String> liTimes) {
super(ctx, R.layout.reminder_time_listview, liTimes);
this.liTimes = liTimes;
this.ctx = ctx;
inf = LayoutInflater.from(ctx);
}
public void setLiTimes(List<String> liTimes){
this.liTimes = liTimes;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
ViewHolder viewHolder;
if (view == null){
view = inf.inflate(R.layout.reminder_time_listview,parent,false);
viewHolder = new ViewHolder();
viewHolder.sTime = (TextView) view.findViewById(R.id.tvTime);
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) view.getTag();
}
viewHolder.sTime.setText(liTimes.get(position));
return view;
}
private static class ViewHolder{
TextView sTime;
}
}
Any help would be appreciated as this is driving me crazy.
Quick update to this question: I have just tested supplying the initial list more than one value but even then it only displays the first item. Is there perhaps a problem with using ListView inside a CardView object? All my other cards work fine, only the ListView one fails to display properly.
Also, I have tried amending the code so that instead of changing the number of elements in the list, it just changes the text in the string of the first element and this works fine. So the notifyDataSetChanged appears to be working, but it just won't display more than one item. A quick check of the Adapter.getCount() method also gives the correct number of elements back, but won't display them.
A lot of folks forget to do the notifyDataSetChanged() call, but you've got that. Are you using a custom adapter? If so, that makes this sound like an issue with one or more of the adapter's methods. In particular, it sounds like getCount or getView might not be returning what they should be. That could either be because of a flawed logic issue, the underlying data source isn't being updated correctly, or the underlying data source isn't the same object you think it is. Without seeing your adapter though, it's hard to diagnose.
I found the problem. I had several CardView objects inside a LinearLayout, which itself was inside a ScrollView. As soon as I removed the ScrollView, the List inside the Card displayed properly. This has unfortunately created another problem in that I can no longer scroll the page to see later cards, which I have not yet found a solution for, but that is a different topic.

Building a custom List

I am trying to generate a list from an object using an ArrayAdapter. The result Looks like:
Item A (3)
Item B (1)
Item C (0)
The number in brackets represents the amount of items that are behind that file. I want to Display an Image whenever there is a 1 in brackets - in this case only for item B.
I have an Attribute Image available that is only set true when the item has a 1.
However, when I'm creating the list, it creates everywhere the Image, except in Item C. I have created a short log to try to understand the reason and found out, that public View getView(int position, View convertView, ViewGroup parent) {
method is called up to 11 times... though the 1st 3 should be enough. when i modified my if clause that it should set imageavailable to false when an item is detected - only the 1st item had a Picture. can anyone help me out? ( i also tryed to make if(imageavailable&number==1) resulting in the same result - 1st 2 have a picture
You should be managing the adapter, not adding logic to getView. You logic for handling the adapter should be in its own method. For example:
ArrayList<Drawable> adapter = new ArrayList<Drawable>();
void constructAdapter(List<Drawable>... drawables, int sizeFilter) {
if (drawables != null) {
for (List<Drawable> l : drawables) {
if (drawable.size() == sizeFilter) {
for (int i = 0; i < sizeFilter) {
adapter.add(l.get(i));
}
}
}
}
}
And then from here you would pass the adapter list into your array adapter.
Note: I used drawable as my example, since you said images. This could be whatever you want, so long as you just change the logic to handle that particular data set.

What is the best way to change drawable of all item in ListView

Let say I have my view that I use it as a toggle button. When user clicks it, I change the background via setBackgroundResource(). The number of list is around 15 items and ListView can show only around 7 items on screen.
At first, I try to use ListView.getChildAt(position) but when position is more than 7 it returns NullPointer. eventhough ListView.getCount() returns 15. But that's make sense because it show only visible child.
Then I solve it by loop through all Data that binds to this Adapter, change the boolean value, and call notifyDataSetChange()
So the number of loop will be 15 for update data + 7 show visible view.
The best way should be 15 and that's done.
Is there anyway to achieve this?
Thank
Forget your child index. You should just toggle some type of flag in your adapter.
Then when your getView method is called again it will redraw your list.
i.e.:
public class YourAdapter extends BaseAdapter {
private boolean useBackgroundTwo = false;
.. constructor ..
#Override
public View getView (int position, View convertView, ViewGroup parent) {
...
...
View background = findViewById(...);
int backgroundResource = R.drawable.one;
if(useBackgroundTwo){
backgroundResource = R.drawable.two;
}
background.setBackgroundResource(backgroundResource);
....
}
public void useNewBackground(){
this.useBackgroundTwo = true;
notifyDataSetChanged();
}
public void useOldBackground(){
this.useBackgroundTwo = false;
notifyDataSetChanged();
}
}
Then in your activity code:
((YourAdapter) listview.getAdapter()).useNewBackground();
Taking it further, you could use an enum instead of a boolean and have multiple methods setBackgroundGreen(), setBackgroundRed() or you could pass in the drawable you want to use setItemBackground(R.drawable.one); The choice is yours.
Api: Adapter

Categories

Resources