일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 재택근무
- 테트리스
- 함수형 프로그래밍
- 자취필수템
- 한달독서
- T자형인재
- 북한살둘레길
- 캐치마인드
- 1일1커밋
- 슬기로운 온라인 게임
- 베드테이블
- 한달어스
- 프래그먼트
- 아비투스
- 브런치작가되기
- 안드로이드
- 커스텀린트
- 면접
- 끝말잇기
- 베드트레이
- 좌식테이블
- 한달브런치북만들기
- 소프시스
- 지지않는다는말
- 한단어의힘
- 목적 중심 리더십
- 소프시스 밤부 좌식 엑슬 테이블
- 목적중심리더십
- 리얼하다
- 어떻게 나답게 살 것인가
- Today
- Total
정상에서 IT를 외치다
[Android, Indicator] 뷰 페이저에 인디케이터 달기 본문
안녕하세요. 블랙진입니다.
이번시간에는 '뷰페이저 만들기' 포스팅에 이어서 인디케이터를 달아볼려고 합니다.
먼저 인디케이터가 무엇인지 봐야겠죠?
위 이미지 처럼 A ~ E 의 5개의 화면을 전환하는데 몇 번째 화면인지를 표시하기 위한 뷰가 인디케이터 입니다.
위 예제를 진행하기에 앞서 이전 "뷰페이저 만들기" 포스팅을 진행해 주셔합니다. 혹은 깃허브 주소에서 예제 파일을 다운받아 주세요.
그럼 간단한 인디케이터를 만드는 법에 대해 포스팅을 시작하겠습니다!!
1. CircleIndicator class 를 새로 만들어 줍니다.
class CircleIndicator: LinearLayout {
private var mContext: Context? = null
private var mDefaultCircle: Int = 0
private var mSelectCircle: Int = 0
private var imageDot: MutableList<ImageView> = mutableListOf()
// 4.5dp 를 픽셀 단위로 바꿉니다.
private val temp = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, 4.5f, resources.displayMetrics)
constructor(context: Context) : super(context) {
mContext = context
}
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
mContext = context
}
/**
* 기본 점 생성
* @param count 점의 갯수
* @param defaultCircle 기본 점의 이미지
* @param selectCircle 선택된 점의 이미지
* @param position 선택된 점의 포지션
*/
fun createDotPanel(count: Int, defaultCircle: Int, selectCircle: Int, position: Int) {
this.removeAllViews()
mDefaultCircle = defaultCircle
mSelectCircle = selectCircle
for (i in 0 until count) {
imageDot.add(ImageView(mContext).apply { setPadding(temp.toInt(), 0, temp.toInt(), 0) })
this.addView(imageDot[i])
}
//인덱스 선택
selectDot(position)
}
/**
* 선택된 점 표시
* @param position
*/
fun selectDot(position: Int) {
for (i in imageDot.indices) {
if (i == position) {
imageDot[i].setImageResource(mSelectCircle)
} else {
imageDot[i].setImageResource(mDefaultCircle)
}
}
}
}
주석을 참고 하시면 어렵지 않게 이해가 되실겁니다.
위 코드중 createDotPanel 함수를 통해 점의 이미지를 가져오는 부분이 있습니다. 이때 각 점들의 padding 값을 4.5dp로 설정하였습니다. 만약 패딩을 안주면 각 점들이 붙어 있는 현상이 발생하겠죠?
for (i in 0 until count) {
imageDot.add(ImageView(mContext).apply { setPadding(temp.toInt(), 0, temp.toInt(), 0) })
this.addView(imageDot[i])
}
setPadding 을 통해 각 점들의 간격을 설정하였습니다. 이때 temp 값은 4.5dp 를 픽셀로 변경한 값입니다.
코드를 통해 xml 을 수정할 때에는 크기 및 간격은 모두 픽셀로 변경해 주셔야 합니다.
2. activity_main.xml 에 생성한 커스텀 뷰 CircleIndicator 를 추가해 줍니다.
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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">
<android.support.v4.view.ViewPager
android:id="@+id/vpMainActivity"
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" />
<{package name}.CircleIndicator
android:id="@+id/ciMainActivity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="100dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</android.support.constraint.ConstraintLayout>
CircleIndicator 를 하단에서 100dp 떨어진 곳에 추가해주었습니다.
xml 에 커스텀 뷰를 추가해 줄 때에는 해당 뷰(CircleIndicator)의 위치를 전부 적어주어야합니다.
3. 추가해 줄 인디케이터 이미지를 생성해 줍니다.
indicator_dot_off.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid
android:color="#000"/>
<size
android:height="30dp"
android:width="30dp"/>
</shape>
30dp 크기의 검정색 원입니다.
indicator_dot_on.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid
android:color="#ff0"/>
<size
android:height="30dp"
android:width="30dp"/>
</shape>
30dp 크기의 노랑색 원입니다.
4. MainActivity 에 인디케이터를 연결해 줍니다.
class MainActivity : AppCompatActivity() {
private val adapter by lazy { MainAdapter(supportFragmentManager) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//init viewpager
vpMainActivity.adapter = MainActivity@adapter
vpMainActivity.addOnPageChangeListener(object : ViewPager.OnPageChangeListener{
override fun onPageScrollStateChanged(p0: Int) {
}
override fun onPageScrolled(p0: Int, p1: Float, p2: Int) {
}
override fun onPageSelected(p0: Int) {
ciMainActivity.selectDot(p0)
}
})
//init indicator
ciMainActivity.createDotPanel(5, R.drawable.indicator_dot_off, R.drawable.indicator_dot_on, 0)
}
}
위와 같이 만들면 5개의 인디케이터가 생성되고 뷰페이저 화면 전환을 표시해 줄 수 있습니다.
위 코드중에서 중요한 부분에 대해 설명 들어가겠습니다.~!
_1. 5개의 점을 가진 인디케이터 생성하기
ciMainActivity.createDotPanel(5, R.drawable.indicator_dot_off, R.drawable.indicator_dot_on, 0)
createDotPanel 를 통해 인디케이터를 초기화 해줍니다.
5개의 점을 가지고 있고 기본 점의 이미지는 indicaator_dot_off , 선택된 점의 이미지는 indicator_dot_on 입니다.
그리고 인디케이터를 생성할 때 선택되어질 점의 초기 포지션이 0 이라는 의미입니다.
_2. 뷰페이저의 화면전환에 반응하기
vpMainActivity.addOnPageChangeListener(object : ViewPager.OnPageChangeListener{
override fun onPageScrollStateChanged(p0: Int) {
}
override fun onPageScrolled(p0: Int, p1: Float, p2: Int) {
}
override fun onPageSelected(p0: Int) {
ciMainActivity.selectDot(p0)
}
})
뷰페이저의 addOnPageChangeListener 를 통해 화면 전환시 선택된 포지션 값을 받아올 수 있습니다.
위 오버라이팅 메소드 중 onPageSelected 는 화면 전환이 끝났을 때 해당 포지션을 반환합니다. 받은 포지션 p0 를 selectDot 에 넣어주어 해당 포지션을 선택된 점으로 변환하여 인디케이터 역활을 하게 만듭니다.
3번의 추가해줄 인디케이터 이미지를 원이 아닌 다른 이미지로 변경하면 원하는 모양의 인디케이터를 쉽게 만드실 수 있을 겁니다. 안뇨옹~!
위 예제 완성 코드 입니다.
'안드로이드' 카테고리의 다른 글
[Android, Lottie] Lottie 를 사용한 애니메이션 효과 (4) | 2018.09.12 |
---|---|
[Android, bitmap] 비트맵에 대한 탐구_이미지 자르기 (0) | 2018.09.06 |
[Android, ViewPager] 프래그먼트 뷰페이저 만들기 (0) | 2018.09.05 |
[Android] 그라데이션 효과 적용하기 (0) | 2018.08.31 |
[Android, Databinding] BindingAdapter 사용해 보기 (0) | 2018.08.28 |