우리는 간단하게 이미지를 나열하기 위하여 Viewpager를 사용합니다.
그렇다면 인스타그램처럼 여러 사진을 게시물로 게시할 때 아래와 같이 viewpager와 indicator를 함께 사용하기 위해서는 어떻게 해야 할까요?? (실제로는 react로 구현된 다른 라이브러리일 것입니다. 안드로이드의 예시..!)
아마 ViewPager를 만들고 indicator라이브러리를 사용하여 둘 사이의 listener 또는 callback을 달아줘야 할 입니다. 이러한 과정을 간소화한다면 어떨까라는 생각과 함께 viewpager와 indicator를 한 번에 생성할 수 있는 라이브러리를 만들게 되었습니다.
라이브러리의 이름은 SIViewPager..!
build.gradle에서 의존성만 추가하면 바로 사용하실 수 있습니다.
implementation 'com.myhome.siviewpager:siviewpager:1.0.1'
SIViewpager를 사용하기 위해서는 viewpager with indicator가 들어가고자 하는 레이아웃 xml에서 크기와 위치 등을 지정한 뒤 코드 단에서 SIPagerAdapter를 상속받은 커스텀 어댑터와 연결해주기만 하면 됩니다. 여기서 주의할 점은 커스텀 어댑터에서 instantiateItem메서드를 오버라이드 해야 동작한다는 점입니다.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/my_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/add_bt"/>
<Button
android:id="@+id/add_bt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="추가하기"
app:layout_constraintTop_toBottomOf="@id/my_text"
app:layout_constraintBottom_toTopOf="@id/siviewpager"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"/>
<com.myhome.siviewpager.SIViewPager
android:id="@+id/siviewpager"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintTop_toBottomOf="@id/add_bt"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintVertical_weight="1"
android:orientation="vertical"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<activity_main.xml>
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto">
<ImageView
android:id="@+id/my_image"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintVertical_weight="1"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/remove_bt"/>
<Button
android:id="@+id/remove_bt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="지우기"
app:layout_constraintTop_toBottomOf="@id/my_image"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<pager_item.xml>
package com.myhome.viewpagersample
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.myhome.siviewpager.SIViewPager
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
var index = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val siViewpager = findViewById<SIViewPager>(R.id.siviewpager)
val siPagerAdapter = MyPagerAdapter(applicationContext)
siPagerAdapter.addItem(R.drawable.ic_android_black_24dp)
siPagerAdapter.addItem(R.drawable.ic_assignment_black_24dp)
siViewpager.build(siPagerAdapter)
add_bt.setOnClickListener {
if(index % 2 == 0){
siPagerAdapter.addItem(R.drawable.ic_android_black_24dp)
}
else{
siPagerAdapter.addItem(R.drawable.ic_assignment_black_24dp)
}
index++
}
}
}
<MainActivity.kt>
package com.myhome.viewpagersample
import android.content.Context
import android.view.LayoutInflater
import android.view.ViewGroup
import com.myhome.siviewpager.SIPagerAdapter
import kotlinx.android.synthetic.main.pager_item.view.*
class MyPagerAdapter(context:Context): SIPagerAdapter() {
val context = context
override fun instantiateItem(container: ViewGroup, position: Int): Any {
val view = LayoutInflater.from(context).inflate(R.layout.pager_item, container, false)
view.my_image.setImageResource(items.get(position) as Int)
view.setTag(position)
container.addView(view)
view.remove_bt.setOnClickListener {
removeAt(position)
}
return view
}
}
<MyPagerAdapter.kt>
위의 예제에서는 이미지의 리소스인 Int값을 SIPAgerAdapter의 items에 삽입하였지만 items필드는 Any객체로 지정되어 있기 때문에 커스텀한 객체를 사용할 수도 있습니다. 여기서 view에 setTag를 하는 이유는 viewpager에서 item의 이동을 감지하거나 추가, 삭제가 될 경우 view에 접근하기 위한 position이 필요하기 때문입니다.(필수로 작성해야합니다)
위의 예제는 간단하게 viewpager를 만들고 새로운 이미지를 추가/제거하는 예제입니다. 라이브러리를 사용하시면서 문제가 발생한다면 피드백 주시면 정말 정말 감사드리겠습니다!!
[예제 실행화면]
위의 추가하기 버튼을 누르면 두가지의 이미지가 반복적으로 viewpager에 추가되고 indicator도 추가됩니다.
반대로 아래의 지우기 버튼을 누르면 현재 위치의 viewpager item이 삭제됩니다. indicator 또한 이전 또는 이후(인덱스가 0인경우) item으로 인덱스가 변경되고 삭제됩니다.
추가하기 버튼을 두번 누르고 마지막 인덱스로 viewpager item 이동
첫 이미지를 제외한 모든 item 삭제
전체 예제 코드 -> https://github.com/godsangin/SIViewPagerSample
SIViewPager -> https://github.com/godsangin/SIViewPager
'IT 프로그래밍-Android' 카테고리의 다른 글
DrawerLayout, NavigationView 사용 시 주의사항 (1) | 2020.04.01 |
---|---|
안드로이드 라이브러리 bintray 배포 시 주의할 점 (0) | 2020.03.18 |
Retrofit을 적용해서 데이터 불러오기 (0) | 2020.01.18 |
[Android] RecyclerView 무한스크롤(endless scroll) 만들기 (0) | 2020.01.16 |
[Android] Glide 라이브러리 gif파일 로드 (0) | 2020.01.10 |