티스토리 뷰
앱에서 가장 많이 볼 수 있는 기능을 살펴보면 "좌우 스와이프" 기능을 쉽게 찾을 수 있는데요.
Android의 스와이프 기능은 다양한 구현 방법이 존재하는데 대표적으로 ViewPager 일 것입니다.
이번 포스트에서 공유 드릴 내용은 ViewPager을 이용한 "Carousel View Pager" 입니다.
![]() |
![]() |
위에 사진을 보면 현재 보여지는 화면과 좌우에 이전과 다음에 보여질 화면이 미리 보여집니다.
물론 이동도 가능하며 옆에 살짝 보이는 부분을 클릭을 통하여 화면에 대한 이벤트도 적용할 수 있습니다.
이 포스트에서는 이벤트 적용에 대한 부분은 생략을 할 것입니다.
(자세한 내용은 참고 사이트를 참고해주세요.)
"카드뷰"의 핵심 기능은 pager.setPagemargin() 입니다.
setPageMargin() 을 활용하여 Pager의 margin 값을 음수로 이동 시 위와 같은 화면이 보여질 것입니다.
1. CarouselPagerAdapter
Pager Adapter 부분으로 실질적으로 카드뷰 자체가 그려줄 때 설정하는 Adapter 입니다.
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
public class CarouselPagerAdapter extends PagerAdapter implements ViewPager.OnPageChangeListener {
private static final int FIRST_PAGE = 0;
private Context context;
private CarouselPagerLayout[] mRootLayout;
private int mCount = 0;
private List mImgList;
public CarouselPagerAdapter(Context context, List list) {
this.context = context;
this.mImgList = list;
mCount = mImgList.size();
mRootLayout = new CarouselPagerLayout[list.size()];
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
float scale = MainActivity.BIG_SCALE;
try {
//First item change BigSize.
if (position != FIRST_PAGE) {
scale = MainActivity.SMALL_SCALE;
}
position = position % mImgList.size();
} catch (Exception e) {
// TODO: handle exception
}
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(R.layout.carouse_adapter_cell, null);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
ImageView iv = Utils.findViewByIdFromView(view,R.id.img_pager,ImageView.class);
iv.setLayoutParams(layoutParams);
iv.setImageResource(mImgList.get(position));
iv.setPadding(15, 15, 15, 15);
mImgList.get(position);
mRootLayout[position] = (CarouselPagerLayout) view.findViewById(R.id.root);
mRootLayout[position].setScaleValue(scale);
container.addView(view, 0);
return view;
}
@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
try {
if (positionOffset >= 0f && positionOffset < 1f) {
CarouselPagerLayout cur = getRootView(position);
CarouselPagerLayout next = getRootView(position + 1);
cur.setScaleValue(MainActivity.BIG_SCALE - MainActivity.DIFF_SCALE * positionOffset);
next.setScaleValue(MainActivity.SMALL_SCALE + MainActivity.DIFF_SCALE * positionOffset);
}
}catch (Exception e){
e.printStackTrace();
}
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
@Override
public void onPageSelected(int i) {
}
@Override
public void onPageScrollStateChanged(int i) {
}
@Override
public void finishUpdate(ViewGroup container) {
super.finishUpdate(container);
}
@Override
public int getCount() {
if (mImgList != null) {
return mImgList.size();
}
return 0;
}
/**
* return 값에 따른 화면에 보여지는 결과가 달라진다.
* @param view
* @param o
* @return
*/
@Override
public boolean isViewFromObject(View view, Object o) {
return view == o;
}
private CarouselPagerLayout getRootView(int position){
return mRootLayout[position];
}
}
|
cs |
2. CarouselPagerLayout
카드뷰의 Layout 을 표현하며, Canvas의 Scale 값을 변화하여 카드뷰의 크기를 조절합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
pupublic class CarouselPagerLayout extends LinearLayout {
public CarouselPagerLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CarouselPagerLayout(Context context) {
super(context);
}
private float scale = MainActivity.BIG_SCALE;
public void setScaleValue(float scale){
this.scale = scale;
this.invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
int w = this.getWidth();
int h = this.getHeight();
canvas.scale(scale,scale,w/2,h/2);
super.onDraw(canvas);
}
}
|
ViewPager에서 사용할 View의 상태를 설정합니다.
3. MainActivity
Pager을 호출하고 카드뷰의 값을 설정합니다.
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
31
32
33
34
35
36
37
38
|
public class MainActivity extends Activity {
public static final float BIG_SCALE = 1.0f;
public static final float SMALL_SCALE = 0.9f;
public static final float DIFF_SCALE = BIG_SCALE - SMALL_SCALE;
CarouselPagerAdapter mAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewPager pager;
pager = Utils.findViewByIdFromActivity(this, R.id.pager1, ViewPager.class);
mAdapter = new CarouselPagerAdapter(this, setListInfo());
pager.setAdapter(mAdapter);
pager.setPageMargin(-getPagerMarginValue());
pager.addOnPageChangeListener(mAdapter);
mAdapter.notifyDataSetChanged();
}
/**
* Pager Margin 값을 설정한다.
* @return
* @throws Exception
*/
private int getPagerMarginValue() {
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
int pageMargin = (int) ((metrics.heightPixels / 9) * 2); //중요! 이 부분을 조절하여 margin 설정 가능
return pageMargin;
}
private List<Integer> setListInfo() {
return Arrays.asList(R.drawable.lighthouse, R.drawable.penguins,R.drawable.tulips);
}
}
|
4. activity_main.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<Linearlayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v4.view.Viewpager
android:id="@+id/pager1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:overscrollmode="never">
</android.support.v4.view.Viewpager>
</Linearlayout >
|
5. carouse_adapter_cell.xml
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
<Linearlayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:paddingleft="20dp"
android:paddingright="20dp"
android:orientation="vertical">
<com.test.carouseexample.carouselpagerlayout
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/transparent"
android:gravity="center"
android:layout_margin="15dp"
android:orientation="vertical">
<Framelayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<Linearlayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<Imageview
android:id="@+id/img_pager"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp">
<Textview
android:id="@+id/txt_context"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margintop="-50dp"
android:gravity="center"
android:text=""
android:textcolor="#000"
android:textsize="20dp">
</Textview >
</Linearlayout >
</Framelayout>
</com.testcarouseexample.carouselpagerlayout>
</Linearlayout >
|
Github에 오픈되어 있던 CarouselViewProject 을 참고하여 샘플 프로젝트로 만들어 공유 드렸습니다.
참고
'프로그래밍 > Android' 카테고리의 다른 글
[Android] Full Screen 모드 전환 (0) | 2017.12.18 |
---|---|
[Android] [버그이슈] 앱 빌드 시도 시 아무런 동작 안하는 이슈 (0) | 2017.12.18 |
[Android] 해상도에 따른 UI 구성에 필요한 도구 (0) | 2017.12.18 |
[Android] 화면 회전 상태 확인 방법 (0) | 2017.12.18 |
[Android] 안드로이드 빌드 시 리소스 자동화(android build automated resources) (0) | 2017.12.18 |
- 패턴
- 선교
- missionchina
- flutter
- Android Studio
- Android
- java
- 탁구
- DI
- 코틀린
- 스코어헬퍼
- IT
- swift
- 고시문
- 점수판
- 고시문헬퍼
- Kotlin
- 미션차이나센터
- IOS
- missioon
- 알고리즘
- MCC
- RXjava
- 임용고시
- 디자인패턴
- 안드로이드
- view
- push
- issue
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |