The Problem
My way to add the view makes every fifth item to add the view when i only want one position to have this "Mängd" row.
Why Can i only edit listitems when they are visible on the screen.
The child will be static at 5 items even though i got like 20 item....
Is there any way to only say that item 1 will have this and not
position - firstvisibleposition
i think this is the problem with the listview
My code is not understandable at the time because of other things so i hope you get my problem anyways.
This is my main question
It seems like the thing i add to position 0 also happens to 6 and 12 Why is ListView this wierd ?
It's on swedish, but this is what i got with list view.
Every listview item has a empty Linearlayout that i add a view to when i press the down arrow button. the problem is that every fifth item gets this or i can only click on the first 5.
I dont get why they make ListView so complicated. i want to be able to get a child that is in the list without seening it!
CODE getView
public View getView (int position, View convertView, ViewGroup parent){
if (convertView == null)
{
convertView = LayoutInflater.from(getContext()).inflate(R.layout.view_meal_item_editable, null);
}
convertView.setOnTouchListener(new ItemSwipeListener(position,
getResources().getDisplayMetrics().density));
convertView.setClickable(true);
// Lookup view for data population
TextView food_item_name = (TextView) convertView.findViewById(R.id.food_item_name);
food_item_name.setHint("hello");
}
Where i add the view
View view = searchResultList.getAdapter().getView(position, searchResultList.getChildAt(position - searchResultList.getFirstVisiblePosition()), searchResultList);
LinearLayout extendedView = (LinearLayout)view.findViewById(R.id.extended_food_information);
View convertExtendedView = LayoutInflater.from(this).inflate(R.layout.change_amount_on_food_view, null);
extendedView.addView(convertExtendedView);
It's recommended to use a header view if you do this stuff only for the first element.
Otherwise it will be better if you add your extra view in getView() method, something like:
if(position==0){
// add extra view
} else {
// remove extra view if exist
}
Or you can remove the IF condition: if (convertView == null), so you will inflate a new layout each time, it will solve your problem but this is not good for list performance
Related
I am writing a custom adapter for ListView which extends BaseAdapter and in this method
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View vi = convertView;
if (vi == null)
vi = inflater.inflate(R.layout.x, null);
}
why is the check if(vi==null) performed. getView() is called for row when it comes in the visible area of the screen. So vi will be null everytime getview() is called? So why is the check necessary here.?
P.S. I was getting some problem on coloring some specific rows of the listview, but when i removed this check, everything works fine. Thats why i am wondering over its usefullness.
The convertView parameter may be a recycled view (for example, after scrolling down, the top rows become invisible, so their View objects are not destroyed, but recycled and passed as parameters for reuse).
However, the very first time a draw request comes, there is no view (e.g. the first time the screen with the list is loaded). Hence, in this case convertView has no value because nothing has been recycled (it is null), in which case you must create the rows using the inflater.
convertView : is for recycling. Let's say you have a listview which can only display 10 item at a time, and currently it is displaying item 1 -> item 10. When you scroll down one item, the item 1 will be out of screen, and item 11 will be displayed. To generate View for item 11, the getView() method will be call, and convertView here is the view of item 1 (which is not neccessary anymore). So instead create a new View object for item 11 (which is costly), why not re-use convertView? => we just check convertView is null or not, if null create new view, else re-use convertView.
Hello I am working on demo application where I am using listview and custom adapter. I want to do that when I scroll the list when you come at position to 2 or 3 then that row should be on top of the screen means previous row should be hide completely.
Example I am on first row first time and started to scroll listview then comes to second when getview call with position 2 then list should only show of row 2 on the screen. How I can achieve this ? Please assist.
See screenshot when I scroll then both rows appear when I even move to row 2 then first row also appears until I move up list manually.
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null) {
LayoutInflater mInflator = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = mInflator.inflate(R.layout.home_list_item, parent, false);
}
TextView mChapterContent = (TextView) convertView.findViewById(R.id.contentTextView);
// get the data from verse instance
Verse verse = rowItem.get(position);
// setting the content
mChapterContent.setText(Html.fromHtml("<html><body style=\"text-align:justify\">" + verse.getText() + "</body></html>"));
return convertView;
}
Thanks in advance.
Judging from the state, it looks to me as a good use-case of Vertical View pager.
Checkout these likes:
https://github.com/JakeWharton/Android-DirectionalViewPager/
Android: Vertical ViewPager
You can use the ListView's setSelection feature to scroll to a particular item in the list as follows...
listView.setSelection(2)
Or if you want it animated...
listView.smoothScrollToPosition(2)
This answer is referenced from this answer.
In myadapter.java I have following code:
public View getView(int position,View convertView,ViewGroup parent) {
View view=null;
if(convertView!=null)view=convertView;else view=newView(context,parent);
HashMap<String,String> d=new HashMap<String,String>();
d=data.get(position);
String _r=d.get("r");
String out=d.get("out");
Typeface mf=Typeface.createFromAsset(context.getAssets(),"fonts/mf.ttf");
TextView txt=(TextView)view.findViewById(R.id.c_n);
txt.setText(_r);
txt.setTypeface(mf);
if(out.equals("yes") && !d.get("sid").equals("-1")) {
ImageView imag=(ImageView)view.findViewById(R.id.myimage);
imag.setVisibility(imag.VISIBLE);//This fires sometimes while scroll, while
//I scroll & where I don't need it.
//view.setBackgroundDrawable(context.getResources().getDrawable(R.drawable.c_c));
//^ same as setVisibility.
}
...
return view;
}
When I start my app, this list is OK. But, while I scroll, imag.setVisibility(imag.VISIBLE); fires sometimes where I don't need it, like listview generates every scroll event. Some ImageViews become visible, that weren't at apps start.
How do I fix this?
The problem is caused by convertView and the way it is used for re-cycling existing views.
Example - suppose your list adapter has 20 items but the ListView can only display 5 on the screen. Those 5 list item 'views' will be re-cycled by being passed as the convertView parameter when the ListView is scrolled.
Once you set the visibility of the ImageView, it will remain set in the convertView. In other words you need to set it to INVISIBLE or GONE if you don't want it visible...
ImageView imag=(ImageView)view.findViewById(R.id.myimage);
if (d.get("ms").equals("yes") && !d.get("sid").equals("-1")) {
imag.setVisibility(View.VISIBLE);
}
else
imag.setVisibility(View.INVISIBLE); // Or use View.GONE depending on what you need
I have a custom adapter extended from the SimpleCursorAdapter. Using this I'm binding a ListView which contains a checkbox and Two textboxes. On opening the activity, the list appears fine. But on clicking the checkboxes and entering some text in the textboxes and scrolling down, and then up again, the data disappears.
In fact any change disappears, even if they were already checked. I uncheck them, then scroll down and up, the go back to checked. So basically, they go back whatever state they were when retrieved.
Any ideas why? Thanks.
You need to have an arraylist of the states of each item in the list,, then load these states each time the list item view is loaded.Do this by overriding GetView() method in the adapter and add your saved state to the list based on the item position
Listview tends to recreate its views every time your list is scrolled up or down. You need to have some kind of model class that can save the state of your checkbox and textbox in memory in case some change is done(for that particular row) and later display it on the view.
As mentioned on other answers in this post u can use getview to programatically induce values that you have stored in your model classes to your views based on the list view position.
Something like this
#Override
public View getView(int position, View convertView, ViewGroup parent) {
System.out.println("getView " + position + " " + convertView);
ViewHolder holder = null;
if (convertView == null)
{
convertView = mInflater.inflate(R.layout.item1, null);
holder = new ViewHolder();
holder.textView = (TextView)convertView.findViewById(R.id.text);
convertView.setTag(holder);
}
else {
holder = (ViewHolder)convertView.getTag();
}
// Pass on the value to your text view like this. You can do it similarly for a check box as well
holder.textView.setText(mData.get(position));
return convertView;
}
Android does not render all ListView entries at once, but only those visible on the screen. When "new" List-Rows come into view the
public View getView(int position, View convertView, ViewGroup parent)
method of your Adapter gets called and the view is recreated.
To fill in previousely saved values you probalby have to overwrite the getView method.
I am retrieving a list of items from a URL and displaying them in a ListView using a customized ArrayAdapter. I display at most 25 results, but retrieve up to 26 from the URL because I want to display a "next" link if there are more than 25. I am trying to figure out a way to make the last item in the view just display the next link instead of the image and two TextViews that the other items display. Scrolling down, all the items show up the way they are supposed to, but the last item continues to look like the rest. When scrolling back up, every fifth item is blank (can tell it is still there because of the separating lines).
Inside getView:
if (position + 1 == limit) { // Limit = 26, corresponding position is 25
Log.e("Last Item", String.valueOf(position));
// Gone
image.setVisibility(8);
text.setVisibility(8);
// Visible
next.setVisibility(0);
} else {
if (item != null) {
Log.e("Other item", String.valueOf(position));
if (top_text != null) {
top_text.setText(item.getItemTitle(), BufferType.SPANNABLE);
}
if(bottom_text != null){
bottom_text.setText(item.getItemDescription());
}
}
}
return view;
In ddms, it is printing the "Last Item" tag only for the last item, and the "Other Item" tag for the rest, but the items aren't being changed based off the if-else. In the XML, next is set to gone so it doesn't need changed in the else. When I remove the if-else and leave only the code within the else, the list functions properly but I need the next link. Any ideas for the cause of the odd behavior? Please let me know if you need to see any additional code or need clarification on what is happening.
Please post full code of getView.
You return view; but what is view, is it convertView or inflated from xml?
Here is way how i get different view for last item:
1. create 2 layout, the first for normal items, the sencond for last item
2. in getView(int position, View convertView, ViewGroup parent)
View view = convertView;
if (view == null) {
LayoutInflater vi = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = vi.inflate(R.layout.xxx, null);
} else {
//check if view is not layout we need (based on position), we need inflate from xml
}
//set text ...