Updating Elements of Listview in a Fragment from a Catalog within another Fragment

38 views Asked by At

The title might be a little confusing so I hope that I can express my problem correctly. So I'm working on a simple workout log app. I have fragment ActiveWorkout as in Image 1. When I press the pink add button I am directed to another fragment, which contains different exercises as a List, which is shown in Image 2. Then I am to select an exercise(with the onItemClickListener) and the title of that exercise should be sent back to the ActiveWorkoutFragment and added to the Active Workout, so it should be like Image 3. So the problem here is, I don't exactly know how to keep my Active Workout 'alive', it should be updated if I want to add another exercise and not be blank when I press the pink add button again, so in the end it should be something like in Image 4. I was thinking about sending data with a Bundle, which I also tried in the code but the more difficult part is updating the Workout list without deleting the previous added exercises. Btw the reason I am trying to do something like this is because the data is actually in Firebase Database, so in a sense I'm trying to retrieve data from the Workout database.

Images:

Image 1 Image 2 Image 3 Image 4

This is the Exercise List or the Catalog:

public class ExercisesFragment extends Fragment {

    private ListView lv;
    private FirebaseListAdapter adapter;
    private ArrayList<Exercise> exerciseList;
    private ArrayList<String> nameList;
    //private Adapter adapter;

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

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        View v = inflater.inflate(R.layout.fragment_exercises, container, false);
        lv = v.findViewById(R.id.lv);
        Query query = FirebaseDatabase.getInstance().getReference().child("exerciseList");
        FirebaseListOptions<ExerciseElement> options = new FirebaseListOptions.Builder<ExerciseElement>()
                .setLayout(R.layout.exercise)
                .setQuery(query, ExerciseElement.class)
                .build();

        adapter = new FirebaseListAdapter(options) {
            @Override
            protected void populateView(@NonNull View v, @NonNull Object model, int position) {
                TextView bodypart = v.findViewById(R.id.bodypart);
                TextView title = v.findViewById(R.id.title);

                ExerciseElement el = (ExerciseElement) model;
                bodypart.setText(el.getBodypart().toString());
                title.setText(el.getTitle().toString());


            }
        };
        lv.setAdapter(adapter);


        lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                ExerciseElement el = (ExerciseElement) lv.getItemAtPosition(position);
                String item = el.getTitle();

                ActiveWorkoutFragment awf = new ActiveWorkoutFragment();
                Bundle args = new Bundle();
                args.putString("ExerciseTitle", item);
                awf.setArguments(args);

                getFragmentManager().beginTransaction().replace(R.id.nav_host_fragment, awf).commit();
                //Navigation.findNavController(v).navigate(R.id.activeWorkoutFragment);

            }
        });
        return v;
    }

    @Override
    public void onStart() {
        super.onStart();
        adapter.startListening();
    }

    @Override
    public void onStop() {
        super.onStop();
        adapter.stopListening();
    }
}

Then there is the ActiveWorkoutFragment, which is a little longer but the upper part is not the concern. The addNewExercise() method is being called when I click on the pink add button, so I was trying to retrieve the data somehow there.

public class ActiveWorkoutFragment extends Fragment {

    private Workout workout;
    private TextView emptyRecyclerView;
    private RecyclerView exerciseRecyclerView;
    private ExerciseRecyclerViewAdapter adapter;
    private WorkoutHistory workoutHistory;
    private FloatingActionButton fab;
    private FirebaseAuth mAuth;
    private DatabaseReference databaseWorkouts;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {



        View v =  inflater.inflate(R.layout.fragment_active_workout, container, false);
        fab = v.findViewById(R.id.fab);
        fab.setOnClickListener(this::addNewExercise);
        setHasOptionsMenu(true);

        workout = new Workout("WORKOUT");

        if(savedInstanceState != null) {
            workout = savedInstanceState.getParcelable("key");
        }

        emptyRecyclerView = v.findViewById(R.id.empty_recycler_view);
        //buildRecyclerView(workout);
        exerciseRecyclerView = v.findViewById(R.id.recycler_view_exercise);

        // improves performance if size of RecyclerView content is fixed
        // taken from developer.android.com
        exerciseRecyclerView.setHasFixedSize(true);

        // use a linear layout manager for RecyclerView
        LinearLayoutManager layoutManager = new LinearLayoutManager(this.getContext());
        exerciseRecyclerView.setLayoutManager(layoutManager);

        // add divider
        RecyclerView.ItemDecoration itemDecoration = new
                DividerItemDecoration(this.getContext(), DividerItemDecoration.VERTICAL);
        exerciseRecyclerView.addItemDecoration(itemDecoration);

        // Create adapter and set its data set to workout
        adapter = new ExerciseRecyclerViewAdapter(workout, this);

        // Set up swipe to dismiss and ability to move RecyclerView items around

        // Create callback object for ItemTouchHelper
        ItemTouchHelper.Callback callback = new CustomItemTouchHelperCallback(adapter);

        // Implement object created above
        ItemTouchHelper touchHelper = new ItemTouchHelper(callback);

        touchHelper.attachToRecyclerView(exerciseRecyclerView);

        if (adapter.getItemCount() == 0)
        {
            showEmptyRecyclerViewText();
        }
        else
        {
            exerciseRecyclerView.setAdapter(adapter);
        }

        return v;
    }

