7

Alright so i have a list(which is also a fragment dialog) that displays a users friends and each item in that list has a button(labeled friends in the picture) and when users click that button id like to display another fragment dialog that displays all the options for interacting with that user(friend request, block, send private message ect...) the problem is that this button and its onClick listener are currently implemented via overriding my listview adapters getView method and to create a fragmentDialog requires access to fragment manager. is there a way to make this work?

EDIT: I cannot post actual code from the project , but ive attached a simplified base adapter w. onClickListener that should make it clear what im trying to do . I cannot access the fragmentManager from a base adapter class to make the dialog fragment possible

LazyAdapter.java
package com.example.androidhive;

import java.util.ArrayList;
import java.util.HashMap;

import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class LazyAdapter extends BaseAdapter {

    private Activity activity;
    private ArrayList<HashMap<String, String>> data;
    private static LayoutInflater inflater=null;
    public ImageLoader imageLoader;

    public LazyAdapter(Activity a, ArrayList<HashMap<String, String>> d) {
        activity = a;
        data=d;
        inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        imageLoader=new ImageLoader(activity.getApplicationContext());
    }

    public int getCount() {
        return data.size();
    }

    public Object getItem(int position) {
        return position;
    }

    public long getItemId(int position) {
        return position;
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        View vi=convertView;
        if(convertView==null)
            vi = inflater.inflate(R.layout.list_row, null);
         Button requestBtn = (Button)vi.findViewById(R.id.title); // title

        HashMap<String, String> song = new HashMap<String, String>();
        song = data.get(position);

        // Setting all values in listview
        title.setText(song.get(CustomizedListView.KEY_TITLE));
        artist.setText(song.get(CustomizedListView.KEY_ARTIST));
        duration.setText(song.get(CustomizedListView.KEY_DURATION));
        imageLoader.DisplayImage(song.get(CustomizedListView.KEY_THUMB_URL), thumb_image);

        requestBtn.setOnClickListener(new myOnClickListener(position));
        return vi;
    }

        public class myOnClickListener implements OnClickListener{
     private int position;
  private String clicked_uid;
  public myOnClickListener(int position){
      this.position=position;
     }
  @Override
  public void onClick(View v) {


    //THIS IS WHERE IM TRYING TO PUT THE FRAGMENT DIALOG

        FragmentManager fm = TabHostFragmentActivity.this.getSupportFragmentManager();
        FriendsFamiliarsDialog friendsDialog = new FriendsFamiliarsDialog().newInstance(TabHostFragmentActivity.profile_uid,"friends");
        friendsDialog.show(fm, "friendsdialog");





  }

    }
}

listview fragment dialog getView android

ChuckKelly
  • 1,742
  • 5
  • 25
  • 54

4 Answers4

22

I also struggled to access the Fragment Manager from an adapter in order to display a DialogFragment. Here is the solution in code:

public class YourPagerAdapter extends PagerAdapter{

   private Context context;

   public YourPagerAdapter(Context c) {
          this.context = c;
   }

   @Override
      public void onClick(View v) {
            FragmentActivity activity = (FragmentActivity)(context);
            FragmentManager fm = activity.getSupportFragmentManager();
            YourDialogFragment alertDialog = new YourDialogFragment();
            alertDialog.show(fm, "fragment_alert");
      }
}

The trick is that you receive the activity as context and you simply cast it to ensure it is a FragmentActivity - which is what the manager needs. This works because when you call YourPagerAdapter in your higher level file you pass the activity into it:

pagerAdapter = new YourPagerAdapter(getActivity());
yourViewPager.setAdapter(pagerAdapter);
lsiq
  • 331
  • 2
  • 4
1

I was trying to open a dialogfragment from a button located in a custom listview for an app that shows a list of events. I solved this by changing my adapter constructor.

In my adapter class:

public class EventAdapter extends BaseAdapter {

private Context context;
private ArrayList <Event> mEvents;
private FragmentManager fm;

public EventAdapter(Context context, ArrayList<Event> events, FragmentManager fm) {
    this.context = context;
    this.fm = fm;
    mEvents = events;
}

then I was able to do this:

        holder.saveButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            SignupFragment signupFragment = new SignupFragment();
            signupFragment.show(fm, "Sample Fragment");
            Log.i(TAG, "click on save button");
        }
    });

And i changed my adapter call in my higher up activity (AllEventsActivity):

    FragmentManager fm = getFragmentManager();
    mAdapter = new EventAdapter(this, mEvents, fm);
perrysetgo
  • 73
  • 1
  • 10
0

When you create LazyAdapter pass in the view for which adapter is created or the parent fragment or ACtivity, and then in onclick method use this to call a function on your fragment or activity to show the dialog fragment, remember that from adapter class you should only be sending message through function calls to UI components to do something interesting like showing dialog fragments

Pulkit Sethi
  • 1,325
  • 1
  • 14
  • 22
  • in my actual base adapter i do pass in context , but context alone cannot be used to access a fragment manager for some reason , can you post a example of ur solution? I think ull find the same problem as me – ChuckKelly Aug 26 '13 at 04:48
  • Instead of passing in the context, pass your activity. lets say your classs id TestActivity pass this to constructor of adapter class. and inside the onclick method do mTestActivity.ShowDialogFragment(string data1, string data2); – Pulkit Sethi Aug 26 '13 at 05:14
  • I figured it out about 2 mins after i responded ,but i did so via passing in a fragment manager in my base adapters constructor which worked....is there any advantages of passing the actual dialog fragment in the constructor instead of the fragment manager? – ChuckKelly Aug 26 '13 at 05:31
  • You should not pass fragment manager as its connected to Activity thats y i wrote pass in the activity and call activity method (myactivity.showfragment), keep UI stuff in UI classes, this is just a better design incase you need to upgrade your stuff – Pulkit Sethi Aug 26 '13 at 05:44
0

For Kotlin (current version 1.8.0), I had to pass the appropriate FragmentManager object from the Fragment class to the associated Adapter class. In the onBindViewHolder() method, I retrieved the desired Fragment from the fragments method of the passed FragmentManager object, which returns a list of Fragments managed by that FragmentManager object.

class StockRecyclerViewAdapter(private val fragmentManager: FragmentManager) :
    RecyclerView.Adapter<StockHistoryItemViewHolder>() {
/*
.
....more code 
.
*/
override fun onBindViewHolder(holder: StockHistoryItemViewHolder, position: Int) {
val stockHomeFragment = fragmentManager.fragments[0]
/*
.
...some more code
.
*/

stockHomeFragment.findNavController().navigate(FragmentDirectionsObject)

To understand the appropriate FragmentManager object to use, study the FragmentManager docs in the official Android Developer documentation here. Its a long read but worth the hassle. Happy coding!

Mwanagenzi
  • 136
  • 1
  • 6