안드로이드 스튜디오 뉴스앱 만들기 (RecyclerView)

2019. 12. 20. 20:002020/Android App Develop

ListVIew의 상위호환으로 사용되어지는 RecyclerView

사용법 참고 https://developer.android.com/guide/topics/ui/layout/recyclerview#java

 

RecyclerView로 목록 만들기  |  Android Developers

RecyclerView를 사용하여 동적 콘텐츠의 목록과 그리드를 표시합니다.

developer.android.com

[ 실행결과 ]

리스트의 각 항목들의 제목을 다르지만 형식은 같은 것을 확인할 수 있다. 컴포넌트의 특정 항목의 값만 바꾸는 로직을 생성할 것이고 각 항목들을 관리하기 위해서 Adapter 를 사용한다

 

<1> RecyclerView Layout component를 사용할 Layout을 하나 만는다 - Activity_news.xml

     => matching with NewsActivity.class

 

<2> Adapter를 위한 MyAdapter.class 생성 ( 실제로 앱 구동시 실행하는 class가 아니다 Oncraete 함수가 없음 )

    Adapter는 리스트(RecyclerView)에 들어가는 각 항목들에 들어가는 component들을 관리할 것이다. 

    해당 항목을 위한 xml파일을 생성해야 한다 ( row_news.xml )

 

< Scenario >

1. AndroidManifest.xml 수정 -> 안드로이드 시작 시 activity_news.xml 실행 

2. activity_news.xml 코드에는 단순히 RecyclerViewLayout 컴포넌트가 배치되어있다.

3. NewsActivity.class가 실행되고 activity_news.xml으로부터 RecyclerVIewLayout을 가져오고 디자인과 값을 변경

4. 그 동작방식은 NewsActivity.class - setAdapter() 함수 =>activity_news.xml과 Adapter(MyAdapter) 매칭

5. Adapter는 새로운 row_news.xml과 매칭시킨다 ( 리스트에 들어갈 항목들의 디자인과 값들을 관리하기 위해서 )

( row_news.xml : 뉴스의 제목과 뉴스의 내용들을 적을 TextVIew Component 2개를 생성하고 ImageVIew도 하나 생성 )

6. Adapter - OnCreateViewHolder Function & MyViewHolder Class - Component 들을 관리 (리스트의 각 항목들의 components)

7. Adapter생성자에 데이터를 전송할 수 있는 장치를 만들어주어 activity_news.xml -> Adapter -> row_new.xml 데이터 전송 ( 리스트의 각 항목들에 데이터들이 저장되어 있음 )

 

[ activity_news.xml ] App실행 시 화면 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
 
        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/my_recycler_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
 
        </androidx.recyclerview.widget.RecyclerView>
    </LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
 

RecyclerView Component에 id를 부여하였고 이를 통해 해당 component를 관리할 것

 

[ NewsActivity.class ] matched with activity_news.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package com.example.myapplication;
 
 
 
 
public class NewsActivity extends AppCompatActivity {
 
    private RecyclerView recyclerView;
    private RecyclerView.Adapter mAdapter;
    private RecyclerView.LayoutManager layoutManager;
    /* 리스트의 각 객체들에 들어갈 데이터들 / DB로부터 또는 사용자로부터 받아올 수 있다 */
    private String[] myDataset = {"첫 번째 뉴스의 제목 ","두 번째 뉴스의 제목","세 번째 뉴스의 제목"};
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        /* matching with activity_news*/
        setContentView(R.layout.activity_news);
 
        /* activity_news.xml에서 RecyclerView 가져옴 */
        recyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
 
        // use this setting to improve performance if you know that changes
        // in content do not change the layout size of the RecyclerView
        recyclerView.setHasFixedSize(true);
 
        // use a linear layout manager
        layoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(layoutManager);
 
        /* Adapter를 연결 ! 
           Adapter를 사용해서 리스트의 각 항목들을 효과적으로 관리 */
        // specify an adapter (see also next example)
        mAdapter = new MyAdapter(myDataset); // Adapter생성자를 사용 해당 생성자는 Myadapter.class에서 확인
        recyclerView.setAdapter(mAdapter);
 
    }
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
 

 

[ MyAdapter.class ] matched with row_news.xml 

