Computer >> 컴퓨터 >  >> 프로그래밍 >> Android

Android RecyclerView에서 LinearLayoutManager로 맨 위로 스크롤하는 방법

본격적인 예제에 들어가기 앞서, 안드로이드의 RecyclerView가 무엇인지 간단히 짚고 넘어가겠습니다. RecyclerView는 ListView의 발전된 형태로, ViewHolder 디자인 패턴을 기반으로 동작합니다. 이를 활용하면 그리드 형태나 리스트 형태의 아이템을 효율적으로 화면에 표시할 수 있습니다.

이번 예제에서는 학생 이름과 나이를 보여주는 학생 정보 앱을 만들면서, LinearLayoutManager를 사용하는 RecyclerView에서 맨 위로 스크롤하는 방법을 단계별로 알아보겠습니다.

1단계: 새 프로젝트 생성

Android Studio에서 File → New Project로 이동한 뒤, 필요한 모든 정보를 입력하여 새 프로젝트를 생성합니다.

2단계: build.gradle에 라이브러리 의존성 추가

build.gradle 파일을 열고 RecyclerView와 CardView 라이브러리 의존성을 추가합니다.

apply plugin: 'com.android.application'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.example.andy.tutorialspoint"
        minSdkVersion 19
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}
dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support:design:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    implementation 'com.android.support:cardview-v7:28.0.0'
    implementation 'com.android.support:recyclerview-v7:28.0.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}

3단계: activity_main.xml 레이아웃 작성

res/layout/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"
    xmlns:app = "https://schemas.android.com/apk/res-auto"
    android:layout_width = "match_parent"
    android:layout_height = "match_parent"
    app:layout_behavior = "@string/appbar_scrolling_view_behavior"
    tools:showIn = "@layout/activity_main"
    android:fitsSystemWindows = "true"
    tools:context = ".MainActivity">
    <android.support.v7.widget.RecyclerView
        android:id = "@+id/recycler_view"
        android:layout_width = "match_parent"
        android:layout_height = "wrap_content"
        android:scrollbars = "horizontal" />
    <android.support.design.widget.FloatingActionButton
        android:id = "@+id/top"
        app:backgroundTint = "#FFFF00"
        android:layout_width = "wrap_content"
        android:layout_height = "wrap_content"
        android:layout_gravity = "bottom|end"
        android:src = "@android:drawable/arrow_up_float" />
</android.support.design.widget.CoordinatorLayout >

위 코드에서는 RecyclerView를 화면에 배치하고, 하단 우측에 FloatingActionButton을 추가했습니다. FloatingActionButton은 CoordinatorLayout을 지원하기 때문에 부모 레이아웃을 CoordinatorLayout으로 설정했습니다. 이 버튼을 클릭하면 RecyclerView가 맨 위 위치로 스크롤됩니다.

4단계: MainActivity.java 구현

src/MainActivity.java 파일에 다음 코드를 추가합니다.

package com.example.andy.tutorialspoint;

import android.annotation.TargetApi;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.RequiresApi;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class MainActivity extends AppCompatActivity {
    private RecyclerView recyclerView;
    private StudentAdapter studentAdapter;
    private List studentDataList = new ArrayList<>();
    @TargetApi(Build.VERSION_CODES.O)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        FloatingActionButton moveTop = findViewById(R.id.top);
        recyclerView = findViewById(R.id.recycler_view);
        studentAdapter = new StudentAdapter(studentDataList,MainActivity.this);
        RecyclerView.LayoutManager manager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(manager);
        recyclerView.setAdapter(studentAdapter);
        StudentDataPrepare();
        moveTop.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                recyclerView.smoothScrollToPosition(0);
            }
        });
    }
    @RequiresApi(api = Build.VERSION_CODES.N)
    private void StudentDataPrepare() {
        studentData data = new studentData("sai", 25);
        studentDataList.add(data);
        data = new studentData("sai raj", 25);
        studentDataList.add(data);
        data = new studentData("raghu", 20);
        studentDataList.add(data);
        data = new studentData("raj", 28);
        studentDataList.add(data);
        data = new studentData("amar", 15);
        studentDataList.add(data);
        data = new studentData("bapu", 19);
        studentDataList.add(data);
        data = new studentData("chandra", 52);
        studentDataList.add(data);
        data = new studentData("deraj", 30);
        studentDataList.add(data);
        data = new studentData("eshanth", 28);
        studentDataList.add(data);
        Collections.sort(studentDataList, new Comparator() {
            @Override
            public int compare(studentData o1, studentData o2) {
                return o1.name.compareTo(o2.name);
            }
        });
    }
}

위 코드에서는 RecyclerView와 StudentAdapter를 연결했습니다. 어댑터에는 학생 이름과 나이를 담고 있는 studentDataList(ArrayList)를 전달했으며, 데이터는 이름순으로 정렬됩니다.

핵심은 smoothScrollToPosition() 메서드입니다. 이 메서드를 사용하면 지정한 위치로 부드럽게 스크롤할 수 있으며, 필요에 따라 원하는 어떤 위치든 지정할 수 있습니다. 이번 예제에서는 0번(맨 위) 위치로 스크롤하도록 구현했습니다.

