Home > Back-end >  How Do I Pass Data Between Two Fragments On The Same Activity?
How Do I Pass Data Between Two Fragments On The Same Activity?

Time:09-03

enter image description here

Howdy, I'm working on a project and I'm running into some issues. Namely, I have two fragments, each with their own adapter as both fragments are meant to be able to swipe horizontally. A photo should be attached of the layout I have for further clarity. I would like to be able to tap the bottom fragment, which when I tap a place on the top fragment, the image I tapped or "Structure" will be placed down. However, what I can't figure out is how to smoothly transfer this data and if I were to do it through the activity, how do I do it as the activity has already run through all its code. Could somebody please help, it would be greatly appreciated.

Main Activity

public class MainMap extends AppCompatActivity
{
    MapData data = MapData.get();
    StructureData structure = StructureData.get();

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_map);

        FragmentManager frag = getSupportFragmentManager();    //To manage the map fragment
        MapCellFragment rv = (MapCellFragment) frag.findFragmentById(R.id.map);

        FragmentManager selectionFrag = getSupportFragmentManager();    //To manage the selection fragment
        SelectionCellFragment cf = (SelectionCellFragment) selectionFrag.findFragmentById(R.id.bar);

        if (rv == null)
        {
            rv = new MapCellFragment(data);
            frag.beginTransaction().add(R.id.map, rv).commit();
        }

        if (cf == null)
        {
            cf = new SelectionCellFragment(structure);
            selectionFrag.beginTransaction().add(R.id.bar, cf).commit();
        }
        
    }

Map Fragment

    public MapData data;

    public MapCellFragment() {
        // Required empty public constructor
    }

    public MapCellFragment(MapData data)
    {
        this.data = data;
    }

    /**
     * Use this factory method to create a new instance of
     * this fragment using the provided parameters.
     *
     * @param param1 Parameter 1.
     * @param param2 Parameter 2.
     * @return A new instance of fragment gridCellFragment.
     */
    // TODO: Rename and change types and number of parameters
    public static MapCellFragment newInstance(String param1, String param2) {
        MapCellFragment fragment = new MapCellFragment();
        Bundle args = new Bundle();
        args.putString(ARG_PARAM1, param1);
        args.putString(ARG_PARAM2, param2);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mParam1 = getArguments().getString(ARG_PARAM1);
            mParam2 = getArguments().getString(ARG_PARAM2);
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.map_fragment, container, false);
        RecyclerView rv = (RecyclerView) view.findViewById(R.id.recyclerview);
        rv.setLayoutManager(new GridLayoutManager(getActivity(), MapData.HEIGHT, GridLayoutManager.HORIZONTAL,false));
        MapAdapter myAdapter = new MapAdapter(data);
        rv.setAdapter(myAdapter);
        return view;
    }

Bottom Bar Fragment This was essentially a copy and paste of the other fragment, just changing the data which goes in and the XML it's attached to.

Map Adapter

package com.example.map;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class MapAdapter extends RecyclerView.Adapter<MapViewHolder>
{
    MapData data;

    public MapAdapter(MapData data)
    {
        this.data = data;
    }

    @NonNull
    @Override
    public MapViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType)
    {
        LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
        View view = layoutInflater.inflate(R.layout.grid_cells,parent,false);

        //Resizes the images within the grid cells xml file
        int size = parent.getMeasuredHeight() / MapData.HEIGHT   1;
        ViewGroup.LayoutParams lp = view.getLayoutParams();
        lp.width = size;
        lp.height = size;

        MapViewHolder myViewHolder = new MapViewHolder(view);
        return myViewHolder;
    }

    @Override
    public void onBindViewHolder(@NonNull MapViewHolder holder, int position)
    {
        int row = position % MapData.HEIGHT;
        int col = position / MapData.HEIGHT;

        MapElement ele = data.get(row, col);

        holder.ne.setImageResource(ele.getNorthEast());
        holder.nw.setImageResource(ele.getNorthWest());
        holder.se.setImageResource(ele.getSouthEast());
        holder.sw.setImageResource(ele.getSouthWest());

        if(ele.getStructure() != null)
        {
            holder.mapStruct.setImageResource(ele.getStructure().getDrawableId());
        }

    }

    @Override
    public int getItemCount()
    {
        return 300;
    }

}

Map View Holder

package com.example.map;

import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import java.util.Objects;

public class MapViewHolder extends RecyclerView.ViewHolder {
    ImageView nw;
    ImageView ne;
    ImageView sw;
    ImageView se;
    ImageView mapStruct;

    public MapViewHolder(@NonNull View itemView)
    {
        super(itemView);
        nw = itemView.findViewById(R.id.northWest);
        ne = itemView.findViewById(R.id.northEast);
        sw = itemView.findViewById(R.id.southWest);
        se = itemView.findViewById(R.id.southEast);
        mapStruct = itemView.findViewById(R.id.structure);

    }

}

Bar Adapter

package com.example.map;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class SelectionAdapter extends RecyclerView.Adapter<SelectionViewHolder>
{
    StructureData data;

    public SelectionAdapter(StructureData data)
    {
        this.data = data;
    }

    @NonNull
    @Override
    public SelectionViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType)
    {
        LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
        View view = layoutInflater.inflate(R.layout.list_selection,parent,false);
        SelectionViewHolder myViewHolder = new SelectionViewHolder(view);
        return myViewHolder;
    }

    @Override
    public void onBindViewHolder(@NonNull SelectionViewHolder holder, int position)
    {
        Structure s = data.get(position);
        holder.structure.setImageResource(s.getDrawableId());
        holder.label.setText(s.getLabel());
        holder.bind(s);
    }

    @Override
    public int getItemCount()
    {
        return data.size();
    }
}

Bar ViewHolder

package com.example.map;

import android.annotation.SuppressLint;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import java.util.Objects;

public class SelectionViewHolder extends RecyclerView.ViewHolder
{
    Structure selectObject;
    ImageView structure;
    TextView label;

    public SelectionViewHolder(@NonNull View itemView)
    {
        super(itemView);
        structure = itemView.findViewById(R.id.image);
        label = itemView.findViewById(R.id.label);

        structure.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View view)
            {
                SelectionCellFragment.selectedData = selectObject;
            }

        });

    }

    public void bind(Structure s)
    {
        selectObject = s;
    }

    //Maybe, I need to place this bind function in MapViewHolder as well
    //When I press on the button, I must share the information over to the Map fragment
    //Then the new information will form a ImageView on the big one
}

CodePudding user response:

You could use ViewModel to solve your use-case. You could have something like SelectedStructureViewModel that will be set in the SelectionCellFragment when the user taps to select the structure. While the MapCellFragment can observe this SelectedStructureViewModel to be notified whenever the user selects the structure. You can then query it when user taps a place on the Map.

  • Related