Arup Sarkar
Arup Sarkar

Reputation: 951

Button always null in onCreateView in a Fragment

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

Answers (4)

Arup Sarkar
Arup Sarkar

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

Renan Arceno
Renan Arceno

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

Androider
Androider

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

Vitaly Zinchenko
Vitaly Zinchenko

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

Related Questions