I'm displaying some sql data in a list via a ListAdapter. Everything works fine except when I try to set a click listener to each item in the list. Nothing happens when I click any of the items; no error messages, it just silently fails.
public class Notes extends ListActivity implements OnClickListener {
private static final String TAG = "Notes";
private NotesData notes;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
notes = new NotesData(this);
try {
Cursor cursor = getNotes();
showNotes(cursor); /* set the cursor to the listadapter */
ListView ls = (ListView) findViewById(android.R.id.list);
ls.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent,View v,
int position,long id) {
Toast.makeText(getApplicationContext(),"clicked",
Toast.LENGTH_SHORT).show();
}
});
} finally {
notes.close();
}
}
main.xml, containing the listview:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<Button
android:id="#+id/new_note_button"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:text="#string/new_note"/>
<ListView
android:id="#android:id/list"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/empty"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="#string/empty"/>
</LinearLayout>
Is there something I'm missing?
Nothing is missing, your code is completely correct, just replace the getApplicationContext() to "this" could probably solve the problem, as what you need to pass is a reference to the context of the current component rather than the context of the current process.
Hope it helps.
Hass.
You need to add android:focusable="false" to the button you have in your main.xml file. The button is taking the focus away from the list item.
This is solve your problem for sure.
I guess your list item is set clickable. (view.setClickable(true))
onItemClick will to be called when the list item is clickable.
I'd recommend throwing something like this in your try statement
try{
//yourstuff
} catch (Exception e) {
e.printStackTrace();
}
And then check to see what error message is thrown. It's possible that it's throwing the error when it sets the onClickListener, maybe there's something invalid, but as long as all of that is in a try statement, it's not going to give you any helpful error message. So you could also just pull as much out of the try statement as possible until you find the problem. :-)
Related
I have a class extending RoboListFragment that uses a manager class to fetch some class' information (a Guest in my model). The problem I'm facing is when this manager fails to retrieve the data, I would like to dismiss the progress bar that is shown.
Here are the most important parts of my Fragment:
public class GuestFragment extends RoboListFragment {
// Lines omitted
private void loadGuest() {
Log.d(GuestFragment.class.getSimpleName(), "Loading guest...");
this.guestManager.getGuest(new Callback<Guest>() {
#Override
public void onSuccess(Guest guest) {
Log.d(GuestFragment.class.getSimpleName(), "Guest loaded OK");
GuestFragment.this.createAdapter(guest);
}
#Override
public void onFailure(UmError ex) {
// Here I want to dismiss the ProgressBar
Log.d(GuestFragment.class.getSimpleName(), "Guest failed");
GuestFragment.this.getListView().setEmptyView(new View(getActivity())); // This line wouldn't work
Toast.makeText(GuestFragment.this.getActivity(), "Error here!", Toast.LENGTH_LONG);
}
});
}
private void createAdapter(Guest guest) {
// Lines omitted
if (guestExists && activityWasCreated) {
ArrayAdapter adapter = new ProfilesAdapter(this.getActivity(), guest.getDeliveryProfiles());
this.setListAdapter(adapter);
}
}
}
EDIT #1: I tried adding this line in my onFailure() method
GuestFragment.this.getListView().setAdapter(null)
but didn't work.
EDIT #2: I also tried adding this in my onFailure() method
GuestFragment.this.getListView().setEmptyView(null);
didn't work either.
The XML is quite simple:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="#dimen/pLarge"
android:orientation="vertical"
tools:context=".fragment.GuestFragment">
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#id/android:list"
android:divider="#android:color/transparent"
android:dividerHeight="#dimen/fSmaller"/>
</LinearLayout>
As you can see, I'm not defining any ProgressBar at all. I've been told that this ProgressBar is shown by Android until the Adapter is set (I don't have further details), but I don't know how to set some empty content for the ListView
How could I achieve this, so that the ProgressBar hides when the Callback returns sucessfully?
Best regards.
I was making a stupid mistake :(
Instead of setting null to the List Adapter, like this (correct way):
GuestFragment.this.setListAdapter(null)
I was trying to get the ListView and set a null adapter, like this:
GuestFragment.this.getListView().setAdapter(null)
Thanks for your comments anyway!
I'm trying to use PullToRefreshListView instead my standard ListView however, it did not work for me as a beginner, the listView is using an adapter and inflating xml item file into the listview,
when i replaced my listview wih
</com.handmark.pulltorefresh.library.PullToRefreshListView>
the listview becomes empty, no items are loaded
onItemClickListener()
when i replace the listview from ListView to PullToRefreshListView, i don't get the getItemAtPosition option,
so how can i add an onItemClickListener() if i can't get the position?
list_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="vertical" >
<com.handmark.pulltorefresh.library.PullToRefreshListView
android:id="#+id/CarsList"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
my Activity.xml extends Activity
public class MainActivity extends Activity implements AsyncCallBack {
PullToRefreshListView myList;
CustomList cl;
....
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myList = (PullToRefreshListView) findViewById(R.id.CarsList);
...
That's the part of the code... getApiJsonArray is a listener which gets excuted on onPostExecute()
#Override
public JSONArray getApiJsonArray(JSONArray results) {
if (dialog != null) {
dialog.dismiss();
}
ArrayList<CarsItems> carsItems;
try {
carsItems = getCarsList(results);
cl = new CustomList(this, carsItems);
myList.setAdapter(cl);
myList.setOnItemClickListener(new OnItemClickListener() {
problem is in dimensions, the fill_parent is the problem, i check and it worked
By default when you copy and paste the pulltorefresh code into your project you get this :
<com.markupartist.android.widget.PullToRefreshListView
android:id="#+id/android:list"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
/>
i hesitated to ask someone on stackoverflow cuz i frustrated with importing it and updating the support version.....etc
however when you copy the code directly into your project you get a blank list or no list at all
simply change the height and width to something else like match_parent, this should be a straight forward answer for beginners like me.
and if you get a problem not finding the getItemAtPosition() for the setOnItemClickListener() method in the list try to call it inside that method (the setOnItemClickListener())
like that
#Override
public void onItemClick(AdapterView<?> a, View v, int position, long id) {
Object item = a.getItemAtPosition(position);
..
hope this will help beginners like me! :)
try to trace your code
Log.i("MyApp","Results = "+results.toString());
carsItems = getCarsList(results);
inside CustomList after you set the items inside the adapter add
notifyDataSetChanged(); <-- without this no elements will appear
I have a custom layout for my list view rows:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#drawable/listSelector"
android:orientation="horizontal">
<LinearLayout
android:id="#+id/checkboxSelection1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="3dip">
<CheckBox android:id="#+id/checkbox1" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#+id/checkbox1"
android:orientation="vertical">
<TextView
android:id="#+id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/text2"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</RelativeLayout>
I've also got an adapter to get the appropriate data to display; which it does. From the UI perspective, it looks like I want it to.
However, when I click a checkbox - nothing happens. I want to store a list of the items I've selected in the backend (in the activity class ideally).
In my onCreate in the activity class, I've got this code:
listView.setAdapter(adapter);
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
// Click event for single list row
listView.setOnItemClickListener(new OnItemClickListener()
{
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
int i = 1;
}
});
I've got the int 1 = 1; line there just so I could add a breakpoint to see if it gets hit. It doesn't. I'm sure I'm doing something wrong, like it's hooked up to the list view row instead of the checkbox or something - but I'm not sure how I can hook the event up to the checkbox.
If anyone could point me in the right direction I would appreciate it.
Thanks
Edit: JUST TO CLARIFY
I have this in the adapter:
taskChecked.setOnCheckedChangeListener(new OnCheckedChangeListener()
{
public void onCheckedChanged(CompoundButton arg0, boolean arg1)
{
// TODO Auto-generated method stub
int i = 1;
}
});
And that breakpoint does get hit. So I'm just trying to find out how I get have an event get raised in the activity, instead of just the adapter, when a checkbox is selected or unselected.
Don't do it!!! I almost went mad trying to get widgets in a ListView to respond to clicks. Do not put Button, ImageButton, or CheckBox widgets in a ListView. TextViews and ImageViews are the way to go. Trying to react to that click on that CheckBox to find what ListView item it is in and then send something to the Activity could be very harmful to your health. I tried.
TextView + ImageView that can vary between an icon showing a checkmark and one without - simulate a CheckBox;
ImageView by itself can simulate a Button.
The ImageView needs to be set to focus=false.
First, create a new class that has the fields you want to display for each item in the ListView. I made one with the text to display and a boolean that indicates whether it is checked or not. Use this class for your ArrayList and ArrayAdapter.
Then you add the setOnItemClickListener() for the ListView, then use the position to find the item view, and then get the item of your new class and toggle its boolean.
In the MyArrayAdapter.getView method, getItem(position) returns the instance of the new class for that item. Use the boolean to determine what icon to use for the ImageView.
When you need to know what is and isn't "checked" in the ListView, you just go through the ArrayList and check the boolean for each item.
I figured it out.
In the adapter I added this:
With _activity being the activity passed into the constructor from the calling activity. myObj is declared as a final earlier up in the code, based on the position in getView and the data passed in when the adapter was constructed.
taskChecked.setOnCheckedChangeListener(new OnCheckedChangeListener()
{
#Override
public void onCheckedChanged(CompoundButton button, boolean checked)
{
// Cast it so we can access the public functions
MyActivity myActivity = (MyActivity) _activity;
if (checked) // true if the checkbox is checked, false if unchecked
{
myActivity.checkboxSelected(myObj);
}
}
});
And in the activity I added this:
public void checkboxSelected(MyObj myObj)
{
// Do stuff with myObj here
}
Hopefully this helps someone.
I am trying to update a single row (two textviews) in a listview by changing the visibility of the second textview from "gone" to "visible".
Here is the XML for the custom layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/userlistlayout"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<TextView
android:id="#+id/textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Medium Text"
android:textAppearance="?android:attr/textAppearanceMedium" android:textColor="#000000"/>
<TextView
android:id="#+id/textView2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Medium Text"
android:textAppearance="?android:attr/textAppearanceMedium" android:visibility="gone"/>
I am using an arrayadapter to bind the data from a string[] to the listview. This is working perfectly. Where I am running into problems is pushing the change back to the screen.
Here is the test code I have for my array adapter and the attempt to set the visiblity on a single row's second textview.
searchResults = (ListView) findViewById(R.id.listView1);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,R.layout.userlist, R.id.textView1,names);
searchResults.setAdapter(adapter);
//all the code above this point works perfectly to populate the listview (textview1)
with the names passed in from the names string[]
LinearLayout hold = (LinearLayout) adapter.getView(2, null, null);
TextView hold2 = (TextView) hold.findViewById(R.id.textView2);
hold2.setVisibility(TextView.VISIBLE);
adapter.notifyDataSetChanged();
searchResults.invalidateViews();
This code does not throw any kind of error, however, i am not getting any kind of update on the listview. I am not sure what I am doing wrong or what step I am missing to get the visibility change made to hold2 to be pushed back into the adapter/listview and updated on the screen whereby the second textview on that particular row will be visible.
Once I get this working I want to trigger it onclick.
Any help would be much appreciated.
its pretty late but here is my answer ;
in your code , you are just doing refreshing in the oncreate , just once. but you have the listen for user for all the time , so you can do it
listview.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
final int position, long id) {
//here
}
});
now you can use adapter.notifyDataSetChanged(); in the on click .
but i think you should check these posts
this
that
also there is a different solution, we use animations
in the global of adapter
public View selectedView ,previousView ;
public Animation fadeIn , fadeOut;
in the adapter's getview
try {
if (previousView != v){
Animation b = AnimationUtils.loadAnimation(context, R.anim.fadein);
b.setDuration(177);
b.setFillAfter(true);
previousView.startAnimation(b);
previousView.findViewById(R.id.llTicketViewOnClickContainer).setVisibility(View.GONE);
}
} catch (Exception e) {
e.printStackTrace();
}
//..... some other code
//just before closing of get view
previousView =v
}
I'm having trouble with the setListAdapter(). It tells me to just create the method because it doesn't know anything about it. I'm, for now, just trying to get a list to populate and I don't even know what this code is doing.
public class PassScreen extends Activity {
TextView selection;
ArrayList<String> items = new ArrayList<String>();
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.passwordscreen);
selection=(TextView)findViewById(R.id.selection);
try {
InputStream in=getResources().openRawResource(R.raw.words);
DocumentBuilder builder=DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = builder.parse(in,null);
NodeList words=doc.getElementsByTagName("word");
for (int i =0;i<words.getLength();i++){
items.add(((Element)words.item(i)).getAttribute("value"));
}
in.close();
}
catch (Throwable t){
Toast.makeText(this, "Exception: " + t.toString(), 2000).show();
}
setListAdapter(new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1,
items));
}
public void onListItemClick(ListView parent, View v, int position, long id){
selection.setText(items.get(position).toString());
}
}
As you can see I have and xml file that I'm using. That looks just like what the book looks like but then again I copy and pasted the setListAdapter() so I guess that's not all that helpful.
If you could also show me what the setListAdapter() is doing that would be great. I can't seen to understand what google is talking about.
Here is the xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:id="#+id/selection"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
<ListView
android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:drawSelectorOnTop="false"/>
</LinearLayout>
And some of the words xml:
<words>
<word value="lorem"/>
<word value="ipsom"/>
<word value="dolor"/>
</words>
Also can you explain what's going on? I don't understand the setListAdapter() at all. Or just point to Googles white paper. I can't find it. It's not like I know how to look that stuff up anyway.
setListAdapter() isn't a method you can call on an Activity (it is available on ListActivity but you're not using that). You're going to have to add a ListView into your layout (/res/layout/passwordscreen) and then find it and call setAdapter on that.
e.g.
ListView lv = (ListView) findViewById(R.id.mylistview);
lv.setAdapter(.....);
Hey That's because of base class, your base class should be:
public class yourClassName extends ListActivity{
Not class yourClassName extends Activity{
When you call setListAdapter this must extend ListActivity probably you class just extends Activity.
I saw it on some other post and it works for me!!