1

EDITED:

PROBLEM: Im trying to show the details of an artist from my list to a fragment but i have an CustomAdapter im using so i dont know how to achieve this when my apps logic is like this:

  • ListViewAdapter.java --> MainFragment.java --> SongFragment.java (i have to go from adapter to one fragtment to another fragtment and this is causing me trouble)

Im trying to set the name of the artist, song name and image of the artist when i go to SongFragment.Java but my setOnItemClickListener is inside MainFragment.java.

Here is a demonstration on what to happen
Steps:

  1. Click on a song from the list (setOnItemClickListener) This is my customListView
  2. Open up SongFragment and show info about singer (artist, song name, image of the artist) This is my SongFragment after i clicked on a song

My ListViewAdapter code:

public class ListViewAdapter extends BaseAdapter {

//Create variables
MediaPlayer mediaPlayer;
int layout;
Song currentSong;
ArrayList<Song> arrayList;
Context context;

public ListViewAdapter(int layout, ArrayList<Song> arrayList, Context 
context) {
    this.layout = layout;
    this.arrayList = arrayList;
    this.context = context;
}

private class Viewholder {
    TextView artistTxt, songNameTxt;
    ImageView playB, stopB;
    CircleImageView artistImg;
}


@Override
public int getCount() {
    return arrayList.size();
}

@Override
public Object getItem(int position) {
    return null;
}

@Override
public long getItemId(int position) {
    return 0;
}

@Override
public View getView(int position, View view, ViewGroup parent) {

    final Viewholder viewholder;

    if (view == null) {
        viewholder = new Viewholder();

        LayoutInflater layoutInflater = (LayoutInflater)
        context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        view = layoutInflater.inflate(layout, null);

        viewholder.artistTxt = (TextView) view.findViewById(R.id.artistTxt);
        viewholder.songNameTxt = (TextView) 
        view.findViewById(R.id.songNameTxt);
        viewholder.playB = (ImageView) view.findViewById(R.id.playB);
        viewholder.stopB = (ImageView) view.findViewById(R.id.stopB);
        viewholder.artistImg = (CircleImageView) 
        view.findViewById(R.id.artistImg);

        view.setTag(viewholder);
    } else {
        viewholder = (Viewholder) view.getTag();
    }

    final Song song = arrayList.get(position);

    viewholder.artistImg.setImageResource(song.getArtistImg());
    viewholder.artistTxt.setText(song.getArtist());
    viewholder.songNameTxt.setText(song.getSongName());

    //get all songs
    mediaPlayer = MediaPlayer.create(context, song.getSong());

    viewholder.playB.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            if (currentSong == null) {
                mediaPlayer = MediaPlayer.create(context, song.getSong());
            }

            //if mediaplayer is not null and my current song is not equal to 
            //the new song i clicked on
            if (mediaPlayer != null && currentSong != song) {

                //resets the mediaplayer and creates a new song from the 
                //position in the list
                mediaPlayer.reset();

                mediaPlayer = MediaPlayer.create(context, song.getSong());
                viewholder.playB.setImageResource(R.drawable.play_black);

                mediaPlayer.start();
                viewholder.playB.setImageResource(R.drawable.pause_black);
            } else {
                mediaPlayer.pause();
                viewholder.playB.setImageResource(R.drawable.play_black);
            }

            //check if current song is null or the newly clicked song is 
            //equal to my current song
            //if true then assign the newly clicked song as my CURRENT one
            //--so it doesnt play the same song for every single one
            if (currentSong == null || song != currentSong) {
                currentSong = song;
            }
        }
    });

    //stop song
    viewholder.stopB.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            //stops my current song and make it null
            if (currentSong != null) {
                mediaPlayer.stop();
                mediaPlayer.release();

                currentSong = null;
                viewholder.playB.setImageResource(R.drawable.play_black);
            }
        }
    });
    return view;
}

My MainFragment.java where i add my songs to the list and call my adapter:

public class MainFragment extends Fragment {


//Declare variables
ArrayList<Song> arrayList;
ListView songListView;
ListViewAdapter adapter;
SongFragment songFragment;
FragmentManager fragmentManager;
FragmentTransaction fragmentTransaction;


@Nullable
@Override
public View onCreateView(@NonNull final LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_main, container, false);

    //Find my listview
    songListView = (ListView) view.findViewById(R.id.songListView);

    //create a new arraylist object
    arrayList = new ArrayList<>();

