티스토리 뷰
앱에서 가장 많이 볼 수 있는 기능을 살펴보면 "좌우 스와이프" 기능을 쉽게 찾을 수 있는데요.
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 |
- 알고리즘
- 안드로이드
- Android Studio
- missioon
- flutter
- 탁구
- 점수판
- view
- DI
- IOS
- 고시문
- 고시문헬퍼
- Android
- push
- 임용고시
- 스코어헬퍼
- IT
- 선교
- java
- swift
- missionchina
- 디자인패턴
- Kotlin
- RXjava
- 코틀린
- 패턴
- 미션차이나센터
- MCC
- 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 | 31 |