moveTop.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        recyclerView.smoothScrollToPosition(0);
    }
});

5단계: StudentAdapter.java 작성

src/StudentAdapter.java 파일의 내용은 다음과 같습니다.

package com.example.andy.tutorialspoint;
import android.graphics.Color;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;

import java.util.List;
import java.util.Random;

class StudentAdapter extends RecyclerView.Adapter {
    List studentDataList;
    public StudentAdapter(List studentDataList) {
        this.studentDataList = studentDataList;
    }
    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        View itemView = LayoutInflater.from(viewGroup.getContext())
        .inflate(R.layout.student_list_row, viewGroup, false);
        return new MyViewHolder(itemView);
    }
    @Override
    public void onBindViewHolder(MyViewHolder viewHolder, int i) {
        studentData data = studentDataList.get(i);
        Random rnd = new Random();
        int currentColor = Color.argb(255, rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256));
        viewHolder.parent.setBackgroundColor(currentColor);
        viewHolder.name.setText(data.name);
        viewHolder.age.setText(String.valueOf(data.age));
    }
    @Override
    public int getItemCount() {
        return studentDataList.size();
    }
    class MyViewHolder extends RecyclerView.ViewHolder {
        TextView name,age;
        LinearLayout parent;
        public MyViewHolder(View itemView) {
            super(itemView);
            parent = itemView.findViewById(R.id.parent);
            name = itemView.findViewById(R.id.name);
            age = itemView.findViewById(R.id.age);
        }
    }
}

어댑터 클래스에는 다음 네 가지 핵심 요소가 포함되어 있습니다.

  • onCreateViewHolder(): ViewHolder를 생성하고 해당 뷰를 반환합니다.
  • onBindViewHolder(): 생성된 ViewHolder에 데이터를 바인딩합니다.
  • getItemCount(): 리스트의 전체 크기를 반환합니다.
  • MyViewHolder 클래스: RecyclerView.ViewHolder를 상속받는 내부 ViewHolder 클래스입니다.

RecyclerView 아이템에 랜덤한 배경색을 적용하기 위해, 안드로이드에서 기본 제공하는 Random 클래스로 임의의 색상을 생성하고 이를 아이템 뷰의 부모 레이아웃에 설정했습니다.

Random rnd = new Random();
int currentColor = Color.argb(255, rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256));
viewHolder.parent.setBackgroundColor(currentColor);

6단계: student_list_row.xml 작성

res/layout/student_list_row.xml 파일의 내용은 다음과 같습니다.

<?xml version = "1.0" encoding = "utf-8"?>
<android.support.v7.widget.CardView xmlns:android = "https://schemas.android.com/apk/res/android"
    xmlns:card_view = "https://schemas.android.com/apk/res-auto"
    android:layout_width = "match_parent"
    card_view:cardCornerRadius = "4dp"
    android:id = "@+id/card_view"
    android:layout_margin = "10dp"
    android:layout_height = "200dp">
    <LinearLayout
        android:id = "@+id/parent"
        android:layout_gravity = "center"
        android:layout_width = "match_parent"
        android:orientation = "vertical"
        android:gravity = "center"
        android:layout_height = "match_parent">
    <TextView
        android:id = "@+id/name"
        android:layout_width = "wrap_content"
        android:gravity = "center"
        android:textSize = "25sp"
        android:textColor = "#FFF"
        android:layout_height = "wrap_content" />
    <TextView
        android:id = "@+id/age"
        android:layout_width = "wrap_content"
        android:gravity = "center"
        android:textSize = "25sp"
        android:textColor = "#FFF"
        android:layout_height = "wrap_content" />
    </LinearLayout>
</android.support.v7.widget.CardView>

위 리스트 아이템 뷰에서는 CardView 내부에 이름과 나이를 표시하는 두 개의 TextView를 배치했습니다. CardView는 미리 정의된 코너 반경(cornerRadius)과 그림자 속성을 제공하므로, 이를 활용해 카드 형태의 UI를 손쉽게 구현할 수 있습니다.

7단계: studentData.java 데이터 클래스 작성

src/studentData.java 파일의 내용은 다음과 같습니다.

class studentData {  
    String name;
    int age;
    public studentData(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

위 코드는 학생의 이름과 나이를 담는 데이터 객체를 정의합니다.

앱 실행 및 결과 확인

이제 애플리케이션을 실행해 보겠습니다. 실제 안드로이드 기기가 컴퓨터에 연결되어 있다고 가정합니다. Android Studio에서 프로젝트의 액티비티 파일 중 하나를 연 뒤, 툴바의 Run 아이콘을 클릭하고 실행 기기로 자신의 모바일 기기를 선택하세요. 그러면 기기 화면에 아래와 같은 기본 화면이 표시됩니다.

Android RecyclerView에서 LinearLayoutManager로 맨 위로 스크롤하는 방법

이후 노란색 버튼(플로팅 버튼)을 클릭하면 RecyclerView가 맨 위로 부드럽게 스크롤되며, 결과는 아래와 같습니다.

Android RecyclerView에서 LinearLayoutManager로 맨 위로 스크롤하는 방법