Hi I have a list and I am redrawing the image based on the setting on notification. Basically I can't figure out why the image is NOT redrawn. I see in the log that it gets set.
Odly I tried to set a textview in the same view and that works fine. What's wrong with the image? can anybody tell me?
Thank you in advance!
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
//---- if the view is null, create a new one from xml
if (convertView == null)
{
LayoutInflater layoutInflater = _context.getLayoutInflater();
convertView = layoutInflater.inflate(R.drawable.my_item_layout, parent, false);
convertView.setBackgroundResource(R.drawable.mybg);
}
CustomItem item = super.getItem(position);
if (item != null)
{
TextView title = (TextView)convertView.findViewById(R.id.titleTextView);
ImageView image1= (ImageView)convertView.findViewById(R.id.image1);
title.setText(item.getName());
if (item.getMyNotificationChangedItemState()){
image1.setImageResource(R.drawable.myimagePink); <- this does not get updated
title.setTextColor(this._context.getResources().getColor(R.color.main_text_pink));
else
{
image1.setImageResource(R.drawable.myimageBlue);
title.setTextColor(this._context.getResources().getColor(R.color.main_text_blue));
}
}
So my Blue image & text gets shown when the list gets loaded the first time. Once notification happens I first update to change the one that's currrently PINK to BLUE and then change the one that I need to update from BLUE to PINK depending on previous and current index of the items in the list. The update is done on the activity. I can see the log prints the fact that getMyNotificationChangedItemState() is changed, and the image is being set, but I never see the change in the UI.
Why does that work for TEXTVIEW and does not work for IMAGEVIEW?
For adapters, getView() only gets called when the current view is invalidated.
Have you made sure to call invalidate() on the view in question after you make the notification?
As another sanity check, what about switching pink and blue and trying again?
Related
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
I'm trying to perform something like the GMail app does: when long touching several List view items their background colour is changed so that the user notices that something happened.
My problem is to keep those items visually selected (with the background colour changed) when the device orientation is changed. I tried this with little luck:
ListView lv = getListView();
ItemAdapter adapter = (ItemAdapter)lv.getAdapter();
if (adapter == null) return;
for (Item q : mSelectedItems) {
int position = adapter.getItemPosition(q);
if (position == -1) continue;
View itemView = lv.getChildAt(position);
if (itemView == null) continue;
itemView.setBackgroundColor(getResources().getColor(R.color.orange));
}
I call this method from the onRestoreInstanceState() callback, but I receive a null in itemView because it seems that the listView hasn't been filled up yet, so there are no children at the moment. I tried to call this method from the onResume with no luck as well.
What's the proper way to accomplish this?
I found the solution by myself. The proper way to accomplish this is the custom Adapter created to fill the view. Create the adapter providing a context (the Activity that has the information of which items should be painted this way or that way) and call it to get the items whose background must be changed. When iterating on the listview to paint, if the current item is one of those, paint it differently. Example:
public View getView(int position, View convertView, ViewGroup parent) {
...
RelativeLayout itemLayout =
(RelativeLayout) LayoutInflater.from(mContext).inflate(R.layout.my_layout, parent,
false);
if (((MyActivity) mContext).isItemSelected(item)) {
itemLayout.setBackgroundColor(mContext.getResources().getColor(R.color.orange));
}
}
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 am using the current Android SDK, r15.
In my Project, I am using ListViews with customized Adapters, based on BaseAdapter. In the BaseAdapter::getView-method, there is a view, inflated from xml ressources and customized and filled with text; also the background color is changed, depending on several conditions. This works great at all, but:
On Android Virtual Devices (AVD) with Android 3.0 and higher, I've got the problem, that at some point, when Android tries to recycle existing views, the background color does not change, even if it is specified in the xml ressource.
Shall I assume, that this is a problem of the android emulator, or may it be that this also happens on real devices?
I never saw this problem on a real device yet, with the same application.
non-abstracted example:
I've got a project with a login-layout (almost white, with input fields and a button), a "tablet"-layout containing a contact listView and a conversation listView; after logging in, I am able to select a contact. Online contacts have got a green background, offline contacts a white one. After selecting the contact the background of the contact turns red. Conversation is loaded into the conversation listView. Now I log off, and now it could be that my former white login is green or red, as in the contact ListView before. Also, it could be that even my conversation listView-Entries inherit the color of a contact listView element, ignoring the background color specified in the xml. That seems quite random.
Shortened code of getView:
(just excluded the code for setting 'profileImage')
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = inflater.inflate(R.layout.contacts_listelement, parent, false);
int userId = contactList.get(position);
BackendStamp user = users.get(userId);
ImageView profileImage = (ImageView)view.findViewById(R.id.profilePicture);
TextView username = (TextView)view.findViewById(R.id.username);
TextView unreadMails = (TextView)view.findViewById(R.id.unreadMails);
ImageView userStatus = (ImageView)view.findViewById(R.id.userStatus);
if (user != null) {
if (user.getUnreadMails() == 0) {
unreadMails.setBackgroundResource(R.drawable.bgmessagesnull);
unreadMails.setTextColor(0xff000000);
}
else {
unreadMails.setBackgroundResource(R.drawable.bgmessagesnotnull);
unreadMails.setTextColor(0xffffffff);
}
if (user.getStatus() == 0) {
view.setBackgroundColor(0xFFFFFFFF);
}
else {
view.setBackgroundColor(0xFFEFFFD4);
}
// [...]
username.setText(user.getNickname());
unreadMails.setText("" + user.getUnreadMails());
// [...]
}
return view;
}
Try this snippet:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view;
if(convertView == null) {
view = inflater.inflate(R.layout.contacts_listelement, parent, false);
}
else {
view = convertView;
}
Even if this does not solve your problem, this is great performance boost to your ListView. As Android tries to re-use views, convertView is null first time and then it contains the old created views which are re-cycled and should be used.
I am working on customize (inflated) list view. In which I have used the text and background image for text (as per the condition).
Now I am facing problem in scrolling the list view that background of text view is overlapping to the other text views.
Here is the sample code:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View icontextlayout=convertView;
icontextlayout= inflater.inflate(R.layout.layout_complex_list, null);
TextView Txt1=(TextView)icontextlayout.findViewById(R.id.txt1);
if(disp1==true)
{
Txt1.setBackgroundResource(R.drawable.pic)
}
else
Txt1.setText("Text1 "+strUser);//
TextView Txt2=(TextView)icontextlayout.findViewById(R.id.txt2);
if(disp2==true)
{
Txt2.setBackgroundResource(R.drawable.pic);
}
else Txt2.setText("Text2: "+strIndus);
return icontextlayout;
}
Could you please help me out that background image pic do not overlap the others background.
Thanking you...
The problem is that you must set a default background when you don't need a background. For instance:
if(disp1==true){
Txt1.setBackgroundResource(R.drawable.pic);
Txt1.setText("");
}
else{
Txt1.setText("Text1 "+strUser);//
Txt1.setBackgroundDrawable(null);
}
Also, if you don't mind, I like to give you my opinion about your code:
That's not they way in which list are usually populated. Take a look at this answer: How to load the Listview "smoothly" in android
convertView is used to reuse rows. In your case you are doing something like:
View icontextlayout=convertView;
icontextlayout= inflater.inflate(R.layout.layout_complex_list, null);
Which is bad, because you are not actually using the convertView (when you call inflater.inflate) it will create a new row, thus your list will be really slow.
if(disp2==true) is redundant. You should consider using just: if(disp2).