• After 15+ years, we've made a big change: Android Forums is now Early Bird Club. Learn more here.

Apps Listview OnItemLongClick and getView - part 2 - the saga continues.. [SOLVED]

timcs

Member
Sep 18, 2013
61
6
from this original post :
http://androidforums.com/application-development/770370-listview-onitemlongclick-getview-solved.html

I had help from alostpacket to get the longclick to highlight the row on the simplecursor adapter.

Now as further progress to this, I would like the user to be able to unhighlight the row also using a long click. This I thought should be simple but after hours of trying to get this to work and also getting so close, I have run into a problem.

The problem occurs when the following pattern happens :

User long clicks on e.g. row 1 . This is then highlighted. User then long clicks on row 1 again, this is then unhighlighted and at this point I added a Toast message to confirm this part works. So far so good.

User then long clicks on e.g. row 3 - this is highlighted but if the user either long clicks on row 1 afterwards or long clicks on row 3 to unhighlight (that works) but then long clicks on row 1, it does not highlight BUT it does not bring up the Toast message so I know it has not reached the method to unhighlight it.

Sorry if the above sounds confusing it is very hard to explain in a post .

Also found that due to multiple return true statements in this SetValueView method this makes the method get read for every return true that there is. I am wondering if this has some affect on what I am trying to do


I am still using the viewbinder as per the post link above but I have added logic ( all be it upside down :) ) to both the long click method and the viewbinder as well.


Long Click Code :

[HIGH]
if (longrowclick1==arg2) {
islongclickbefore = true;
adapter.notifyDataSetChanged();
Toast.makeText(getApplicationContext(), "YOU HAVE CLICKED HERE BEFORE!!!!", Toast.LENGTH_LONG).show();
// longrowclick1 = -1;
return true;
} else {
isclick = false;
islongclick = true;
longrowclick1 = arg2;
Log.d("ONITEMLONGCLICK","View Clicked = "+arg1);
Log.d("ONITEMLONGCLICK","Position Clicked = "+arg2);
islongclickbefore = false;
adapter.notifyDataSetChanged();
// datalist.smoothScrollToPosition(longrowclick1);

return false;
}
[/HIGH]



ViewBinder / SetViewValue Code part 1 of 3 :

