2016년 8월 1일 월요일

Android Studio - ListView 의 업그레이드 버전인 RecyclerView


기존 ListView 에서는 개발자가 임의로 관여할 수 있는 기회가 적었던 반면,
RecyclerView 는 그 안에다가 효과, 레이아웃의 변경이 가능하다.

ex) LinearLayoutManager / GridLayoutManager / StaggeredGridLayoutManager (높이가 불규칙한 Grid)


1. Graddle 에 dependency 추가
프로젝트 익스플로러에서 '모듈 우클릭' -> 'open module setting' -> 'dependency 탭 선택' -> '우측의 + 버튼 클릭'

  library : 이미 다운 받아진 구글의 라이브러리
  file : 개발자가 다운 받은 임의의 jar 파일
  module : 현재 개발중인 다른 모듈의 라이브러리

com.android.support:recyclerview-v7:24.1.1 추가

Graddle에 추가된 것 확인

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    testCompile 'junit:junit:4.12'    
    compile 'com.android.support:appcompat-v7:23.4.0'
    compile 'com.android.support:recyclerview-v7:24.1.1'
}


2. recycler view xml 파일 준비

fragment_one.xml

<?xml version="1.0" encoding="utf-8"?><android.support.v7.widget.RecyclerView
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:id="@+id/recyclerView"  />

recycler view 멤버 변수 추가

OneFragment.java

RecyclerView recyclerView;


2. Holder 패턴



findViewById 의 퍼포먼스 문제로 인해서 한번 가져 온 viewId를 지니고 있다가 활용

OneFragment.java
// findViewId의 성능 이슈부분 솔루션
// 내부적으로 holder 객체는 메모리에 누적되어 한번만 view find
class MyViewHolder extends RecyclerView.ViewHolder{
    public TextView title;  // Adapter에서 획득하고자 하는 view
    // 매개변수는 항목 layout.xml 초기화 view 계층의 root 객체이다.
    // Adapter가 전달할 것임.
    public MyViewHolder(View itemView){
        super(itemView);
        title = (TextView)itemView.findViewById(android.R.id.text1);
    }
}



3. Adapter

OneFragment.java

class MyAdapter extends RecyclerView.Adapter<MyViewHolder>{
    final List<String> list;
    // 항목구성 집합 데이터.. activity가 전달할것임
    public MyAdapter(List<String> list){
        this.list = list;
    }

    // 하나의 항목을 위해 최초에 수행될 부분
    // 항목 layout 초기화.. Holder 준비
    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        // 항목 layout 초기화
        View view = LayoutInflater.from(parent.getContext())
          .inflate(android.R.layout.simple_list_item_1, parent, false);
        return new MyViewHolder(view);
    // holder 리턴 시키면 내부적으로 holder 객체를 메모리에 유지 
    }

    // 항목 하나를 구성하기 위해서 호출
    // 항목구성 데이터, 이벤트 알고리즘이 구성되는 곳
    // onCreateViewHolder에서 리턴시킨 holder가 매개변수로
    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        String text = list.get(position);
        holder.title.setText(text);
    }

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

4. Decoration (optional)

OneFragment.java

class MyDecoration extends RecyclerView.ItemDecoration{
    // RecyclerView Adapter 작업에 의해 항목이 추가된 후에 호출
    // 항목위에 추가 drawing 작업이 필요시 이용
    @Override
    public void onDrawOver(Canvas c, RecyclerView parent, 
                           RecyclerView.State state) {
        super.onDrawOver(c, parent, state);

        int width = parent.getWidth();
        int height = parent.getHeight();

        Drawable dr = getActivity().getResources()
         .getDrawable(R.drawable.kbo);
        int drWidth = dr.getIntrinsicWidth();
        int drHeight = dr.getIntrinsicHeight();

        int left = width/2 - drWidth/2;
        int top = height/2 - drHeight/2;

        c.drawBitmap(
                BitmapFactory.decodeResource(getActivity().getResources(), R.drawable.kbo),
                left, top, null);
    }

    // 항목 하나하나를 추가하기 위해서
    @Override
    public void getItemOffsets(Rect outRect, View view, 
                  RecyclerView parent, RecyclerView.State state) {
        super.getItemOffsets(outRect, view, parent, state);

        // 항목의 index
        int index = parent.getChildAdapterPosition(view)+1;

        if(index % 3==0){
            outRect.set(20,20,20,60);
        }else{
            outRect.set(20,20,20,20);
        }

        view.setBackgroundColor(0xFFECE9E9);
        ViewCompat.setElevation(view, 20.0f);
    // 하위버전 호완을 위해서
    }
}

4. Fragment에 적용

OneFragment.java

public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    recyclerView = (RecyclerView)inflater.inflate(R.layout.fragment_one, container, false);

    // 항목구성 데이터 준비    List<String> list = new ArrayList<>();

    for(int i=0; i<20; i++){
        list.add("item="+i);
    }

    recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
    recyclerView.setAdapter(new MyAdapter(list));
    recyclerView.addItemDecoration(new MyDecoration());

    return recyclerView;
}

댓글 없음:

댓글 쓰기