Android Studio Master Detail List onClick not working - android

I am new to android development so may be i am missing something elementary here, but after almost 2 days of googling I am still unable to figure out the cause.
I have followed the following article to create my project, except that I am invoking this activity from another activity when a button is clicked.
I have also created my own List adopter public class MyListAdapter extends ArrayAdapter<MyData> and in the getView() method of this adapter I am actually providing a different representation like below.
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.my_list_view, parent, false);
}
this all works fine I am able to bind the data and its displaying the results on the list without any issues. Now I want to show the details of selected MyData when the user clicks on the list item, but this is just not working no matter what I try.
I have ensured that my activity is implementing the callback interface like below:
public class MyItemListActivity extends FragmentActivity
implements MyItemListFragment.Callbacks
and the callback itself is also very simple:
public interface Callbacks {
public void onItemSelected(MyData item);
}
also on my MyItemListFragment the onAttched is correctly hooked up mCallbacks = (Callbacks) activity;
What I really notice is that the following function is just not called when I click on the list item:
#Override
public void onListItemClick(ListView listView, View view, int position, long id) {
super.onListItemClick(listView, view, position, id);
MyData data = DataContent.ITEMS.get(position);
// Notify the active callbacks interface (the activity, if the
// fragment is attached to one) that an item has been selected.
mCallbacks.onItemSelected(data);
}
my fragment that displays the list item looks like this:
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/myitem_list"
android:name="path.MyItemListFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
tools:context="path.MyItemListActivity"
tools:layout="#android:layout/list_content" />
and the actual custom adapter view my_list_view looks like below:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >....</RelativeLayout>
I can see that its missing the android:onClick tag here, but not sure if that is the cause and also who needs to implement this handler as there is no direct context on this layout.
Any help is really appreciated.
Regards
Kiran

Related

How to categorize list items in a recyclerview?

I am building a notifications list for an application I'm working on and I'm having trouble finding a way to take my list of notifications from the server and displaying them in separate lists in a RecyclerView. The end product would display the list of notifications with headers for Recent notifications and Older notifications, a la:
<RECENT HEADER>
<NOTIF-1>
<NOTIF-2>
<OLDER HEADER>
<NOTIF-3>
<NOTIF-4>
<NOTIF-5>
<NOTIF-6>
except instead of angle-bracket text it's actual views representing those, complete with images, actual notification details and dividers.
I already have code that displays them in a RecyclerView:
XML:
<!-- Main layout -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="#layout/include_toolbar"/>
<RelativeLayout
android:id="#+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/notification_swipe_refresh"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.mapjungle.mymoose.ui.widget.EmptyRecyclerView
android:id="#+id/notification_list"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</android.support.v4.widget.SwipeRefreshLayout>
</RelativeLayout>
</LinearLayout>
Java:
#InjectView(R.id.notification_list) RecyclerView mRecyclerView;
#Inject Picasso mPicasso;
#Inject NotificationService mUserService;
private NotificationAdapter mAdatper;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_notifications);
ButterKnife.inject(this);
setTitle("Notifications");
mAdatper = new NotificationAdapter(mPicasso);
mRecyclerView.addItemDecoration(new HorizontalDividerItemDecoration.Builder(this)
.color(getResources().getColor(R.color.secondary_color))
.size(1)
.build());
final LinearLayoutManager layoutManager = new LinearLayoutManager(this);
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
mRecyclerView.setLayoutManager(layoutManager);
mRecyclerView.setAdapter(mAdatper);
updateList();
}
#Override
protected int getSelfNavDrawerItem() {
return NAVDRAWER_ITEM_PHOTO_POST;
}
public void updateList() {
mUserService.getNotifications(new Callback<List<Notification>>() {
#Override
public void success(List<Notification> notificationList, Response response) {
mAdatper.replaceWith(notificationList);
}
#Override
public void failure(RetrofitError error) {
Timber.e(error, "Failed to load notifications...");
}
});
}
This all works fine enough to display all of the notifications and they're all sorted in the order from newest to oldest descending. But each has a boolean property "acknowledged" that is set to false if the user hasn't seen them before. I want to put split the list into the two groups I've explained above using this flag, but I don't know how to throw in the headers. I've thought about subclassing Notification to create NotificationHeader views and inserting them into the list where appropriate but that just feels sloppy to me. I've also thought about doing two recycler views, one for the new and another for the old, but visually that didn't work the way I intended (I haven't confirmed it but it looked like each recycler view scrolled independently of the others, something that I do not want). Any suggestions?
I know that the first idea of creating special Notification Headers will probably work, I've done something like that before, but it just feels like bad practice.
RecyclerView.Adapter has a method called getItemViewType() that takes the position of an item in the adapter's list, and returns the view type it should use. In my case, the method looks like this:
#Override
public int getItemViewType(int position){
Notification n = mNotifications.get(position);
boolean useHeader = n.getType().equals(Notification.HEADER_OLDER) ||
n.getType().equals(Notification.HEADER_RECENT);
return useHeader ? this.USE_HEADER : this.DONT_USE_HEADER;
}
Which checks the items in the notification list and sees if they're a special static 'Header notification' object. This is used internally by the Adapter class and it passes the 'viewType' parameter to the onCreateViewHolder() method, which we also override:
#Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
int layout = viewType == USE_HEADER ?
R.layout.view_item_notification_header :
R.layout.view_item_notification;
NotificationItemView view = (NotificationItemView) LayoutInflater.from(viewGroup.getContext())
.inflate(layout, viewGroup, false);
return new ViewHolder(view);
}
Overriding this method allows us to use the viewType parameter to choose the appropriate layout to inflate for the ViewHolder.
There are some better style/good practice decisions things I should have done here, such as making my Notification adapter hold a list of NotificationListItems instead of Notifications, which would allow me to put in a new kind of NotificationHeader object on it's own instead of making Notification objects that weren't really Notifications and using a bunch of constant values. But the underlying principle is still there:
In your Model, have a method that returns the layout view to use for it
In your adapter override getItemViewType() to use the aforementioned method and return an int that corresponds to the layout that should be inflated
In your adapter also override onCreateViewHolder() to use the int from getItemViewType() and inflate the appropriate view accordingly