    // Adds save button (check mark) to action bar
    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        inflater.inflate(R.menu.active_workout_action_bar, menu);
        super.onCreateOptionsMenu(menu, inflater);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.action_save: {

                List<Exercise> exercises = workout.getExercises();

                mAuth = FirebaseAuth.getInstance();
                String user_id = mAuth.getCurrentUser().getUid();


                databaseWorkouts = FirebaseDatabase.getInstance().getReference("Workouts").child(user_id);
                String id = databaseWorkouts.push().getKey();

                workout = new Workout("abc", user_id, exercises);
                databaseWorkouts.child(id).setValue(workout);


                Toast.makeText(getContext(), "Workout saved", Toast.LENGTH_SHORT).show();

                return true;
            }
            case R.id.action_delete: {
                exerciseRecyclerView.requestFocus();

                AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
                builder.setTitle("Confirm deletion").setMessage("Are you sure you want to delete" +
                        " this workout?");

                builder.setPositiveButton(android.R.string.yes, (dialog, which) -> {
                    try {
                        workoutHistory.removeWorkout(workout);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }

                    Toast.makeText(getContext(), "Workout deleted", Toast.LENGTH_SHORT).show();
                });
                builder.setNegativeButton(android.R.string.no, (dialog, which) -> {
                    dialog.dismiss();
                });

                builder.show();
                return true;
            }
            default:
                // unrecognized button pressed
                return super.onOptionsItemSelected(item);
        }
    }

    public void showEmptyRecyclerViewText()
    {
        emptyRecyclerView.setVisibility(View.VISIBLE);
    }

    public void addNewExercise(View view) {

        Bundle bundle = getArguments();
        String value = "";
        if(bundle != null) {
            value = bundle.getString("ExerciseTitle");
        }
        System.out.println("lala");
        System.out.println(value);

        Exercise newExercise = new Exercise(value, -1, -1);
        if (exerciseRecyclerView.getAdapter() == null) {
            exerciseRecyclerView.setAdapter(adapter);
        }


        emptyRecyclerView.setVisibility(View.INVISIBLE);

        workout.addExercise(newExercise);

        adapter.notifyItemInserted(workout.getExercises().size() - 1);
    }

    private void hideKeyboard(Context context, View view) {
        InputMethodManager imm = (InputMethodManager) context.getSystemService
                (Activity.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
    }

    @Override
    public void onSaveInstanceState(@NonNull Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putParcelable("key", workout);
    }
}
1

There are 1 answers

0
Faisal Naseer On BEST ANSWER

Try this as a base for your project. add views to it and other necessary methods however it will provide you with the flow of module

//contract to update Framgents
public interface FragUpdater {
    public void updateExerciseFrag(Exercise exercise);
}



public class ExerciseActiity extends AppCompatActivity implements FragUpdater {
    FragmentManager fm;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_exercise_actiity);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                gotoActiveWorkoutFragment();
            }
        });
        fm = getSupportFragmentManager();

        gotoExercisesFragment();
    }

    private void gotoActiveWorkoutFragment() {
        ActiveWorkoutFragment activeWorkoutFragment = new ActiveWorkoutFragment();
        Bundle bundle = new Bundle();
        activeWorkoutFragment.setArguments(bundle);
        fm.beginTransaction().add(R.id.content_frame, activeWorkoutFragment, "ExerciseSelectionFrag").addToBackStack(null).commit();
    }

    private void gotoExercisesFragment() {
        ExercisesFragment exercisesFragment = new ExercisesFragment();
        Bundle bundle = new Bundle();
        exercisesFragment.setArguments(bundle);
        fm.beginTransaction().replace(R.id.content_frame, exercisesFragment, "ExerciseDisplayFrag").commit();
    }

    @Override
    public void updateExerciseFrag(Exercise exercise) {
        // Get Fragment ExercisesFragment
        ExercisesFragment frag = (ExercisesFragment)
        fm.findFragmentByTag("ExerciseDisplayFrag");
        if (frag == null) {
            return;
        }
        frag.updateList(exercise);
    }


}



public class ExercisesFragment extends Fragment {

    //here update your list in ExerciseFragment
    public void updateList(Exercise exercise) {}
}


public class ActiveWorkoutFragment extends Fragment {
    FragUpdater fragUpdater;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        fragUpdater = (ExerciseActiity) getActivity();
    }

    private void selectListItem(Exercise exercise) {
        fragUpdater.updateExerciseFrag(exercise);
        getActivity().getSupportFragmentManager().popBackStack();


    }
}