안드로이드 GridLayoutManager 예제

안드로이드 GridLayoutManager은 그리드 안에 항목을 배치하는 RecyclerView.LayoutManager 구현입니다. 이 튜토리얼에서는 CardViewsGridLayout 형식의 RecyclerView 안에 표시하는 애플리케이션을 만들겠습니다. 또한 RecyclerView 항목을 클릭하여 ListViewitemClickListener와 유사하게 구현할 것입니다.

안드로이드 GridLayoutManager

여기에서 LinearLayoutManager를 사용하여 RecyclerView를 구현했습니다. 이제 RecyclerView를 그리드로 레이아웃하는 GridLayoutManager를 사용해 보겠습니다. 다음은 GridLayoutManager의 생성자입니다.

GridLayoutManager (Context context, 
                int spanCount, 
                int orientation, 
                boolean reverseLayout)

reverseLayout을 true로 설정하면 항목을 뒤에서 시작하여 배치합니다. 각 항목의 Span 크기를 설정하려면 GridLayoutManager에서 setSpanSizeLookup 메서드를 호출합니다. 새로운 Android Studio 프로젝트에서 GridLayoutManager를 사용하여 RecyclerView를 구현해 봅시다.

Android GridLayoutManager 예제 프로젝트 구조

프로젝트는 단일 Activity로 구성되어 있습니다. MainActivity.java, 어댑터 클래스인 RecyclerViewAdapter.java, DataModel.java 클래스 및 사용자 정의 GridLayoutManager 클래스인 AutoFitGridLayoutManager.java가 있습니다. MainActivity.java 클래스의 xml 레이아웃은 activity_main.xml 파일에 정의되어 있습니다.

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="https://schemas.android.com/apk/res-auto"
    android:fitsSystemWindows="true"
    tools:context=".MainActivity">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <android.support.v7.widget.RecyclerView
            android:id="@+id/recyclerView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scrollbars="vertical"
            app:layout_behavior="@string/appbar_scrolling_view_behavior" />

    </RelativeLayout>

</android.support.design.widget.CoordinatorLayout>

참고: Material Design 위젯과 CardView를 위해 build.gradle 파일에 다음 종속성을 추가하지 않는 것을 잊지 마십시오.

compile 'com.android.support:cardview-v7:25.1.1'
compile 'com.android.support:design:25.1.1'

DataModel.java 클래스는 다음과 같습니다: package com.journaldev.recyclerviewgridlayoutmanager;

public class DataModel {

    public String text;
    public int drawable;
    public String color;

    public DataModel(String t, int d, String c )
    {
        text=t;
        drawable=d;
        color=c;
    }
}

DataModel 클래스는 각 항목 셀의 텍스트, 드로어블 아이콘 및 배경 색상을 보유합니다. RecyclerViewAdapter.java 클래스는 다음과 같습니다:

package com.journaldev.recyclerviewgridlayoutmanager;

import android.content.Context;
import android.graphics.Color;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import java.util.ArrayList;


public class RecyclerViewAdapter extends RecyclerView.Adapter {

    ArrayList mValues;
    Context mContext;
    protected ItemListener mListener;

    public RecyclerViewAdapter(Context context, ArrayList values, ItemListener itemListener) {

        mValues = values;
        mContext = context;
        mListener=itemListener;
    }

    public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

        public TextView textView;
        public ImageView imageView;
        public RelativeLayout relativeLayout;
        DataModel item;

        public ViewHolder(View v) {

            super(v);

            v.setOnClickListener(this);
            textView = (TextView) v.findViewById(R.id.textView);
            imageView = (ImageView) v.findViewById(R.id.imageView);
            relativeLayout = (RelativeLayout) v.findViewById(R.id.relativeLayout);

        }

        public void setData(DataModel item) {
            this.item = item;

            textView.setText(item.text);
            imageView.setImageResource(item.drawable);
            relativeLayout.setBackgroundColor(Color.parseColor(item.color));

        }


        @Override
        public void onClick(View view) {
            if (mListener != null) {
                mListener.onItemClick(item);
            }
        }
    }

    @Override
    public RecyclerViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        View view = LayoutInflater.from(mContext).inflate(R.layout.recycler_view_item, parent, false);

        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(ViewHolder Vholder, int position) {
        Vholder.setData(mValues.get(position));

    }

    @Override
    public int getItemCount() {

        return mValues.size();
    }

    public interface ItemListener {
        void onItemClick(DataModel item);
    }
}

위의 코드에서는 MainActivity.java 클래스에서 구현될 ItemListener 인터페이스를 정의했습니다. 각 RecyclerView 항목의 xml 레이아웃은 다음과 같습니다. recycler_view_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:card_view="https://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <android.support.v7.widget.CardView
        android:id="@+id/cardView"
        android:layout_width="match_parent"
        android:layout_height="150dp"
        card_view:cardCornerRadius="0dp"
        card_view:cardElevation="@dimen/margin10"
        card_view:cardMaxElevation="@dimen/margin10"
        card_view:contentPadding="@dimen/margin10">


        <RelativeLayout
            android:id="@+id/relativeLayout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            android:layout_gravity="center">

            <ImageView
                android:id="@+id/imageView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerInParent="true"
                android:tint="@android:color/white"
                android:padding="5dp" />


            <TextView
                android:id="@+id/textView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerHorizontal="true"
                android:textColor="@android:color/white"
                android:layout_below="@+id/imageView" />


        </RelativeLayout>

    </android.support.v7.widget.CardView>

