I am making a custom ListView
of rows containing a CheckBox
and a TextView
. Before I used custom ListViews
with SimpleCursorAdapter, my onListItemClick()
worked fine.
I've read I have to add an onClickListener
to my TextViews
but WHERE? And WHY?
I am still extending ListActivity
and passing an Adapter
to setListAdapter(listedPuzzleAdapter);
, am I not?
public class PuzzleListActivity extends ListActivity {
private PuzzlesDbAdapter mDbHelper;
private Cursor puzzlesCursor;
private ArrayList<ListedPuzzle> listedPuzzles = null;
private ListedPuzzleAdapter listedPuzzleAdapter;
private class ListedPuzzleAdapter extends ArrayAdapter<ListedPuzzle> {
private ArrayList<ListedPuzzle> items;
public ListedPuzzleAdapter(Context context, int textViewResourceId,
ArrayList<ListedPuzzle> items) {
super(context, textViewResourceId, items);
this.items = items;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.puzzles_row, null);
}
ListedPuzzle lp = items.get(position);
if (lp != null) {
TextView title = (TextView) v.findViewById(R.id.listTitles);
title.setText(lp.getTitle());
CheckBox star = (CheckBox) v.findViewById(R.id.star_listed);
star.setChecked(lp.isStarred());
}
return v;
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.puzzles_list);
// Create database helper to open connection
mDbHelper = new PuzzlesDbAdapter(this);
mDbHelper.open();
fetchData();
}
private void fetchData() {
puzzlesCursor = mDbHelper.fetchAllPuzzles();
startManagingCursor(puzzlesCursor);
listedPuzzles = new ArrayList<ListedPuzzle>();
ListedPuzzle lp;
puzzlesCursor.moveToFirst();
while (!puzzlesCursor.isAfterLast()) {
lp = new ListedPuzzle();
lp.setTitle(puzzlesCursor.getString(puzzlesCursor
.getColumnIndex(PuzzlesDbAdapter.KEY_TITLE)));
lp.setStarred(puzzlesCursor.getInt(puzzlesCursor
.getColumnIndex(PuzzlesDbAdapter.KEY_STARRED)) > 0);
listedPuzzles.add(lp);
puzzlesCursor.moveToNext();
}
listedPuzzleAdapter = new ListedPuzzleAdapter(this,
R.layout.puzzles_row, listedPuzzles);
setListAdapter(listedPuzzleAdapter);
}
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
Intent i = new Intent(this, PuzzleQuestionActivity.class);
i.putExtra(PuzzlesDbAdapter.KEY_ROWID, id);
startActivity(i);
}
EDIT: My question was towards making the whole item of a custom ListView
clickable so I found the best answer was the one given by @Luksprog. The onListItemClick
from my ListActivity
was enough. I just needed to set the android:focusable='false'
to make it work.
Now, the CheckBox
on each item of the ListView
should "star" that item, which means, accesing the DB.
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.puzzles_row, null);
}
ListedPuzzle lp = items.get(position);
if (lp != null) {
TextView title = (TextView) v.findViewById(R.id.listTitles);
title.setText(lp.getTitle());
CheckBox star = (CheckBox) v.findViewById(R.id.star_listed);
star.setChecked(lp.isStarred());
star.setOnCheckedChangeListener(new OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
Integer realPosition = (Integer) v.getTag();
ListedPuzzle obj = items.get(realPosition);
obj.getId();
}
});
}
return v;
}
But the v.getTag()
refers to a non-final variable and if I change it the v = vi.inflate(R.layout.puzzles_row, null)
cannot be assigned. What's the best way to solve this? I never really understood the whole final deal.
If you want to add a special action for when you click the TextView
or/and CheckBox
from any of the rows in your ListView
then add a OnCLickListener
for those Views
in the getView
method of your custom Adapter
:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.puzzles_row, null);
}
ListedPuzzle lp = items.get(position);
if (lp != null) {
TextView title = (TextView) v.findViewById(R.id.listTitles);
//set as the tag the position parameter
title.setTag(new Integer(position));
title.setOnclickListener(new OnCLickListener(){
@Override
public void onClick(View v) {
// Do the stuff you want for the case when the row TextView is clicked
// you may want to set as the tag for the TextView the position paremeter of the `getView` method and then retrieve it here
Integer realPosition = (Integer) v.getTag();
// using realPosition , now you know the row where this TextView was clicked
}
});
title.setText(lp.getTitle());
CheckBox star = (CheckBox) v.findViewById(R.id.star_listed);
star.setChecked(lp.isStarred());
}
return v;
}
If you want to do an action when a row is clicked(no matter what View
from that row was clicked(if one was clicked)) just use the OnItemClickListener
on your ListView
(or the callback onListItemClick
in the case of a ListActivity
).
Also, I hope you set android:focusable="false"
for the CheckBox
(in R.layout.puzzles_row
) because I don't think onListItemClick
will work otherwise.
Edit :
You start the new Activity
in the onListItemClick
(in the case of the ListActivity
) callback if you want to start the new activity no matter where the user clicks a row :
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
Intent i = new Intent(this, PuzzleQuestionActivity.class);
i.putExtra(PuzzlesDbAdapter.KEY_ROWID, id);
startActivity(i);
}
If, for some reason, you want to start the new Activity
when the user clicks only (for example) the TextView
in a ListView
row then start the new activity in the onClick
method from my code above:
//...
title.setOnclickListener(new OnCLickListener(){
@Override
public void onClick(View v) {
Integer realPosition = (Integer) v.getTag();
ListedPuzzle obj = items.get(realPosition);
Intent i = new Intent(this, PuzzleQuestionActivity.class);
i.putExtra(PuzzlesDbAdapter.KEY_ROWID, obj.getTheId());//see below
startActivity(i);
}
//...
For this to work you'll have to modify ListedPuzzle
to also add the PuzzlesDbAdapter.KEY_ROWID
column from the puzzlesCursor
cursor in the fetchData()
method:
//...
while (!puzzlesCursor.isAfterLast()) {
lp = new ListedPuzzle();
lp.setTitle(puzzlesCursor.getString(puzzlesCursor
.getColumnIndex(PuzzlesDbAdapter.KEY_TITLE)));
lp.setStarred(puzzlesCursor.getInt(puzzlesCursor
.getColumnIndex(PuzzlesDbAdapter.KEY_STARRED)) > 0);
lp.setTheId(puzzlesCursor.getLong(puzzlesCursor
.getColumnIndex(PuzzlesDbAdapter.KEY_ROWID)));
listedPuzzles.add(lp);
//...
you can assign an onClickListener
in the adapter, but it's bad practice.
what you should do, is to implement onItemClick
like this:
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
TextView text = parent.getItemAtPosition(position);
// DO SOMETHING or in your case
//startActivity(new Intent(<the correct intent>);
}
You should implement onItemClickListener on your ListView.
ListView lv = getListView();
lv.setOnItemClickListener(new OnItemClickListener() {
});
Use onClick Listner in your adapter only. In your adapter you are returning v which is view kiond of object. Put there your onCLickListener.
egvsetOnCLickListener.
I am keeping in mind that you want to open an activity on click of view. And yes if your ListedPuzzle class is serializable or parcelable you can forward entire object using putextra method of intent from same.
If you are not clear with answer tell me I will provide you samll code snippet
lstviewemojis.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int position, long arg3) {
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.