    //Add songs to my list
    arrayList.add(new Song("Beyonce", "-Formation", R.raw.beyonce_formation, R.drawable.beyonce));
    arrayList.add(new Song("Chris Brown", "-Hope You Do", R.raw.chrisbrown_hopeyoudo, R.drawable.chrisbrown));
    arrayList.add(new Song("Akon ft. Colby'O'Donis", "-Beautiful", R.raw.akon_beautiful_ft_colbyodonis_kardinaloffishall, R.drawable.akon));
    arrayList.add(new Song("Akon", "-Beautiful", R.raw.akon_dontmatter, R.drawable.akon));
    arrayList.add(new Song("Akon", "-Locked Up", R.raw.akon_lockedup_ft_stylesp, R.drawable.akon));
    arrayList.add(new Song("Ava Max", "-Sweet but Psycho", R.raw.avamax_sweetbutpsycho, R.drawable.avamax));
    arrayList.add(new Song("Tupac and Biggie ft. Akon Remix", "-Ghetto", R.raw.tupacbiggieakon_ghetto, R.drawable.biggie));

    //Create a new adapter of my custom adapter and assign its values
    adapter = new ListViewAdapter(R.layout.listview_customlayout, arrayList, getActivity());

    //Set my listview to my custom adapter
    songListView.setAdapter(adapter);

    //Click on a specific song from my list
    songListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            //Initiliaze my songFragment to my fragment class
            songFragment = new SongFragment();

            //call FragmentManager and begin the transaction to my songFragment class
            fragmentManager = getFragmentManager();
            fragmentTransaction = fragmentManager.beginTransaction();

            //When clicked on a listview item - navigate to songfragment and when clicked back -> go back to mainfragment
            //save my mainfragment to my stack so it isnt destroyed but kept safe so i can get back to it
            fragmentTransaction.replace(R.id.fragment_container, songFragment).addToBackStack(null).commit();

        }
    });
    //return my view
    return view;
}

} My customListView.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white">

<de.hdodenhof.circleimageview.CircleImageView
    android:id="@+id/artistImg"
    android:layout_width="50sp"
    android:layout_height="50sp"
    android:src="@drawable/musiclogo"
    app:civ_border_color="@color/white"
    app:civ_border_width="2dp" />

<TextView
    android:id="@+id/artistTxt"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_toRightOf="@id/artistImg"
    android:text="Artist"
    android:textColor="@color/black"
    android:textSize="15sp"
    android:textStyle="bold" />

<TextView
    android:id="@+id/songNameTxt"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@id/artistTxt"
    android:layout_toRightOf="@id/artistImg"
    android:text="Song Name"
    android:textColor="#11ca6b" />

<ImageView
    android:id="@+id/playB"
    android:layout_width="30sp"
    android:layout_height="30sp"
    android:layout_marginTop="4sp"
    android:layout_toLeftOf="@id/stopB"
    android:src="@drawable/play_black" />

<ImageView
    android:id="@+id/stopB"
    android:layout_width="30sp"
    android:layout_height="30sp"
    android:layout_alignParentRight="true"
    android:layout_marginTop="4sp"
    android:src="@drawable/stop_black" />

</RelativeLayout>

My fragment_song.xml layout:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/constrainLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">


<ImageView
    android:id="@id/artistImg"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:alpha="0.4"
    android:background="@color/black"
    android:scaleType="centerCrop"
    android:src="@drawable/edsher" />

<de.hdodenhof.circleimageview.CircleImageView
    android:id="@id/artistImg"
    android:layout_width="250sp"
    android:layout_height="250sp"
    android:layout_alignParentTop="true"
    android:layout_centerHorizontal="true"
    android:layout_marginTop="75sp"
    android:src="@drawable/edsher"
    app:civ_border_color="@color/white"
    app:civ_border_width="2sp" />

<TextView
    android:id="@id/songNameTxt"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@id/artistImg"
    android:layout_centerInParent="true"
    android:layout_marginTop="10sp"
    android:text="Song name" />

<TextView
    android:id="@+id/currentSongLenght"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@id/songNameTxt"
    android:layout_marginTop="9sp"
    android:layout_toLeftOf="@id/songLenght"
    android:text="03:00" />

<TextView
    android:id="@+id/currentSongLeft"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@id/songNameTxt"
    android:layout_marginTop="9sp"
    android:layout_toRightOf="@id/songLenght"
    android:text="-02:20" />

<SeekBar
    android:id="@+id/songLenght"
    android:layout_width="300sp"
    android:layout_height="wrap_content"
    android:layout_below="@id/songNameTxt"
    android:layout_centerInParent="true"
    android:layout_marginTop="10sp" />


<ImageView
    android:id="@+id/previousB"
    android:layout_width="60dp"
    android:layout_height="60dp"
    android:layout_below="@id/songLenght"
    android:layout_toLeftOf="@id/playB"
    android:src="@drawable/previous" />

<ImageView
    android:id="@id/playB"
    android:layout_width="70sp"
    android:layout_height="70sp"
    android:layout_below="@id/songLenght"
    android:layout_centerInParent="true"
    android:src="@drawable/play_big" />

