코딩스토리

[Android/안드로이드]RecyclerView 화면깜빡임 현상 방지 본문

Android/유용한 기술

[Android/안드로이드]RecyclerView 화면깜빡임 현상 방지

라크라꾸 2019. 12. 23. 20:42

RecyclerView를 사용하면서 수정된 데이터를 다시 뿌려주기 위해서 notifyDataSetChanged()를 사용해 화면을 다시 갱신을 시킬 경우가 많이 있습니다.  화면을 갱신 시키는데 깜빡임 현상때문에 고정되어있는 데이터들도 깜빡거려 안좋게 보일 수가 있습니다. 

 

이번 시간에는 위 사진과 같이 notifyDataSetChanged()를 통해 화면을 새로 갱신을 할 때 깜빡이는 현상을 방지하는 방법에 대해 알아보도록 하겠습니다.

 

  
  RecyclerView.ItemAnimator animator = recyclerView.getItemAnimator();
  if (animator instanceof SimpleItemAnimator) {
      ((SimpleItemAnimator) animator).setSupportsChangeAnimations(false);
  }
  

 

위 코드를 recyclerView와 adapter를 연결해주기 전이나 후쯤 넣어주시면 됩니다.

깜빡임 기능 방지를 위한 코드는 위의 코드면 되지만 이전 글과 연결해 실행시켜보고싶은 분들을 위해 수정된 부분의 코드를 올려드리도록 하겠습니다.

 

MainActivity.java

  
  package com.example.recyclerviewtest;
  
  import androidx.appcompat.app.AppCompatActivity;
  import androidx.recyclerview.widget.LinearLayoutManager;
  import androidx.recyclerview.widget.RecyclerView;
  import androidx.recyclerview.widget.SimpleItemAnimator;
  
  import android.content.Intent;
  import android.os.Bundle;
  import android.view.View;
  import android.widget.Button;
  
  public class MainActivity extends AppCompatActivity {
  
      RecyclerVierAdapter adapter_small;
      RecyclerView recyclerView;
      Button btn_show_large;
  
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);
          init();
          getData();
  
      }
  
      private void init(){
          recyclerView = findViewById(R.id.recyclerView);
          btn_show_large = findViewById(R.id.btn_show_large);
  
          LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
          recyclerView.setLayoutManager(linearLayoutManager);
  
          adapter_small = new RecyclerVierAdapter(MovieCase.SMALL);
          recyclerView.setAdapter(adapter_small);
  
          RecyclerView.ItemAnimator animator = recyclerView.getItemAnimator();
          if (animator instanceof SimpleItemAnimator) {
              ((SimpleItemAnimator) animator).setSupportsChangeAnimations(false);
          }
  
          btn_show_large.setOnClickListener(new View.OnClickListener() {
              @Override
              public void onClick(View v) {
  //                Intent intent = new Intent(getBaseContext(),ActivityMovieLarge.class);
  //                startActivity(intent);
                  DataMovie data = new DataMovie(R.drawable.hulk, "헐크");
                  adapter_small.changeItem(data,0);
                  data = new DataMovie(R.drawable.thor, "토르");
                  adapter_small.changeItem(data,1);
                  data = new DataMovie(R.drawable.doctor, "닥터스트레인지");
                  adapter_small.changeItem(data,2);
              }
          });
      }
  
      private void getData(){
          DataMovie data = new DataMovie(R.drawable.iron_man, "아이언맨");
          adapter_small.addItem(data);
          data = new DataMovie(R.drawable.spider_man, "스파이더맨");
          adapter_small.addItem(data);
          data = new DataMovie(R.drawable.black_panther, "블랙팬서");
          adapter_small.addItem(data);
          data = new DataMovie(R.drawable.doctor, "닥터스트레인지");
          adapter_small.addItem(data);
          data = new DataMovie(R.drawable.hulk, "헐크");
          adapter_small.addItem(data);
          data = new DataMovie(R.drawable.thor, "토르");
          adapter_small.addItem(data);
          data = new DataMovie(R.drawable.iron_man, "아이언맨");
          adapter_small.addItem(data);
          data = new DataMovie(R.drawable.spider_man, "스파이더맨");
          adapter_small.addItem(data);
          data = new DataMovie(R.drawable.black_panther, "블랙팬서");
          adapter_small.addItem(data);
          data = new DataMovie(R.drawable.doctor, "닥터스트레인지");
          adapter_small.addItem(data);
          data = new DataMovie(R.drawable.hulk, "헐크");
          adapter_small.addItem(data);
          data = new DataMovie(R.drawable.thor, "토르");
          adapter_small.addItem(data);
      }
  }
  

 

