ViewPager 2 의 사용 을 깊이 이해 하 다.

17453 단어 AndroidViewPager2
1.ViewPager 2 의 새로운 기능
ViewPager 2 는 이름 에서 ViewPager 의 업그레이드 버 전 임 을 알 수 있 습 니 다.업그레이드 버 전이 라면 ViewPager 에 비해 어떤 새로운 기능 과 어떤 API 변화 가 있 습 니까?우 리 는 이어서 아래 를 내 려 다 보 았 다.
1.ViewPager 2 새로운 기능
4.567917.RecyclerView 를 바탕 으로 이 루어 집 니 다.이것 은 RecyclerView 의 장점 이 ViewPager 2 에 의 해 계승 된다 는 것 을 의미한다4.567917.수직 미끄럼 을 지원 합 니 다.하나의 인자 만 있 으 면 미끄럼 방향 을 바 꿀 수 있다사용자 입력 을 닫 는 것 을 지원 합 니 다.setUserInput Enabled 를 통 해 사용자 가 페이지 를 미 끄 러 뜨리 는 것 을 금지 할 지 여 부 를 설정 합 니 다
  • 프로 그래 밍 방식 으로 스크롤 하 는 것 을 지원 합 니 다.fakeDragBy(offsetPx)코드 를 통 해 사용자 가 페이지 를 미 끄 러 지 는 것 을 모 의 합 니 다
  • Composite PageTransformer 는 여러 개의 PageTransformer 를 동시에 추가 할 수 있 습 니 다
  • DiffUtil 을 지원 합 니 다.데이터 집합 이 변 경 된 item 애니메이션 을 추가 할 수 있 습 니 다
  • RTL(right-to-left)레이아웃 을 지원 합 니 다.나 는 이 기능 이 국내 개발 자 들 에 게 큰 도움 이 되 지 않 을 것 이 라 고 생각한다.
  • 2.ViewPager 에 비해 달라 진 API
    ViewPager 2 는 ViewPager 에 비해 어떤 변화 가 있 었 나 요?한 번 연구 한 후에 나 는 대략 다음 과 같은 몇 가 지 를 열거 했다.
  • ViewPager 2 는 ViewPager 와 함께 ViewGrop 에서 계승 되 었 으 나 ViewPager 2 는 final 로 성명 되 었 다.더 이상 ViewPager 처럼 계승 을 통 해 ViewPager 2 의 코드 를 수정 할 수 없다 는 뜻 입 니 다
  • Fragment StatePagerAdapter 가 Fragment StateAdapter 로 대체 되 었 습 니 다
  • PagerAdapter 는 RecyclerView.Adapter 로 대체 되 었 습 니 다
  • addPageChangeListener 가 registerOnPageChangeCallback 에 등록 되 었 습 니 다.ViewPager 의 addPageChangeListener 는 OnPageChangeListener 의 인 터 페 이 스 를 받 는 것 을 알 고 있 습 니 다.이 인터페이스 에는 세 가지 방법 이 있 습 니 다.페이지 변 화 를 감청 하려 면 이 세 가지 방법 을 다시 써 야 합 니 다.한편,ViewPager 2 의 registerOnPageChange Callback 방법 은 OnPageChange Callback 이라는 추상 적 인 유형 을 받 아들 이기 때문에 우 리 는 필요 한 방법 을 선택적으로 다시 쓸 수 있다
  • setPargeMargin 방법 을 제거 하 였 습 니 다.
    위 에 나 열 된 새로운 기능 과 API 가 완전 하지 않 을 수 있 습 니 다.누락 이 있 으 면 메 시 지 를 남 겨 보충 할 수 있 습 니 다.
    2.ViewPager 2 의 여행 시작
    ViewPager 2 는 androidx 패키지 에 있 습 니 다.즉,ViewPager 처럼 시스템 소스 코드 에 내장 되 어 있 지 않 습 니 다.따라서 ViewPager 2 를 사용 하려 면 의존 라 이브 러 리 를 추가 해 야 합 니 다.또한,android support 에는 ViewPager 가 포함 되 어 있 지 않 습 니 다.즉,ViewPager 2 를 사용 하려 면 androidx 로 이전 해 야 합 니 다.
    1.의존 도 를 추가 합 니 다.현재 ViewPager 2 의 최신 버 전 은 1.0.0 입 니 다.
    
    dependencies {
      implementation "androidx.viewpager2:viewpager2:1.0.0"
    }
    2.ViewPager 2 레이아웃 파일:
    
    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/view_pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    3.ViewPager 2 의 Adapter
    ViewPager 2 내부 에 RecyclerView 가 봉 인 돼 있 기 때문에 Adapter 는 RecyclerView 의 Adapter 입 니 다.
    
    class MyAdapter : RecyclerView.Adapter<MyAdapter.PagerViewHolder>() {
      private var mList: List<Int> = ArrayList()
      override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PagerViewHolder {
        val itemView = LayoutInflater.from(parent.context).inflate(R.layout.item_page, parent, false)
        return PagerViewHolder(itemView)
      }
    
      override fun onBindViewHolder(holder: PagerViewHolder, position: Int) {
        holder.bindData(mList[position])
      }
    
      fun setList(list: List<Int>) {
        mList = list
      }
    
      override fun getItemCount(): Int {
        return mList.size
      }
    	//	ViewHolder    RecycleView.ViewHolder
      class PagerViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        private val mTextView: TextView = itemView.findViewById(R.id.tv_text)
        private var colors = arrayOf("#CCFF99","#41F1E5","#8D41F1","#FF99CC")
    
        fun bindData(i: Int) {
          mTextView.text = i.toString()
          mTextView.setBackgroundColor(Color.parseColor(colors[i]))
        }
      }
    }
    item_페이지 의 코드 는 다음 과 같 습 니 다:
    
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:gravity="center">
    
      <TextView
        android:id="@+id/tv_text"
        android:background="@color/colorPrimaryDark"
        android:layout_width="match_parent"
        android:layout_height="280dp"
        android:gravity="center"
        android:textColor="#ffffff"
        android:textSize="22sp" />
    </LinearLayout>
    4.Activity 에서 ViewPager 에 Adapter 설정
    간단하게 ViewPager 기능 을 완 성 했 습 니 다.효과 가 어떤 지 보 겠 습 니 다.

    5.ViewPager 2 수직 미끄럼
    다음 에 우 리 는 한 줄 의 코드 를 통 해 수직 미끄럼 을 설정 합 니 다.
    
    viewPager2.orientation = ViewPager2.ORIENTATION_VERTICAL
    세로 슬라이딩 용 뷰 페 거 는 실현 하기 어렵 지만 뷰 페 거 2 를 통 해 하나의 인자 만 설정 하면 된다.효과 보기:

    6.페이지 슬라이딩 이벤트 감청
    위 에서 언급 한 바 와 같이 저 희 는 ViewPager 에 페이지 가 미 끄 러 지 는 감청 사건 을 설정 하기 위해 세 가지 방법 을 다시 써 야 합 니 다.ViewPager 2 에 감청 사건 을 설정 하기 위해 필요 한 방법 만 다시 쓰 면 됩 니 다.ViewPager 2 에서 OnPage Change Callback 은 추상 적 인 유형 이기 때 문 입 니 다.
    
    viewPager2.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
          override fun onPageSelected(position: Int) {
            super.onPageSelected(position)
            Toast.makeText(this@MainActivity, "page selected $position", Toast.LENGTH_SHORT).show()
          }
        })
    7.setUser Input Enabled 와 fakeDragBy
    ViewPager 를 사용 할 때 사용자 가 미 끄 러 지 는 것 을 금지 하려 면 ViewPager 의 onInterceptTouchEvent 를 다시 써 야 한 다 는 것 을 알 고 있 습 니 다.ViewPager 2 는 final 을 위해 더 이상 ViewPager 2 를 계승 할 수 없다 고 밝 혔 다.그러면 우 리 는 ViewPager 2 의 미끄럼 을 어떻게 금지 해 야 합 니까?사실 ViewPager 2 에서 이 기능 을 제 공 했 습 니 다.setUser Input Enabled 를 통 해 만 가능 합 니 다.
    
    viewPager2.isUserInputEnabled = false
    동시에 ViewPager 2 는 fake DragBy 방법 을 추가 했다.이 방법 을 통 해 끌 기 를 모 의 할 수 있다.fakeDragby 를 사용 하기 전에 먼저 beginFakeDrag 방법 으로 아 날로 그 드래그 를 켜 야 합 니 다.fakeDragBy 는 boolean 값 을 되 돌려 줍 니 다.true 는 fake drag 가 실행 되 고 있 음 을 표시 하고 false 로 돌아 가 현재 fake drag 가 실행 되 고 있 지 않 음 을 표시 합 니 다.우 리 는 코드 를 통 해 시도 해 보 자.
    
    fun fakeDragBy(view: View) {
        viewPager2.beginFakeDrag()
        if (viewPager2.fakeDragBy(-310f))
          viewPager2.endFakeDrag()
      }
    fakeDragBy 가 float 의 인 자 를 받 아들 이 는 것 을 주의해 야 합 니 다.매개 변수 가 양수 일 때 한 페이지 앞으로 미 끄 러 지 는 것 을 표시 하고,마이너스 일 때 다음 페이지 가 미 끄 러 지 는 것 을 표시 합 니 다.
    효과 도 를 살 펴 보 겠 습 니 다:

    데모 그림 에 서 는 사용자 의 입력 이 금지 되 어 있 으 며,단 추 를 누 르 면 사용자 가 미 끄 러 지 는 것 을 모 의 할 수 있 습 니 다.
    3.ViewPager 2 의 PageTransformer
    ViewPager 에 비해 ViewPager 2 의 Transformer 기능 이 크게 확장 되 었 습 니 다.ViewPager 2 는 PageTransformer 를 통 해 페이지 애니메이션 을 설정 할 수 있 을 뿐만 아니 라 PageTransformer 로 페이지 간격 을 설정 하고 여러 개의 PageTransformer 를 추가 할 수 있 습 니 다.이제 ViewPager 2 의 PageTransformer 를 만 나 보 겠 습 니 다!
    1.setPageMargin
    제1장 에서 ViewPager 2 가 setPageMargin 을 제거 하 는 방법 을 언급 했 습 니 다.그러면 ViewPager 2 에 페이지 간격 을 어떻게 설정 합 니까?사실 ViewPager 2 에서 MarginPageTransformer 를 제 공 했 습 니 다.ViewPager 2 의 setPageTransformer 방법 을 통 해 페이지 간격 을 설정 할 수 있 습 니 다.코드 는 다음 과 같 습 니 다:
    
    viewPager2.setPageTransformer(MarginPageTransformer(resources.getDimension(R.dimen.dp_10).toInt()))
    위 코드 는 ViewPager 2 에 10dp 의 페이지 간격 을 설정 합 니 다.효 과 는 다음 과 같 습 니 다:

    2.Composite PageTransformer 인식
    이 럴 때 ViewPager 2 에 페이지 간격 을 설정 한 후에 페이지 애니메이션 의 Transformer 를 설정 하려 면 어떻게 해 야 합 니까?이 럴 때 는 Composite Page Transformer 가 나 와 야 합 니 다.이름 에서 도 알 수 있 듯 이 그것 은 그룹의 PageTransformer 이다.맞아요.Composite PageTransformer 는 PageTransformer 인 터 페 이 스 를 실 현 했 고 그 내부 에서 List 집합 을 유 지 했 습 니 다.우 리 는 여러 개의 PageTransformer 를 Composite PageTransformer 에 추가 할 수 있 습 니 다.
    
    val compositePageTransformer = CompositePageTransformer()
        compositePageTransformer.addTransformer(ScaleInTransformer())
        compositePageTransformer.addTransformer(MarginPageTransformer(resources.getDimension(R.dimen.dp_10).toInt()))
        viewPager2.setPageTransformer(compositePageTransformer)
    상기 코드 에서 저 희 는 Composite PageTransformer 를 통 해 ViewPager 에 MarginPageTransformer 와 페이지 크기 를 조정 하 는 Scale InTransformer 를 설정 하 였 습 니 다.효과 보기:

    3.ViewPager 2 의 PageTransformer
    PageTransformer 는 ViewPager 2 에 있 는 인터페이스 이기 때문에 ViewPager 2 의 PageTransformer 는 ViewPager 에 독립 되 어 있 으 며 ViewPager 의 PageTransformer 와 아무런 관계 가 없습니다.그럼 에 도 불구 하고 걱정 할 필 요 는 없다.ViewPager 2 의 PageTransformer 와 ViewPager 의 PageTransformer 실현 방식 이 똑 같 기 때문이다.다음 소절 에 사 용 된 Scale InTransformer 를 살 펴 보 겠 습 니 다.
    
    class ScaleInTransformer : ViewPager2.PageTransformer {
      private val mMinScale = DEFAULT_MIN_SCALE
      override fun transformPage(view: View, position: Float) {
        view.elevation = -abs(position)
        val pageWidth = view.width
        val pageHeight = view.height
    
        view.pivotY = (pageHeight / 2).toFloat()
        view.pivotX = (pageWidth / 2).toFloat()
        if (position < -1) {
          view.scaleX = mMinScale
          view.scaleY = mMinScale
          view.pivotX = pageWidth.toFloat()
        } else if (position <= 1) {
          if (position < 0) {
            val scaleFactor = (1 + position) * (1 - mMinScale) + mMinScale
            view.scaleX = scaleFactor
            view.scaleY = scaleFactor
            view.pivotX = pageWidth * (DEFAULT_CENTER + DEFAULT_CENTER * -position)
          } else {
            val scaleFactor = (1 - position) * (1 - mMinScale) + mMinScale
            view.scaleX = scaleFactor
            view.scaleY = scaleFactor
            view.pivotX = pageWidth * ((1 - position) * DEFAULT_CENTER)
          }
        } else {
          view.pivotX = 0f
          view.scaleX = mMinScale
          view.scaleY = mMinScale
        }
      }
    
      companion object {
    
        const val DEFAULT_MIN_SCALE = 0.85f
        const val DEFAULT_CENTER = 0.5f
      }
    }
    4.ViewPager 2 의 한 화면 여러 페이지 효과
    ViewPager 2 의 공식 Sample 에서 ViewPager 2 의 한 화면 여러 페이지 를 보 았 습 니 다.RecyclerView 에 Padding 을 설정 하여 실현 할 수 있 습 니 다.코드 는 다음 과 같 습 니 다:
    
    viewPager2.apply { 
          offscreenPageLimit=1
          val recyclerView= getChildAt(0) as RecyclerView
          recyclerView.apply {
            val padding = resources.getDimensionPixelOffset(R.dimen.dp_10) +
                resources.getDimensionPixelOffset(R.dimen.dp_10)
            // setting padding on inner RecyclerView puts overscroll effect in the right place
            setPadding(padding, 0, padding, 0)
            clipToPadding = false
          }
        }
    val compositePageTransformer = CompositePageTransformer()
    compositePageTransformer.addTransformer(ScaleInTransformer())
    compositePageTransformer.addTransformer(MarginPageTransformer(resources.getDimension(R.dimen.dp_10).toInt()))
    viewPager2.setPageTransformer(compositePageTransformer)
    마지막 으로 효 과 를 살 펴 보 자.

    4.ViewPager 2 와 Fragment
    앞에서 도 ViewPager 2 에 추 가 된 Fragment StateAdapter 가 ViewPager 의 Fragment StatePager Adapter 를 대체 했다 고 언급 했 습 니 다.그러면 우 리 는 ViewPager 2 로 Activity 에 포 함 된 Fragment 의 인 스 턴 스 를 실현 합 니 다.
    1.Activity 의 layout 에 ViewPager 2 추가
    
    <androidx.viewpager2.widget.ViewPager2
          android:id="@+id/vp_fragment"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:layout_above="@id/rg_tab" />
    2.FragmentStateAdapter 실현
    
    class AdapterFragmentPager(fragmentActivity: FragmentActivity) : FragmentStateAdapter(fragmentActivity) {
    
      private val fragments: SparseArray<BaseFragment> = SparseArray()
    
      init {
        fragments.put(PAGE_HOME, HomeFragment.getInstance())
        fragments.put(PAGE_FIND, PageFragment.getInstance())
        fragments.put(PAGE_INDICATOR, IndicatorFragment.getInstance())
        fragments.put(PAGE_OTHERS, OthersFragment.getInstance())
      }
    
      override fun createFragment(position: Int): Fragment {
        var fragment: Fragment
        when (position) {
          PAGE_HOME -> {
            if (fragments.get(PAGE_HOME) == null) {
              fragment = HomeFragment.getInstance();
              fragments.put(PAGE_HOME, fragment)
            } else {
              fragment = fragments.get(PAGE_HOME)
            }
          }
          PAGE_FIND -> {
            if (fragments.get(PAGE_FIND) == null) {
              fragment = PageFragment.getInstance();
              fragments.put(PAGE_FIND, fragment)
            } else {
              fragment = fragments.get(PAGE_FIND)
            }
          }
    
          PAGE_INDICATOR -> {
            if (fragments.get(PAGE_INDICATOR) == null) {
              fragment = IndicatorFragment.getInstance();
              fragments.put(PAGE_INDICATOR, fragment)
            } else {
              fragment = fragments.get(PAGE_INDICATOR)
            }
          }
    
          PAGE_OTHERS -> {
            if (fragments.get(PAGE_OTHERS) == null) {
              fragment = OthersFragment.getInstance();
              fragments.put(PAGE_OTHERS, fragment)
            } else {
              fragment = fragments.get(PAGE_OTHERS)
            }
          }
          else -> {
            if (fragments.get(PAGE_HOME) == null) {
              fragment = HomeFragment.getInstance();
              fragments.put(PAGE_HOME, fragment)
            } else {
              fragment = fragments.get(PAGE_HOME)
            }
          }
        }
        return fragment
      }
    
      override fun getItemCount(): Int {
        return fragments.size()
      }
    
      companion object {
    
        const val PAGE_HOME = 0
    
        const val PAGE_FIND = 1
    
        const val PAGE_INDICATOR = 2
    
        const val PAGE_OTHERS = 3
    
      }
    
    }
    3.Activity 에서 ViewPager 2 에 Fragment StateAdapter 설정
    
    vp_fragment.adapter = AdapterFragmentPager(this)
        vp_fragment.offscreenPageLimit = 3
        vp_fragment.isUserInputEnabled=false
    5.ViewPager 2 와 TabLayout
    TabLayout 도 프로젝트 에 자주 사용 되 는 컨트롤 입 니 다.ViewPager 와 함께 나타 납 니 다.그러면 ViewPager 2 에 대해 서 는 Tablayot 을 어떻게 사용 해 야 하나 요?이것 은 우리 가 새로운 종류의 TabLayoutMediator 를 알 아야 합 니 다.이 종 류 는 material-1.2.0 에서 추 가 된 종류 입 니 다.현재 material 가방 의 최신 버 전 은 1.2.0-alpha 03 이기 때문에 우 리 는 이 가방 을 단독으로 도입 해 야 합 니 다.다음 과 같이 의존 해 야 합 니 다.
    
    implementation 'com.google.android.material:material:1.2.0-alpha03'
    TabLayoutMediator 의 구조 방법 은 세 개의 인 자 를 받 고 첫 번 째 인 자 는 TabLayout 입 니 다.두 번 째 매개 변 수 는 ViewPager 2 입 니 다.세 번 째 매개 변 수 는 TabConfigurationStrategy 입 니 다.이것 은 인터페이스 입 니 다.이 인터페이스 에는 onConfigureTab(@NonNull TabLayout.Tab tab,int position)방법 이 있 습 니 다.첫 번 째 매개 변 수 는 현재 Tab 이 고 두 번 째 현재 position 입 니 다.원본 은 다음 과 같 습 니 다.
    
    public interface TabConfigurationStrategy {
     /**
      * Called to configure the tab for the page at the specified position. Typically calls {@link
      * TabLayout.Tab#setText(CharSequence)}, but any form of styling can be applied.
      *
      * @param tab The Tab which should be configured to represent the title of the item at the given
      *   position in the data set.
      * @param position The position of the item within the adapter's data set.
      */
     void onConfigureTab(@NonNull TabLayout.Tab tab, int position);
    }
    다음은 TabLayoutMediator 를 통 해 TabLayout 를 ViewPager 2 와 연결 할 수 있 습 니 다.
    
    TabLayoutMediator(tab_layout, view_pager) { tab, position ->
          //  Tab  Text
          tab.text = Card.DECK[position].toString()
        }.attach()
    사용 하기에 매우 간단 하고 실현 효 과 는 다음 그림 과 같다.

    소결
    이 글 에서 우 리 는 ViewPager 2 의 새로운 특성 과 그 용법 을 알 게 되 었 다.어쨌든 ViewPager 2 는 ViewPager 에 비해 성능 이 든 기능 이 든 모두 크게 향상 되 었 다.그래서 나 는 머지않아 ViewPager 2 가 반드시 ViewPager 를 대체 할 것 이 라 고 믿는다.그렇다면 ViewPager 2 를 프로젝트 에 사용 하 는 것 을 고려 해 보 셨 나 요?
    마지막 으로 추천 해 드릴 게 요.이것 은 ViewPager 를 바탕 으로 이 루어 진 강력 한 기능 을 가 진 무한 라 이브 러 리 입 니 다.앞으로 저 는 Banner ViewPager 3.0 버 전에 서 ViewPager 2 로 코드 를 재 구성 할 것 입 니 다.GitHub 에 오신 것 을 환영 합 니 다.
    BannerViewPager
    4 절 에서 ViewPager 2 와 Fragment 의 코드 는 다음 과 같 습 니 다.
    본문 은 원본 다운로드 와 관련된다.
    이상 은 ViewPager 2 의 사용 에 대한 상세 한 내용 을 깊이 이해 하 는 것 입 니 다.ViewPager 2 의 사용 튜 토리 얼 에 관 한 자 료 는 저희 의 다른 관련 글 을 주목 하 시기 바 랍 니 다!

    좋은 웹페이지 즐겨찾기