onListItemClick doesn't work

So, my onListItemClick is not working for some reason. I use the same code structure in another activity and that one is working perfectly. And when I try to implement the same method here, it just doesn't work at all. The Toast doesn't work. And the intent to detailactivity also doesn't work. I'm sure my naming and labeling is fine. The list items doesn't even feel like they are clickable. Can someone help me out here, please?
public class MainActivity extends ListActivity {
String objectId;
protected List<ParseObject> mInfo;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_info);
//**** There is a bunch of code here that takes import the list view from an adapter. I believe they are working fine. ***//
}
//**** this part below is not working. This is the section where if you click on the list item, it brings you to the detailactivity.
#Override
protected void onListItemClick(ListView l,View v, int position, long id){
super.onListItemClick(l, v, position, id);
ParseObject infoObject = mInfo.get(position);
String objectId = infoObject.getObjectId();
Toast.makeText(getApplicationContext(),objectId, Toast.LENGTH_SHORT).show();
Intent Details = new Intent(MainActivity.this, DetailsActivity.class);
Details.putExtra("objectId", objectId);
startActivity(Details);
}
İf you use a custom adapter to fill listview and involve clickable components such as Button, İmageView. onListItemClick will don't work because it won't be able to decide which component will be listened. solution is "android:focusable:"false"" keyword. thanks to this, Listener will only focus items which are populated custom adapter by you.
Like this:
<Button
android:focusable="false"
android:layout_width="match_parent"
android:layout_height="4dp"
android:background="colorCode"
/>
I have used this button to seperate each list view items. But it caused your problem. I think if you will list items, You shouldnt use clicable components in
template xml.
Happy Coding..
Vd.
Please implement the onListItemClickListener
public class MainActivity extends ListActivity implements OnItemClickListener{
//code code code
}
Then when you set the onItemCLick use
setOnItemClickListener(this);
I found an answer to solve this by adding android:focusable="false" inside of the the views in the listview/customlayout that will be imported to the activity. I got the answer from this link:
onListItemClick is not working for listview?

Click event from checkbox in custom listview in Android

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.

Android List Refresh

I'm working on refreshing a list in Android but can't seem to get it right.
I've used notifyDataSetChanged(); at every point that I thought applicable (currently using dialogs for input), but it doesn't work, and I've got to the point of plastering it around all over the place and it still won't refresh.
Am I right in saying this should refresh the list while your looking at it, or it will rebuild the list and you still have to refresh the view?
If anyone has got any suggestions for the positioning of it in relation to constructing a list I'd be glad to hear.
Is this a ListActivity? I have a ListActivity in my project at the moment and I have my own adapter class within it that extends ArrayAdapter.
My experience is that calling notifyDataSetChanged() on my extended list adapter class instance does immediately cause a refresh of the list View being displayed. So, as soon as I call .notifyDataSetChanged() on my adapter instance, the list View is regenerated which therefore causes my adapter's implementation of getView() to be called to generate each individual row view again. So, the user selects a context menu item which triggers some change to the data and then a call to .notifyDataSetChanged(), and the screen instantly refreshes with the new data.
So to add some code snippets to be clear:
I have a ListActivity
public class VarListActivity extends ListActivity {
Within it, I extend ArrayAdapter
class VarAdapter extends ArrayAdapter{
...
#Override
public View getView(int position, View convertView, ViewGroup parent){
// Creates the views based upon myData
...
#Override
public int getCount(){
...
And I create an instance of that array adapter
la = new VarAdapter(this, R.layout.row0);
And when a context menu item is selected
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.a_context_menu_option:
// Does a call to perform modifications to myData
la.notifyDataSetChanged();
return true;
I'm just chucking this all down just in case it's of any similarity to your situation, but really we need to know a bit more about your code.

Making a list view like the favorite tab on native dialer in android

I am making an android application that shows a list with users, I would like to add the image,name,status,and a button in every row of the list, just like in the androids 1.6 native caller-> favorites tab.Until know I have managed to add the image and name using an ListActivity but when I try to add the button the list becomes unselected.So I have 2 questions, first is the list mentioned above listviews or listactivities? also is this possible using listActivity? and second, what is the difference of the above mentioned classes? any link to tutorials would be appreciated.
You will need to extend ListActivity and ListAdapter to implement your design. The activity that displays your list should extend ListActivity instead of Activity. In the onCreate method of your ListActiviry, the content view of your activity should be set to a linear layout that is the parent of a listview. The list view must have id "#+id/android:list". You can also include a textview to be displayed when the list is empty, see below. Also in OnCreate call setListAdapter() and pass in a new object of your that extends ListAdapter.
In the class that you make that extends ListAdapter, override all of the methods that you need to, especially getView().
Example code:
MyListActivity.java
import android.app.ListActivity;
public class MyListActivity extends ListActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_list);
setListAdapter(new MyListAdapter());
}
}
my_list.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">
<ListView android:id="#+id/android:list"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<TextView android:id="#+id/android:empty"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
     android:text="No Events!"/>
</LinearLayout>
MyListAdapter.java
import android.widget.ListAdapter;
public class MyListAdapter implements ListAdapter {
//Methods to load your data
public View getView(int arg0, View reuse, ViewGroup parent) {
//Create the view or if reuse is not null then reuse it.
//Add whatever kind of widgets you want here and return the view object
}
}

Categories

Resources