<ImageView
    android:id="@+id/nextB"
    android:layout_width="60sp"
    android:layout_height="60sp"
    android:layout_below="@id/songLenght"
    android:layout_toRightOf="@id/playB"
    android:src="@drawable/next" />

<ImageView
    android:id="@+id/favoriteB"
    android:layout_width="40sp"
    android:layout_height="40sp"
    android:layout_below="@id/songLenght"
    android:layout_alignParentEnd="true"
    android:layout_marginTop="10sp"
    android:src="@drawable/favorite" />

</RelativeLayout>
Delice
  • 743
  • 9
  • 20

2 Answers2

1

One easy way is to simply pass your data as arguments to the fragment:

Bundle arguments = new Bundle();
// Set your data in the arguments
// For example: arguments.putString("song_title", item.getSongName())
// And you can get the name by calling getArguments() in SongFragment
Fragment songFragment = new SongFragment();
songFragmnet.setArguments(arguments);

Just in case if you're having clicking issue, in a ListView, whenever an item view is being clicked, it will perform View.hasExplicitFocusable on the view, so if there is any clickable view on your item view, then you will not receive callback in onItemClick. So you may need to find another workaround to attach click listener.

Aaron
  • 3,764
  • 2
  • 8
  • 25
  • I think the problem is HOW to send all my items in a bundle from my adapter through my `MainFragment ` (where i have my `onItemClickListener`) to my `SongFragment `where the bundle has to open and set the right properties the right places. How do i achieve this? – Delice Nov 23 '18 at 16:04
1

You would make your Song Serializable: class Song implements Serializable{

And then pass the class in your bundle.

Bundle bundle = new Bundle();
bundle.putSerializable("song", song);
songFragment.setArguments(bundle);

In your SongFragment you should get the arguments:

public class SongFragment extends Fragment {
@Nullable
@Override
public View onCreateView( /* .... */){

Song song = getArguments().getSerializable("song");

}

}

If you don't want to use arguments (I would use arguments definitively) I would create a method in my SongFragment which will receive all the data I need and I would call it in my the mainFragment using the SongFragment instance.

Something like this:

public class SongFragment extends Fragment {

String artist;
String song;
int name;
int image;
TextView nameText, artistText;
/* all my code .... */
@Nullable
@Override
public View onCreateView(@NonNull final LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
   View view = inflater.inflate(R.layout.fragment_main, container, false);
   nameText = view.findByViewId(R.id.my_name_id);
   artistText = view.findByViewId(R.id.my_artist_id);

}
public getSongData(String artist, String song, int name, int image){
   this.artist = artist;
   this.song = song;
   this.name = name;
   this.image = image;

   nameText.setText(name);
   artistText.setText(artist);
}

}

in MainFragment in your songListView.setOnItemClickListener:

songListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

        songFragment = new SongFragment();
       // -----> HERE <-----
        songFragment.getSongData(song.getArtist(), song.getSongName(), song.getName(), song.getArtistImg());
       // -----> HERE <-----

        fragmentManager = getFragmentManager();
        fragmentTransaction = fragmentManager.beginTransaction();


        fragmentTransaction.replace(R.id.fragment_container, songFragment).addToBackStack(null).commit();

    }
});
Alberto Crespo
  • 2,429
  • 5
  • 28
  • 51
  • That almost worked! There is just 1 thing i didnt catch. How do i set the values i get from the method to my TextViews? `getSongDetails(artist, songName, artistImg, song);` <--- this **DIDNT** work inside my `SongFragment` – Delice Nov 23 '18 at 18:21
  • 1
    Try to do as I edited above. If it doesn't work (I think it works always) you should make your TextView as global variables and `setText`inside the `getSongData()`. I am going to edit it on more time in order to show you how. – Alberto Crespo Nov 23 '18 at 18:30
  • Thanks it worked! Now i can get the artist name, song name and the image of the artist in my new fragment! I have one more question tho: what if i want to play the song inside my SongFragment instead of playing it from my list view (screenshot posted (1))? How do i access all the mediaplayer features i have in my Adapter to inside of my SongFragment (where i have a play button)? – Delice Nov 23 '18 at 18:53
  • 1
    You could instanciate first in your MainFragment, pass it through the `ListView` constructor and then pass it again to the `SongFragment` using the `getDataSong` method. I think it should work – Alberto Crespo Nov 23 '18 at 19:22
  • You are welcome! It will be fair if you vote up all my comments ;) – Alberto Crespo Nov 23 '18 at 21:42
  • 1
    Trust me i tried few times.. no luck. Im still newbie here :( – Delice Nov 24 '18 at 18:36