리스트들의 각 항목에 디자인을 입혀주고 값을 효율적으로 관리하기 위해서 사용한다. 코드를 보기 전 row_news.xml의 코드부터 확인하자

( * class형식으로 파일이 존재하지만 OnCreate함수가 없기에 다른 class들처럼 동작하지 않는다 )

[ row_news.xml ] 리스트에 들어가는 각 항목들의 디자인

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    tools:context=".MainActivity">
 
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <!--뉴스 이미지를 넣을 것-->
            <ImageView
                android:id="@+id/ImageView_news"
                android:layout_width="match_parent"
                android:layout_height="45dp"
                android:src="@drawable/icon_happy"></ImageView>
            <!-- 뉴스의 제목을 넣을 공간 -->
            <TextView
                android:id="@+id/TextView_title"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="Hello, this is example of RecycleView"
                android:layout_alignBottom="@+id/ImageView_news"
                android:textSize="20dp"
                android:background="#77ff88aa"
                ></TextView>
        </RelativeLayout>
        <!--뉴스의 내용 일부를 적을 공간-->
        <TextView
            android:id="@+id/TextView_content"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Contents part"
            android:textSize="15dp"
            android:ellipsize="end"
            ></TextView>
    </LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
 

 

[ MyAdapter.class ] matched with row_news.xml 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
package com.example.myapplication;
 
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
 
import android.widget.TextView;
 
import androidx.recyclerview.widget.RecyclerView;
 
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
    private String[] mDataset;
 
    // Provide a reference to the views for each data item
    // Complex data items may need more than one view per item, and
    // you provide access to all the views for a data item in a view holder
    
    /* 리스트 내의 각 항목들을 관리하는 ViewHolder class*/
    
    public static class MyViewHolder extends RecyclerView.ViewHolder {
        // each data item is just a string in this case
        public TextView TextView_title;
        public TextView TextView_content;
        public ImageView ImageView_news;
        
        /* 가져오는 layout에서 id값을 통해 해당 Component를 가져와 변수에 저장 */
        public MyViewHolder(View v) {       
            super(v);
            TextView_title = v.findViewById(R.id.TextView_title);
            TextView_content = v.findViewById(R.id.TextView_content);
            ImageView_news = v.findViewById(R.id.ImageView_news);
        }
    }
 
    // Provide a suitable constructor (depends on the kind of dataset)
    /* NewsActivity에서 Adapter와 매칭시 사용하는 사용자이다
       이 때 NewsActivity의 데이터들이 데이터배열을 통해 전달되어진다
    */
    
    public MyAdapter(String[] myDataset) {
        mDataset = myDataset;
    }
 
    // Create new views (invoked by the layout manager)
    @Override
    public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent,
                                                     int viewType) {
        /* 리스트의 각 항목에 입혀줄 디자인을 생성한다 즉, create a new view
           setContentView(R.layout.xxx) 처럼 xml 매칭, 하지만 RecycleView의 특정 부분만 변경시킬 때는
           효율성을 위해 inflate함수를 사용
           사용할 xml(row_news)의 최상위 layout을 이용
         * */
        androidx.constraintlayout.widget.ConstraintLayout v
                = (androidx.constraintlayout.widget.ConstraintLayout) LayoutInflater.from(parent.getContext())
                .inflate(R.layout.row_news, parent, false);
 
        MyViewHolder vh = new MyViewHolder(v); /* row_news에서 components를 가져와 MyViewHolder객체의 변수들에 저장된다*/
        return vh;
    }
 
    // Replace the contents of a view (값 대입)
    @Override
 
    /* MyAdapter.class와 매칭되어있는 row_news.xml에 있는 TextView_title 컴포넌트에 값 SET */
    public void onBindViewHolder(MyViewHolder holder, int position) {
        // - get element from your dataset at this position
        // - replace the contents of the view with that element
        // TextView_title component에 값을 지정한다 NewsActivity.class에서 넘어온 mDataset에 있는 데이터 
        holder.TextView_title.setText(mDataset[position]);
 
    }
 
    // Return the size of your dataset (invoked by the layout manager)
    @Override
    public int getItemCount() {
        return mDataset.length;
    }
}
 
http://colorscripter.com/info#e" target="_blank" style="text-decoration:none;color:white">cs