[HIGH]
if (cursor.getPosition()==longrowclick1 && !islongclickbefore ) {
islongclicked = true;
// sets up parent view of object
myviewp = (View) view.getParent();
Log.d("HERE", "Set to Blue not long clicked");


// checks if parent view is valid (there are a lot here)
if (((View)view.getParent()).getId()==R.id.Table1 || ((View)view.getParent()).getId()==R.id.tableRow1 || ((View)view.getParent()).getId()==R.id.tableRow2 || ((View)view.getParent()).getId()==R.id.tableRow3 || ((View)view.getParent()).getId()==R.id.Table2 || ((View)view.getParent()).getId()==R.id.Table3 ) {
//Toast.makeText(getApplication(), "Long Row Click1 = "+Integer.toString(longrowclick1) +" and Prev Long Click = "+Integer.toString(prevlongclick) , Toast.LENGTH_LONG).show();
Log.d("PARENTCHECK", "Set to Blue not long clicked");

myviewp.setBackgroundResource(R.drawable.darkslateblue);
if (view.getId()!=R.id.seper) {
view.setBackgroundResource(R.drawable.darkslateblue);

// ... set them to the dark slate blue ...
// view.setBackgroundResource(R.drawable.darkslateblue);
} else { // else if the child object is the date separator ..
// .. keep it as dark gray
view.setBackgroundColor(Color.DKGRAY);
}
}
[/HIGH]


ViewBinder / SetViewValue Code part 2 of 3 :

[HIGH]
if (cursor.getPosition()!=longrowclick1 && !islongclickbefore ) {// if the cursor position does not match the Long Click Position then ..
// .. get the parent of the current child object ...
islongclicked = false;
Log.d("HERE", "Set to black not long clicked : longrowclick1 row no= "+longrowclick1 +"Cursor POS="+cursor.getPosition());
//islongclickbefore = false;
// colorcounter = -1;

myviewp = (View) view.getParent();
// .. set the background of the parent to black ..
myviewp.setBackgroundColor(Color.BLACK);
// .. check to make sure that the child object is not the date separator ...
if (view.getId()!=R.id.seper) {
// .. and then set the child object background to black ..
view.setBackgroundColor(Color.BLACK);
} else { // .. else if it the child object is the date separator then ..
// .. set it to the dark gray background .
view.setBackgroundColor(Color.DKGRAY);
}
ColorDrawable vbk1 = (ColorDrawable) myviewp.getBackground();
Log.d("BACKGRD", "Back Ground Color of Main Views int value when not selected (BLACK) = "+vbk1.getColor());


}
[/HIGH]



ViewBinder / SetViewValue Code part 3 of 3 :

[HIGH]
if (cursor.getPosition()==longrowclick1 && islongclickbefore ) {
Log.d("HERE", "Set to black - Long Clicked!!!");
myviewp = (View) view.getParent();
if (((View)view.getParent()).getId()==R.id.Table1 || ((View)view.getParent()).getId()==R.id.tableRow1 || ((View)view.getParent()).getId()==R.id.tableRow2 || ((View)view.getParent()).getId()==R.id.tableRow3 || ((View)view.getParent()).getId()==R.id.Table2 || ((View)view.getParent()).getId()==R.id.Table3 ) {
// .. set the background of the parent to black ..
myviewp.setBackgroundColor(Color.BLACK);
// .. check to make sure that the child object is not the date separator ...
if (view.getId()!=R.id.seper) {
// .. and then set the child object background to black ..
view.setBackgroundColor(Color.BLACK);
} else { // .. else if it the child object is the date separator then ..
// .. set it to the dark gray background .
view.setBackgroundColor(Color.DKGRAY);
}
}
//longrowclick1 = -1;
//islongclickbefore = false;
return true;

}[/HIGH]


Thanks

TimCS
 
Since posting here I have done more debugging and testing and found that during the re-loads of the viewbinder method, on the last re-load, the section of code that checks for the parent view, is where it stops working.

What I have then found is that on the last re-load of this method (viewbinder) the parent view is lost or dropped for some reason or another.

What is odd is that when the row is first longlicked this is all fine, it is only when the row is re-onlonglicked where the highlighter does not work.

I will continue to look into this but any advice/help/suggestions would be useful


Thanks

TimCS
 
Upvote 0
I think I may need to re-write this part of my app and use a custom simplecusroradapter and a getview instead. I have found this page Android-er: List MediaStore.Images.Thumbnails in GridView, with custom SimpleCursorAdapter. which will hopefully point me in the right direction.

Also I have used a custom ArrayAdapter to achieve a similar goal but this was to list files and folders and only had a single textview to achieve this. However the highlighter logic should be the same for the simplecursoradapter.

As and when I get this resolved I will post the code here so that it can help any future issues with the same problem

Thanks

TimCS
 
Upvote 0
Having problems with the custom simplecursoradapter and I wondered if someone could help please . I have set it up as follows :

[HIGH]public class mainlistadapter extends SimpleCursorAdapter {
private Cursor datacursor;
private Context datacontext;
private String[] datafrom;
private int[] datato;
public mainlistadapter (Context context,int layout, Cursor c, String[] from, int[] to) {
super(context,layout,c,from,to);
datacursor = c;
datacontext = context;
datafrom = from;
datato = to;

}

@Override
public View getView(int position,View convertView, ViewGroup parent) {
super.getView(position, convertView, parent);
View v = convertView;
if (v == null) {

LayoutInflater grow=getLayoutInflater();
//grow = LayoutInflater.from(getBaseContext());
v = grow.inflate(R.layout.viewdata, null);
}

// Start data build up here for the cursor adapter display ......
String imgreference = datacursor.getString(datacursor.getColumnIndex("image_desc"));
if (v.getId()==R.id.image_type ) {
//Log.i("IMG", "Setting unqiue image");
int imgres = getResources().getIdentifier(imgreference, null, null);
((ImageView)v).setImageResource(imgres);
}


return v;
}
[/HIGH]
But when I call the adapter by creating it as a new variable and doing the following :

[HIGH]getmainlistadapter = new mainlistadapter(this,R.layout.viewdata,mC,fields,viewfields);
[/HIGH]

The list when loaded up, is not showing data from the database instead it just shows the default values from the layout.

I have also tried the adapter as follows :

[HIGH]public class mainlistadapter extends SimpleCursorAdapter {
private Cursor datacursor;
private Context datacontext;
private String[] datafrom;
private int[] datato;
public mainlistadapter (Context context,int layout, Cursor c, String[] from, int[] to) {
super(context,layout,c,from,to);
datacursor = c;
datacontext = context;
datafrom = from;
datato = to;

}

@Override
public View getView(int position,View convertView, ViewGroup parent) {

View v = super.getView(position, convertView, parent);


// Start data build up here for the cursor adapter display ......
String imgreference = datacursor.getString(datacursor.getColumnIndex("image_desc"));
if (v.getId()==R.id.image_type ) {
//Log.i("IMG", "Setting unqiue image");
int imgres = getResources().getIdentifier(imgreference, null, null);
((ImageView)v).setImageResource(imgres);
}


return v;
}
[/HIGH]

This does appear to be loading data into the list from the database but the field I am loading in as an image, does not pick up the image from the path held in the database, instead it just shows the path itself .

The logic for loading the fields from the database is the same as I used in the Viewbinder .

** Update 28th Nov 7:43am **
Looks like I need to use bindView to feed the data into the fields - got two to work so far. However there are some more complicated methods that I have set up so I will need to test these

Thanks

TimCS
 
Upvote 0
Sorry for the following rant but I need to do this :

[rant]

Why does Android SDK/Java make what I would to be an easy thing to do so difficult ? . I have been spending hours if not days or weeks trying to get the highlight to work and searching online for answers but I have failed to achieve my goal. I feel out of my depth for something that should be so easy and am going grey too early in my life :)


[/rant over]

Now that I have that off my mind, I REALLY need some help with this because I would like to publish this app at some stage but I feel that putting it on the store with a simple thing not working would be embarrassing.

I have created the custom simple cursor adapter. I tried the logic that I have working on a custom arrayadapter but this has failed to work in the same way.

The custom simple cursor adapter has been tried with either the bindView and getView methods now, as I have got both working (not together as they conflict with each other) but I still am unable to get a previous highlighted row to be highlighted again.

Thanks

TimCS
 
Upvote 0
So I have kept on at this and ended up applying a viewholder thinking that the recycling of the rows was the cause of the problem.

However it ended up being the setBackgroundResource setting against the objects when giving them a color and then using setBackgroundColor to set the row background transparent when highlighted.

it seems that if the specific object is referred to directly with the setBackgroundResource - re-using this method behaves very odd but if the view object is used in this way : ((TextView)view).setBackgroundColor this can use a drawable color setting .


Thanks

TimCS
 
Upvote 0
Glad to hear you got it sorted.

I didnt follow as closely this time but to address your rant, I think you had a fundamental misconception about how view recycling works and how cursoradapters and bindView and getView work.

Basically I think you tried to do too much at once.

Maybe next time try using an array list and a BaseAdapter and see if that gives you some ideas about how the adapter is supposed to function without bogging you down with view binding and db cursors.

Just a thought, anyways, glad to hear you pushed through and got it working. That's an excellent skill for a dev :)
 
Upvote 0
Glad to hear you got it sorted.

I didnt follow as closely this time but to address your rant, I think you had a fundamental misconception about how view recycling works and how cursoradapters and bindView and getView work.

Basically I think you tried to do too much at once.

Maybe next time try using an array list and a BaseAdapter and see if that gives you some ideas about how the adapter is supposed to function without bogging you down with view binding and db cursors.

Just a thought, anyways, glad to hear you pushed through and got it working. That's an excellent skill for a dev :)

Hi alostpacket, I agree with what you have said about my misunderstanding here. Hence my post for a cry for help :) . However the fact that the issue was down to a setting setbackgroundresource and setbackgroundcolor was very frustrating.

It seemed that the custom arrayadapter that I had used worked because 1) there was only one view object in the row and 2) in getview this was used as ((TextView)view).setbackgroundresource .

In the case of the simple cursor adapter there are several textviews , one imageview and table layouts / table rows. So (and this may not be the best way of doing it) I ended up declaring these individually via the viewholder and because they are created as such using setbackgroundResource behaved very differently. My only problem is now, the color I wanted to use which is defined as a drawable file, will not work using the setbackgroundcolor .

Thanks

TimCS
 
Upvote 0

BEST TECH IN 2023

We've been tracking upcoming products and ranking the best tech since 2007. Thanks for trusting our opinion: we get rewarded through affiliate links that earn us a commission and we invite you to learn more about us.

Smartphones