RecyclerVierAdapter.java

  
  package com.example.recyclerviewtest;
  
  import android.util.SparseBooleanArray;
  import android.view.LayoutInflater;
  import android.view.View;
  import android.view.ViewGroup;
  
  import androidx.annotation.NonNull;
  import androidx.recyclerview.widget.RecyclerView;
  
  import java.util.ArrayList;
  
  public class RecyclerVierAdapter extends RecyclerView.Adapter<MyItemView> {
  
      // adapter에 들어갈 list 입니다.
      private ArrayList<MyItem> listData = new ArrayList<>();
  
      // Item의 클릭 상태를 저장할 array 객체
      private SparseBooleanArray selectedItems = new SparseBooleanArray();
      // 직전에 클릭됐던 Item의 position
      private int prePosition = -1;
  
      private MovieCase sel_type;
  
      public RecyclerVierAdapter(MovieCase sel_type){
          this.sel_type = sel_type;
      }
  
  
      @NonNull
      @Override
      public MyItemView onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
  
          View view;
  
          if(sel_type == MovieCase.LARGE){
              view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_movie_large, parent, false);
              return new ViewHolderMovieLarge(view);
          } else if(sel_type == MovieCase.SMALL){
              view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_movie_small, parent, false);
              return new ViewHolderMovieSmall(view);
          }
          return null;
      }
  
      @Override
      public void onBindViewHolder(@NonNull MyItemView holder, final int position) {
          if(holder instanceof ViewHolderMovieLarge){
              ViewHolderMovieLarge viewHolderMovieLarge = (ViewHolderMovieLarge)holder;
              viewHolderMovieLarge.onBind(listData.get(position));
          } else if(holder instanceof  ViewHolderMovieSmall){
              ViewHolderMovieSmall viewHolderMovieSmall = (ViewHolderMovieSmall)holder;
              viewHolderMovieSmall.onBind(listData.get(position),selectedItems.get(position));
              viewHolderMovieSmall.setOnViewHolderItemClickListener(new OnViewHolderItemClickListener() {
                  @Override
                  public void onViewHolderItemClick() {
                      if (selectedItems.get(position)) {
                          // 펼쳐진 Item을 클릭 시
                          selectedItems.delete(position);
                      } else {
                          // 직전의 클릭됐던 Item의 클릭상태를 지움
                          selectedItems.delete(prePosition);
                          // 클릭한 Item의 position을 저장
                          selectedItems.put(position, true);
                      }
                      // 해당 포지션의 변화를 알림
                      if (prePosition != -1) notifyItemChanged(prePosition);
                      notifyItemChanged(position);
                      // 클릭된 position 저장
                      prePosition = position;
                  }
              });
          }
      }
  
      @Override
      public int getItemCount() {
          return listData.size();
      }
  
      void addItem(MyItem data) {
          // 외부에서 item을 추가시킬 함수입니다.
          listData.add(data);
      }
  
      void changeItem(DataMovie data, int position){
          listData.set(position,data);
          notifyItemChanged(position);
      }
  }
  

 

 

위 이미지와 같이 변경버튼을 클릭을 해도 깜빡임 현상 없이 이미지와 title부분만 부드럽게 갱신이 되는 것을 볼 수 있습니다.

 

궁금하신점이나 제가 실수한 부분이 있다면 댓글 달아주세요~~

Comments