João Sardinha João Sardinha - 3 months ago 31
Java Question

Android: RecyclerView behaving as a GridLayout

I need to create a RecyclerView with 3 columns, with a button that when clicked, a custom view is added into the RecyclerView. And when I click in a view, it gets deleted. for example: I added 5 views, if I click on number 3, number 3 gets destroyed, and number 4 e 5 take one step back. I've created this in a GridLayout, but I want it to be in a RecyclerView, I'm aware that I need an Adapter, a Viewholder and a LayoutManager. So how is this done?

This is how it looked with a GridLayout:

public class MainActivity extends AppCompatActivity {
GridLayout gridLayout;
static int i;
static int n = 1000;
private Button theButton;

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

gridLayout = (GridLayout)findViewById(R.id.gamehistory);
Button b = (Button)findViewById(R.id.Button01);

b.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {

theButton = new Button(MainActivity.this);
TextView theText = new TextView(MainActivity.this);
theText.setGravity(Gravity.CENTER_HORIZONTAL);
final LinearLayout theLayout = new LinearLayout(MainActivity.this);

theLayout.setOrientation(LinearLayout.VERTICAL);
theLayout.setBackgroundColor(Color.parseColor("#8BAAC3"));
theLayout.setId(++i);
theButton.setId(++n);
theButton.setText(theButton.getId() + "");
theText.setText(theLayout.getId() + "");
theLayout.addView(theButton);
theLayout.addView(theText);
gridLayout.addView(theLayout);
GridLayout.LayoutParams lp = (GridLayout.LayoutParams) theLayout.getLayoutParams();
lp.setMargins(10, 10, 10, 10);

theButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
gridLayout.removeView(theLayout);
}
});
}
});
}
}


Regarding my attempts with a RecyclerView I've tried a guide in a blog but it didn't work.

Answer

Typically you should post what code you attempted with the RecyclerView (not the code with the GridView). That being said here are some examples to get you going in the right direction.

SAMPLE ATIVITY

public class MainActivity extends AppCompatActivity {

    private static final int NUMBER_COLUMNS = 3;

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

        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
        recyclerView.setLayoutManager(new GridLayoutManager(this, NUMBER_COLUMNS));
        recyclerView.addItemDecoration(new SampleItemDecoration());
        final MyAdapter adapter = new MyAdapter();
        recyclerView.setAdapter(adapter);

        // Items can be added to adapter from any part of code
        adapter.addItem("Static Item A");
        adapter.addItem("Static Item B");


        findViewById(R.id.button_add_item).setOnClickListener(new View.OnClickListener() {
            int i;

            @Override
            public void onClick(View v) {
                adapter.addItem("Dynamic Item " + i++);
            }
        });
    }
}

SAMPLE ADAPTER

class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {

    private List<String> items = new ArrayList<>();

    public void addItem(String name) {
        items.add(name);
        notifyItemInserted(items.size() - 1);
    }

    public void removeItem(int position) {
        items.remove(position);
        notifyItemRemoved(position);
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
        View view = inflater.inflate(R.layout.grid_item_button, parent, false);

        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        holder.setButtonName(items.get(position));
    }

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

    class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

        private Button button;

        public ViewHolder(View itemView) {
            super(itemView);
            button = (Button) itemView.findViewById(R.id.grid_button);
            button.setOnClickListener(this);
        }


        public void setButtonName(String buttonName) {
            button.setText(buttonName);
        }

        @Override
        public void onClick(View v) {
            removeItem(getAdapterPosition());
        }
    }
}

SAMPLE DECORATOR

class SampleItemDecoration extends RecyclerView.ItemDecoration {

    Paint paint = new Paint();

    @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
        for (int i = 0; i < parent.getChildCount(); i++) {
            View view = parent.getChildAt(i);
            paint.setColor(Color.parseColor("#8BAAC3"));
            if (parent.getChildLayoutPosition(view) == RecyclerView.NO_POSITION) {
                continue;
            }

            // Compute bounds of cell in layout
            Rect bounds = new Rect(
                    layoutManager.getDecoratedLeft(view),
                    layoutManager.getDecoratedTop(view),
                    layoutManager.getDecoratedRight(view),
                    layoutManager.getDecoratedBottom(view)
            );

            // Add space between cell backgrounds
            bounds.inset(2, 2);

            c.drawRect(bounds, paint);
        }
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        outRect.set(10, 10, 10, 10); // Specify spacing between items in grid
    }
}