PGMacDesign
PGMacDesign

Reputation: 6302

How can I access UI Elements of a fragment inside of a Custom Adapter From an Activity in Android

Good day all, I am working on an application where I have multiple Activities (Activities A, B, B) that inflate this fragment (TheListFragment).

This is a visual representation of what it looks like: ListView picture

Currently, I am able to change the descriptions, images, etc from the Fragment itself, but that is not what I would like to do. My goal is to have the respective activities all be able to change the fragment and use the fragment as a reusable listview. Here is some of my code:

public class TheListFragment extends Fragment {

    CustomAdapter.Holder holder;

    //The listview
    ListView listView;

    //When the view is created
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        //Inflate the add new game layout view
        View view = inflater.inflate(R.layout.list_view_holder, container, false);

        //Setup the listview and reference it to the listview id
        listView = (ListView) view.findViewById(R.id.data_list_view);

        //Set the custom adapter to the listview
        listView.setAdapter(new CustomAdapter(context);

        return view;
    }

    //This custom adapter is used to fill the respective data into the listview
    class CustomAdapter extends BaseAdapter {
        Context context;

        public CustomAdapter(Context context)) {
            this.context = context;
            inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        }

        @Override
        public int getCount() {
            return all_passed_data.size();
            //List of data. removed it for space purposes
        }

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

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

        //Holds the respective fields
        public class Holder {
            //UI Components
            TextView textview;
            ImageView imageView;

            LinearLayout linearLayout;
        }

        //Custom view
        public View getView(final int position, View convertView, ViewGroup parent) {

            //A holder object to reference the textviews and imageviews
            holder = new Holder();
            View rowView;
            rowView = inflater.inflate(R.layout.custom_list_view, null);

            holder.imageView = (ImageView) rowView.findViewById(R.id.custom_list_view_image);

            holder.textview = (TextView) rowView.findViewById(R.id.custom_list_view_game_name);

            holder.linearLayout = (LinearLayout) rowView.findViewById(R.id.left_layout);

            return rowView;
        }
    }
}

I am trying to set/ alter the listView contents (The holder class items) from within the activity that is inflating the fragment itself. IE, something along the lines of this:

public class ActivityA extends Activity{

    FragmentManager manager;
    ListFragment fragment;

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.list_fragment_holder);

        manager = getFragmentManager();

        ListFragment fragment = (ListFragment) manager.findFragmentById(R.id.the_list_fragment);

        //These will not work at the moment, they read as null pointers
        //This will be changed dynamically depending on the activity. Could be checkbox, imageview, etc.
        fragment.holder.linearLayout.addView(holder.checkBox); 

        fragment.holder.textview.setText("I Want to set the text here");    

        //Make it do something when clicked 
        fragment.holder.textview.setOnClickListener(this); 

        //Use third party library picasso to set the image
        fragment.Picasso.with(context).load("http://www.google.com/somepicture").into(holder.imageview); 

    }
}

But I am having no luck figuring out how to accomplish this. I have read through these links: Call fragment events from activity , Android: Reusing same View object in different Activities (the case is about ad banners) , How to access UI elements created by a List Adapter from an Activity? . Do I need to implement an interface that accesses the data somehow? If so, how? Or some other means I am missing?

Upvotes: 1

Views: 3398

Answers (1)

Gatunox
Gatunox

Reputation: 532

So here is the complete answer i think.

First let each class do its job. So Activity have Fragments and Fragments have adapters and adapters have Holders.

Create a abatract Fragment with the methods you need and then create concrete version of that fragments by making them extend the abstract one.

one of the methods in the abstract fragment should be i.e. public void doSomething();.

in the concrete version of your fragments (A B o C) tha implements the methods you do the actual "something" on the doSomething() method. in these framgents use some kind of colletion to hold the desired information (i use an arraylist). this is the actual data on the list, and holder will pupulate as needed to show on the screen. in you case lest assume that will be the text to put in the elements on the screen. This actually should be a class that represents the elemtens on the screen i.e. class GameItem that has all the elemtns that need to be shown, even the checkbox state. that represent a game.

Then in you adapter (custom adapter) you have to receive two paramenter the context and the arraylist (containg the array of text or to be 100% correct should receive the array of Games) from the holding activity. Also in this adapter create a public method called public void changeGameInfo(); is in method is where you change the content of the array you receive. The holder will acceess the element when you populate the list and grab the appropiate values to show on the screen.

In your class you create the instance of the fragment. at the correct time you call the method you create within the fragment, i.e.fregment.doSomething(); in the doSomething is where you call the adapter.changeGameInfo(); Since is the fragment that holds an instance of the Adapter. and since the adapter has a reference of the arraylist of games you passed as paramters i will know the elemetn that need to be show and that's it,

So as a resume Class XXXX calls fragment.doSomething(). In fragment.doSoemthing you call adapter.changeGameInfo() in the adapter you alter the desired game representation of the arraylist paseed as paramter. the viewholder just shows the elements, After you change the elemnts on the array list remember to call notifyDataSetChanged(); in the adpter so the actual values on the screen get updated automatically

look at examples of the viewholder patter

public class InteractiveArrayAdapter extends ArrayAdapter<Model> {

private final List<Model> list;
private final Activity context;

public InteractiveArrayAdapter(Activity context, List<Model> list) {
  super(context, R.layout.rowbuttonlayout, list);
  this.context = context;
  this.list = list;
}

static class ViewHolder {
  protected TextView text;
  protected CheckBox checkbox;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
  View view = null;
  if (convertView == null) {
    LayoutInflater inflator = context.getLayoutInflater();
    view = inflator.inflate(R.layout.rowbuttonlayout, null);
    final ViewHolder viewHolder = new ViewHolder();
    viewHolder.text = (TextView) view.findViewById(R.id.label);
    viewHolder.checkbox = (CheckBox) view.findViewById(R.id.check);
    viewHolder.checkbox
      .setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {

        @Override
        public void onCheckedChanged(CompoundButton buttonView,
            boolean isChecked) {
          Model element = (Model) viewHolder.checkbox
              .getTag();
          element.setSelected(buttonView.isChecked());

        }
      });
  view.setTag(viewHolder);
  viewHolder.checkbox.setTag(list.get(position));
} else {
  view = convertView;
  ((ViewHolder) view.getTag()).checkbox.setTag(list.get(position));
}
ViewHolder holder = (ViewHolder) view.getTag();
holder.text.setText(list.get(position).getName());
holder.checkbox.setChecked(list.get(position).isSelected());
return view;
}
} 

Upvotes: 2

Related Questions