Reputation: 951
I have a cursor adapter mapped to a content provider fetching data from database and displaying it in a list view inside a fragment, all of it is working fine. Now, I need to place some buttons which will interact with a service.
Problem: The button is always returning null. Someone please let me know where I am doing wrong, but the same button click is working fine in Cursor Adapter.
fragment_track_player.xml
<RelativeLayout 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:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context="com.kavayah.spotifystreamer.TrackPlayerActivityFragment">
<!-- TODO: Update blank fragment layout -->
<ListView
android:id="@+id/listview_player"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:divider="#CFD8DC"
android:dividerHeight="1px">
</ListView>
</RelativeLayout>
list_item_track.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/artist_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:textColor="#3399FF"
android:textSize="10dp"
/>
<TextView
android:id="@+id/album_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/artist_name"
android:layout_centerHorizontal="true"
android:textColor="#3399FF"
android:textSize="10dp"
/>
<ImageView
android:id="@+id/album_icon"
android:layout_width="200dp"
android:layout_height="300dp"
android:layout_below="@+id/album_name"
android:layout_centerHorizontal="true"
/>
<TextView
android:id="@+id/track_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/album_icon"
android:layout_centerHorizontal="true"
android:textColor="#4D4D4D"
android:textSize="12dp"
/>
<TextView
android:id="@+id/duration_ms"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/track_name"
android:layout_centerHorizontal="true"
android:textColor="#4D4D4D"
android:textSize="12dp"
/>
<Button
android:id="@+id/media_play"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="14dp"
android:src="@android:drawable/ic_media_play"
android:layout_centerHorizontal="true" />
onCreateView in fragment, play_button is always null. I tried rootView.findViewById which was also returning null, since I believe it is not defined in fragment xml, but the mListView should find it? I am missing something here.
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
....
final View rootView = inflater.inflate(
R.layout.fragment_track_player, container, false);
mListView = (ListView) rootView.findViewById(R.id.listview_player);
mListView.setAdapter(mTrackPlayerAdapter);
Button play_button = (Button) mListView.findViewById(R.id.media_play);
play_button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (view != null) {
Log.i(LOG_TAG, ">>>>> fragment play button click.");
}
}
});
return rootView;
}
Upvotes: 3
Views: 901
Reputation: 951
After reading through the callback interface between fragment and activity, and going through other stack overflow postings here is how it is working for me what is not clear to me yet, is this thread safe ? but I find it a common design pattern for communication in android. Step 1: Created a callback interface inside the cursor adapter class.
...
//instance variable
Callback callback;
public interface Callback {
/* will communicate with fragment */
public void onItemSelected();
}
//constructor
public TrackPlayerAdapter(Context context, Cursor c,
int flags, Callback callback){
super(context, c, flags);
this.callback = callback;
}
final ImageButton play_button =
(ImageButton) view.findViewById(R.id.media_play);
play_button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (view != null) {
Log.i(LOG_TAG, ">>>>> play button click.");
callback.onItemSelected();
}
}
});
Fragment implements TrackPlayerAdapter.Callback
private static TrackPlayerAdapter mTrackPlayerAdapter;
mTrackPlayerAdapter = new TrackPlayerAdapter(getActivity(), cur, 0, this);
@Override
public void onItemSelected() {
Log.i(LOG_TAG, ">>>>> Response inside fragment.");
}
Upvotes: 0
Reputation: 600
You will need to set the listener in the method newView
and bindView
from your adapter class.
Like:
public class Adapter{
private MyFragment mFragment;
public Adapter(MyFragment mFragment){
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
//...
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
View view = inflater.inflate(R.layout.list_item_track, null);
view.findViewById(R.id.media_play).setOnClickListener(
new View.OnclickListener(){
public void onClick(View v) {
mFragment.executeWhatever();
}
});
return view;
}
}
Upvotes: 1
Reputation: 3873
You should inflate this layout "list_item_track.xml" to another view and then use findViewById() process as you done for example:
LayoutInflater inf = LayoutInflater.from(getContext());
View v = inf.inflate(R.layout.list_item_track.xml, null);
Button play_button=(Button) v.findViewById(R.id.txtLine2);
Try to use it in getView() of your ListView's ArrayAdapter OR BaseAdapter
Upvotes: 0
Reputation: 4911
You try to find button within view of your ListView, although there are no buttons. Instead you should call
Button play_button = (Button) yourListItem.findViewById(R.id.media_play);
where yourListItem is a reference to inflated view of your list item.
Upvotes: 0