In the application I am writing, I have a main class which extends the ListActivity - it contains a list of elements. I want these elements to link to a different page (an xml one, or perhaps a View object). However, I realised one cannot use the method setContentView(int) on a ListActivity object.
What's to be done?
Thanks!
Looks like you are trying to launch a new activity.
You have to override the onListItemClick method of ListActivity.
Here is the code.
// ListView l points to list view whose item user clicked
// View v points to the item in the list view on which the user clicked
// int position is the position index of the item in the list
// long id is the id assigned to the item. This id is assigned using the ListAdapter, CursorAdapter etc.
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
// I am using getApplicationContext() as it is more safe then just passing `this`
Intent i = new Intent(this.getApplicationContext(), ActivityToRun.class);
this.startActivity(i);
}
NOTE: You have to improve on this skeleton depending upon your needs.
Have you tried setting the XML page as a ListView and give it the ID #android:id/list?
Related
Currently I am making an app in Android which is a todo list, it has a edit text, button and a listview, when button is clicked the text is added to listview, everything works fine but when i add too many items to list view and try to select a list item my app stops working and I get a error saying
java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.View android.view.View.findViewById(int)' on a null object reference
Does anyone know a fix?
this is my view data method whcih displays items in listview
public void viewdata(String tablename)
{
db = new mydbhandler(this);
lvitemslist = findViewById(R.id.lvitemlist);
ArrayList mylist = new ArrayList();
Cursor c = db.getdata(tablename);
while(c.moveToNext())
{
mylist.add(c.getString(1));
}
ListAdapter mylistadapter = new ArrayAdapter(this,R.layout.custom_item_row,R.id.ctv,mylist);
lvitemslist.setAdapter(mylistadapter);
}
and this is the onitemclicklistener
lvitemslist.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
View v = lvitemslist.getChildAt(i);
CheckedTextView ctv = v.findViewById(R.id.ctv);
ctv.setCheckMarkDrawable(android.R.drawable.checkbox_on_background);
db.deletedata(tablename,ctv.getText().toString());
viewdata(tablename);
Take a look at this line from your OnItemClickListener:
View v = lvitemslist.getChildAt(i);
I guess you want to assign the ListView row which was clicked to the variable v. But the ViewGroup method getChildAt(int) (ListView is a kind of ViewGroup) will give you
the view at the specified position or null if the position does not exist within the group
(quoted from the ViewGroup documentation)
Like you said, this works for the first few items but for higher positions the app crashes. This is because the ListView has a fixed number of child Views: about as many as fit on the screen simultaneously plus some more to enable smooth scrolling. For every clicked row beyond that fixed number, lvitemslist.getChildAt(i) will return null.
What can you do to fix your code?
Luckily you do not have to do much work to get the clicked View, it is handed to you as one of the parameters of onItemClick(): the second parameter is the clicked ListView row.
So you just need to write
lvitemslist.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long rowId) {
CheckedTextView ctv = view.findViewById(R.id.ctv);
ctv.setCheckMarkDrawable(android.R.drawable.checkbox_on_background);
db.deletedata(tablename,ctv.getText().toString());
viewdata(tablename);
}
}
This will help you to avoid the NullPointerException.
Another thing: you change the appearance of a ListView row from outside of the Adapter by calling
ctv.setCheckMarkDrawable(android.R.drawable.checkbox_on_background);
This is dangerous (there are lots of questions on this site where people had weird behaviour when scrolling as a consequence). It may not be a problem in your case because you refresh the whole ListView soon afterwards. But generally one should provide the Adapter with all the data necessary to decide what each row should look like. Then one can change the data list and after that of course call notifyDatasetChanged() on the Adapter.
I am currently learning android and working on a few projects...in this one I have a list view and when I click it I pass the name of the row I click and a value from a database to my NEXT activity and that works 100%.
This is part of my main Activity on create code. where I populate the listview from my database here and other stuff.
lvUsers = (ListView)findViewById(id.lvUsers);
List<String> listUsers = dbHeplper.getAllUsers();
if(listUsers != null){
adapter = new ArrayAdapter<String>(getApplicationContext(),android.R.layout.simple_list_item_1, android.R.id.text1,listUsers);
// adapter = new ArrayAdapter<String>(getApplicationContext(),R.layout.test, id.movie_title,listUsers);
lvUsers.setAdapter(adapter);
lvUsers.setOnItemClickListener(new OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
String product= ((TextView)view).getText().toString();
// String product= String.valueOf((TextView)findViewById(id.movie_title));
// Toast.makeText(getBaseContext(),product,Toast.LENGTH_LONG).show();
Intent x = new Intent(getApplicationContext(), SingleListItem.class);
// sending data to new activity
x.putExtra("product", product);
startActivity(x);
}
});
This code works fine, but I have attempted to style my row myself if you look at this line. (which is commented in the main view)
adapter = new ArrayAdapter<String>(getApplicationContext(),R.layout.test, id.movie_title,listUsers);.
Adding this threw the error of relativelayout cannot be cast to android widget textview on the line
String product= ((TextView)view).getText().toString();
So I took that to mean it does not know which textview I am referring to anymore. so I edited that line to
String product= String.valueOf((TextView)findViewById(id.movie_title));
because movie_title is the ID of the textview in the test layout.
The then disappeared but now when I click the row instead of getting that data I expected like row name and data from database. the textview in my second activity is displaying
"android.widget.TextView{176f155.v.Ed (more random numbers) app:id/movie_title}
(Some of the code from second activity
Intent i=getIntent();
String name = i.getStringExtra("product");
txtName.setText(name);
Like I said all these errors are occurring from me trying to implement my owned custom rows. So If anyone could point out where I went wrong while doing this I would be grateful .
Have you tried creating a custom adapter and making it extend ArrayAdapter ? You can do this easily and then inside your getView() of your custom adapter you can inflate your textview with your appropriate text . Check this : https://stackoverflow.com/a/8166802/1497188
Also String product= String.valueOf((TextView)findViewById(id.movie_title)); , this line is getting the ID of the view and not the text inside the view. The appropriate view to do it is that from inside your onItemClick() you would convert/cast your view into a textview and then do the getText().toString() on that view. Just Search online how to create custom adapters and onItemClick Listener for Adapter
EDIT:
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
String data=(String)adapterView.getItemAtPosition(arg2);
This will atleast help you get the string from inside your onItemClick()
Hi I currently have a Grid View, Which I Inserted an Array through an Adapter onto the Grid View.
I am using this method currently:
gridview.setOnItemClickListener(new OnItemClickListener() {
}
As demonstrated within the Android Documentation, Specifically I need to find the value set within the field of the grid that the user touch/clicked. Is this done through using the position variable within on item click e.g?
#Override
public void onItemClick(AdapterView<?> parent, View v,
int position, long id) {
// DO something
}
Or is it done manually ? Kind of at logger head's with this. Any help would be really appreciated.
You can try something like:
String value = (String)adapter.getItemAtPosition(position);
inside your onItemClick where adapter is the AdadpterView
The v argument in your onItemClick() method is a reference to the View that was clicked.
Simply cast that into a TextView and get the text:
String text = ((TextView)v).getText().toString();
i currently create an app that needs an custom listview. Everything with my listview is fine, but now i neet to know, how to set an onClickListener to an view, defined in my list_row.xml. i just want the onclicklistener on the whole item, and on this one inner view. I attach a picture to demonstrate my problem, because it is so hard to describe >.<
Picture (dropbox): https://www.dropbox.com/s/72xdxuwz47vl7s5/problem.png
I need a function that is called when clicking into the view [my Problem] indicates. its an ImageView filled with an image.
Here's something I've done before that seems pretty similar to what you want to accomplish.
First, you declare an onItemClickListener for your ListView. This will handle standard list item taps (that is, taps inside a list item but outside the inner view region that you're concerned about). You can do this in a variety of places in your code, but onCreate() is a common one.
Example:
mListView.setOnItemClickListener( new OnItemClickListener() {
#Override
public void onItemClick( AdapterView<?> parent, View view, int position, long id ) {
// Handle standard list item tap
// ...
}
} );
Then, you can just declare whatever onClickListeners you need for your inner view(s) inside your adapter's getView() method to handle click/tap events on your inner view.
Example:
#Override
public View getView( int position, View convertView, ViewGroup parent ) {
LinearLayout itemView;
// Inflate layout XML, etc.
// ...
// Find subviews in layout
ImageView innerView = (ImageView) itemView.findViewById( R.id.myInnerViewId );
// ...
// Set up onClickListener for inner view
innerView.setOnClickListener( new OnClickListener() {
#Override
public void onClick( View v ) {
// Handle inner view tap
// ...
}
} );
// ...
}
To set an OnClickListener in each row simply extend your current Adapter and override the getView() method. In there you can define specific listeners as you normally would.
This is discussed in great detail in this Google Talk by Romain Guy.
I have created a custom ArrayAdapter that fills a ListView. The data in the adapter is a list of POJOs which I get from a server. Each POJO has a unique id given by the server, I have no influence on that id. The id is only for internal use, means it isn't displayed to the user on the ListView.
My intention: if the user clicks an item in the list, I want to pass the id back to the server. The first step would be to create an onItemClickListener:
ListView lv = getListView();
lv.setOnItemClickListener(new OnItemClickListener() {
#Override
public void OnItemClick(AdapterView<?> parent, View view, int position, long id) {
// call the server in a new thread
// BUT: how do I get the POJO id from this position?
}
});
My problem is: I don't know how to obtain the id of the POJO. Since it is not displayed to the user, is is not in the TextView I get passed in the listener. The other parameters - position and id - do not seem to be what I need also. Description:
position: The position of the view in the adapter.
id: The row id of the item that was clicked.
I hope you got what I mean, otherwise tell me. Thank you!
the parent.getItemIdAtPosition(int position) will give you for pojo object at that index.
That would depend on how your adapter work. The id parameter will have a correspondence to one of the items the adapter is adapting. Based on that id, and how your adapter works, you can retrieve the original logical item that was represented by the view that was clicked.
#Override
public void OnItemClick(AdapterView<?> parent, View view, int position, long id) {
Object item = parent.getAdapter().getItem(position);
}