</LinearLayout>

AutoFitGridLayoutManager.java 클래스는 다음과 같습니다:

package com.journaldev.recyclerviewgridlayoutmanager;

import android.content.Context;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;

public class AutoFitGridLayoutManager extends GridLayoutManager {

    private int columnWidth;
    private boolean columnWidthChanged = true;

    public AutoFitGridLayoutManager(Context context, int columnWidth) {
        super(context, 1);

        setColumnWidth(columnWidth);
    }

    public void setColumnWidth(int newColumnWidth) {
        if (newColumnWidth > 0 && newColumnWidth != columnWidth) {
            columnWidth = newColumnWidth;
            columnWidthChanged = true;
        }
    }

    @Override
    public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
        if (columnWidthChanged && columnWidth > 0) {
            int totalSpace;
            if (getOrientation() == VERTICAL) {
                totalSpace = getWidth() - getPaddingRight() - getPaddingLeft();
            } else {
                totalSpace = getHeight() - getPaddingTop() - getPaddingBottom();
            }
            int spanCount = Math.max(1, totalSpace / columnWidth);
            setSpanCount(spanCount);
            columnWidthChanged = false;
        }
        super.onLayoutChildren(recycler, state);
    }
}

스팬 수는 방향, 너비 및 사용 가능한 높이에 따라 동적으로 계산됩니다. MainActivity.java 클래스는 아래와 같습니다:

package com.journaldev.recyclerviewgridlayoutmanager;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.widget.Toast;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity implements RecyclerViewAdapter.ItemListener {

    RecyclerView recyclerView;
    ArrayList arrayList;

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


        recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
        arrayList = new ArrayList();
        arrayList.add(new DataModel("Item 1", R.drawable.battle, "#09A9FF"));
        arrayList.add(new DataModel("Item 2", R.drawable.beer, "#3E51B1"));
        arrayList.add(new DataModel("Item 3", R.drawable.ferrari, "#673BB7"));
        arrayList.add(new DataModel("Item 4", R.drawable.jetpack_joyride, "#4BAA50"));
        arrayList.add(new DataModel("Item 5", R.drawable.three_d, "#F94336"));
        arrayList.add(new DataModel("Item 6", R.drawable.terraria, "#0A9B88"));

        RecyclerViewAdapter adapter = new RecyclerViewAdapter(this, arrayList, this);
        recyclerView.setAdapter(adapter);


        /**
         AutoFitGridLayoutManager that auto fits the cells by the column width defined.
         **/

        /*AutoFitGridLayoutManager layoutManager = new AutoFitGridLayoutManager(this, 500);
        recyclerView.setLayoutManager(layoutManager);*/


        /**
         Simple GridLayoutManager that spans two columns
         **/
        GridLayoutManager manager = new GridLayoutManager(this, 2, GridLayoutManager.VERTICAL, false);
        recyclerView.setLayoutManager(manager);
    }

    @Override
    public void onItemClick(DataModel item) {

        Toast.makeText(getApplicationContext(), item.text + " is clicked", Toast.LENGTH_SHORT).show();

    }
}

  1. 위 클래스는 인터페이스 RecyclerViewAdapter.ItemListener를 구현하고 어댑터 클래스에 정의된 onItemClick 메서드를 재정의합니다. 이렇게 함으로써 우리는 RecyclerView Click Listener를 어댑터 클래스 대신에 우리의 Activity 내에서 구현했습니다(리스트뷰에 대한 표준 onItemClickListener와 유사)
  2. A DataModel class holds the details for each RecyclerView item
  3. RecyclerView의 레이아웃 관리자는 열 너비를 500으로 설정한 AutoFitGridLayoutManager 클래스를 인스턴스화하거나 열 수를 2로 설정한 GridLayoutManager 클래스 객체를 호출하여 정의할 수 있습니다

표준 GridLayoutManager 코드로 응용 프로그램의 출력을 확인해 봅시다. 보시다시피 각 행은 두 개의 항목을 가지며 양방향으로 열 너비를 차지합니다. 이제 간단한 GridLayoutManager 코드의 주석 처리를 해제하고 AutoFitGridLayoutManager 코드를 실행합니다.

AutoFitGridLayoutManager layoutManager = new AutoFitGridLayoutManager(this, 500);
recyclerView.setLayoutManager(layoutManager);

애플리케이션의 작동 결과는 아래에 제공됩니다. 위의 결과에서 보다시피 방향이 가로로 변경되면 각 행에는 세 개의 항목이 있으며, 이로 인해 항목이 자동으로 열 너비에 맞게 크기가 조정됩니다. 이로써 튜토리얼을 마칩니다. 아래 링크에서 최종 안드로이드 GridLayoutManager 프로젝트를 다운로드할 수 있습니다.

안드로이드 GridLayoutManager 프로젝트 다운로드

Source:
https://www.digitalocean.com/community/tutorials/android-gridlayoutmanager-example