RecyclerView of Button array - How to update the data?

Viewed 211

This is my first Q on the site, I'll try to form it well. I have a recyclerView, and the Item is an array of buttons. Button click shows a popup menu that allows the user to change the color of the button. I've managed to set that the onClick method will change the color, but I'm clueless about how to save the chosen color in the ButtonArrayList, that Holds the colors.

The problem is that when the button is pressed, I don't know how to understand programatically on which button, in which button array it was pressed.

Thanks!

Just to demonstrate the problem. when button is clicked, How to identify which button of which item was clicked? 1

The code of the fragment:

package com.examples.recyclerViewWithButtonArray;

import android.os.Build;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.google.android.material.floatingactionbutton.FloatingActionButton;

import java.util.LinkedList;


/**
 * A simple {@link Fragment} subclass.
 * Use the {@link Game#newInstance} factory method to
 * create an instance of this fragment.
 */
public class Game extends Fragment {
    // TODO: Rename parameter arguments, choose names that match
    protected static int[] mButtonsColors;

    private final LinkedList<ButtonArray> mButtonArrayList = new LinkedList<>();
    RecyclerView mGuessLinesRecyclerView;
    ButtonArrayListAdapter mButtonArrayListAdapter;
    FloatingActionButton mFab;

    // TODO: Rename and change types of parameters

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

    public static Game newInstance(String param1, String param2) {
        Game fragment = new Game();
        return fragment;
    }

    private void initGameColors(){
        mButtonsColors = new int[4];
        int[] c = getContext().getResources().getIntArray(R.array.buttonColors);
        //asign colors
        for (int i = 0; i < 4; i++) {
            this.mButtonsColors[i] = c[i];
            }
    }


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initGameColors();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View vw = inflater.inflate(R.layout.fragment_game, container, false);
        return vw;
    }

    @RequiresApi(api = Build.VERSION_CODES.M)
    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        mGuessLinesRecyclerView = view.findViewById(R.id.recycler_view);
        mFab = view.findViewById(R.id.fab);
        //initialize recyclerView
        // Create an adapter and supply the data to be displayed.
        mButtonArrayListAdapter = new ButtonArrayListAdapter(getContext(), mButtonArrayList, this);
        // Connect the adapter with the RecyclerView.
        mGuessLinesRecyclerView.setAdapter(mButtonArrayListAdapter);
        // Give the RecyclerView a default layout manager.
        mGuessLinesRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));

        //initializeFAB
        mFab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mButtonArrayList.add(new ButtonArray(getContext(),mButtonsColors));
                mGuessLinesRecyclerView.setAdapter(mButtonArrayListAdapter);
            }
        });


        //add first array to the recycler view.
        // Next guess lines will be added when clicking on movableFab
        mButtonArrayList.add(new ButtonArray(getContext(), this.mButtonsColors));
    }
}



The code of ButtonArrayListAdapter:

package com.examples.recyclerViewWithButtonArray;

import android.content.Context;
import android.graphics.drawable.ColorDrawable;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.PopupWindow;

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

import java.util.ArrayList;
import java.util.List;

public class ButtonArrayListAdapter extends RecyclerView.Adapter<ButtonArrayListAdapter.ButtonArrayViewHolder> {
    private final Context mContext;
    private final List<ButtonArray> mData;
    class ButtonArrayViewHolder extends RecyclerView.ViewHolder {
        public ArrayList<Button> mButtons;
        final ButtonArrayListAdapter mAdapter;
        public ButtonArrayViewHolder(@NonNull View itemView, ButtonArrayListAdapter adapter) {
            super(itemView);
            this.mAdapter = adapter;
            mButtons =new ArrayList<>();
            if(4==4)
            {
                //create an array of button for binding
                mButtons.add((Button)itemView.findViewById(R.id.button_Guess1));
                mButtons.add((Button)itemView.findViewById(R.id.button_Guess2));
                mButtons.add((Button)itemView.findViewById(R.id.button_Guess3));
                mButtons.add((Button)itemView.findViewById(R.id.button_Guess4));
            }
        }
    }

    public ButtonArrayListAdapter(Context mContext, List<ButtonArray> mData, Game mGame) {
        this.mContext = mContext;
        this.mData = mData;
    }

    @NonNull
    @Override
    public ButtonArrayViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View layout;
        layout = LayoutInflater.from(mContext).inflate(R.layout.guess_line,parent,false);
        return new ButtonArrayViewHolder(layout,this);
    }

    @Override
    public void onBindViewHolder(@NonNull final ButtonArrayViewHolder buttonArrayViewHolder, final int position) {
        //bind data here
        //initiate each guessLineButton
        for (int i = 0; i < 4; i++) {
            int c = mData.get(position).mAnswerButtonsColors[i];
            final Button bt = buttonArrayViewHolder.mButtons.get(i);
            //set initial button color
            bt.setBackgroundColor(c);
            //set button clik to open color chooser
            bt.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    int[] chooseColorButtons = new int[4];

                    // inflate the layout of the popup window
                    final View popupView = LayoutInflater.from(mContext).inflate(R.layout.choose_color_popup,null);
                    // create the popup window
                    int width = bt.getWidth();
                    int height = LinearLayout.LayoutParams.WRAP_CONTENT;
                    boolean focusable = true; // lets taps outside the popup also dismiss it
                    final PopupWindow popupWindow = new PopupWindow(popupView, width, height, focusable);

                    // show the popup window
                    // which view you pass in doesn't matter, it is only used for the window tolken
                    int[] loc = new int[]{0,0};
                    bt.getLocationOnScreen(loc);
                    popupWindow.showAtLocation(v, Gravity.TOP|Gravity.LEFT, loc[0], loc[1] + bt.getHeight());
                    // dismiss the popup window when touched
                    popupView.setOnTouchListener(new View.OnTouchListener() {
                        @Override
                        public boolean onTouch(View v, MotionEvent event) {
                            popupWindow.dismiss();
                            return true;
                        }
                    });

                    //initiate each color choose button
                    if(chooseColorButtons.length==4) {
                        chooseColorButtons[0] = R.id.buttonColor1;
                        chooseColorButtons[1] = R.id.buttonColor2;
                        chooseColorButtons[2] = R.id.buttonColor3;
                        chooseColorButtons[3] = R.id.buttonColor4;
                    }

                    for (int j = 0; j < 4 ; j++) {
                        Button colbt = (Button)(popupView.findViewById(chooseColorButtons[j]));
                        colbt.setBackgroundColor(Game.mButtonsColors[j]);

                        colbt.setTextColor(Game.mButtonsColors[j]);
                        colbt.setOnClickListener(new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                bt.setBackgroundColor(((ColorDrawable)(((Button)v).getBackground())).getColor());
//WHAT SHOULD I DO HERE?
                                popupWindow.dismiss();
                            }
                        });
                    }

                }
            });

        }

    }

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

1 Answers

After reading your question what I get is you want to save the color against every button so next time when that button click the same color should load if yes then you can consider these tw0 suggestions

1- if the number of buttons is static and you are not adding them dynamically then you can hardcode the color against each button by adding them in the list and assign them manually against each button.

2- you can use key-value pair(hash map), these are the best solution for any case either you're are manually adding the button or dynamically, just store the color against each key. In this case, buttons should be your keys and colors will be value.

Thanku

Related