最近開發中須要作一個相似京東首頁那樣的廣告輪播效果,因而採用ViewPager本身自定義了一個輪播圖效果的View。html
主要原理就是利用定時任務器定時切換ViewPager的頁面。java
主頁面佈局實現以下:android
01.
<?xml version=
"1.0"
encoding=
"utf-8"
?>
02.
03.
<RelativeLayout xmlns:android=
"http://schemas.android.com/apk/res/android"
04.
android:layout_width=
"match_parent"
05.
android:layout_height=
"match_parent"
>
06.
07.
<android.support.v4.view.ViewPager
08.
android:id=
"@+id/viewPager"
09.
android:layout_width=
"match_parent"
10.
android:layout_height=
"match_parent"
/>
11.
12.
<LinearLayout
13.
android:layout_width=
"match_parent"
14.
android:layout_height=
"wrap_content"
15.
android:layout_alignParentBottom=
"true"
16.
android:padding=
"5dp"
17.
android:gravity=
"center"
18.
android:orientation=
"horizontal"
>
19.
20.
<View
21.
android:id=
"@+id/v_dot1"
22.
android:layout_width=
"8dp"
23.
android:layout_height=
"8dp"
24.
android:background=
"@drawable/dot_black"
/>
25.
26.
<View
27.
android:id=
"@+id/v_dot2"
28.
android:layout_width=
"8dp"
29.
android:layout_height=
"8dp"
30.
android:layout_marginLeft=
"5dp"
31.
android:background=
"@drawable/dot_white"
/>
32.
33.
<View
34.
android:id=
"@+id/v_dot3"
35.
android:layout_width=
"8dp"
36.
android:layout_height=
"8dp"
37.
android:layout_marginLeft=
"5dp"
38.
android:background=
"@drawable/dot_white"
/>
39.
40.
<View
41.
android:id=
"@+id/v_dot4"
42.
android:layout_width=
"8dp"
43.
android:layout_height=
"8dp"
44.
android:layout_marginLeft=
"5dp"
45.
android:background=
"@drawable/dot_white"
/>
46.
47.
<View
48.
android:id=
"@+id/v_dot5"
49.
android:layout_width=
"8dp"
50.
android:layout_height=
"8dp"
51.
android:layout_marginLeft=
"5dp"
52.
android:background=
"@drawable/dot_white"
/>
53.
54.
</LinearLayout>
55.
</RelativeLayout>
輪播效果視圖類代碼實現以下:ide
001.
package
com.czm.customview;
002.
003.
import
java.util.ArrayList;
004.
import
java.util.List;
005.
import
java.util.concurrent.Executors;
006.
import
java.util.concurrent.ScheduledExecutorService;
007.
import
java.util.concurrent.TimeUnit;
008.
009.
import
android.content.Context;
010.
import
android.graphics.drawable.Drawable;
011.
import
android.os.Handler;
012.
import
android.os.Message;
013.
import
android.os.Parcelable;
014.
import
android.support.v4.view.PagerAdapter;
015.
import
android.support.v4.view.ViewPager;
016.
import
android.support.v4.view.ViewPager.OnPageChangeListener;
017.
import
android.util.AttributeSet;
018.
import
android.view.LayoutInflater;
019.
import
android.view.View;
020.
import
android.widget.FrameLayout;
021.
import
android.widget.ImageView;
022.
import
android.widget.ImageView.ScaleType;
023.
024.
025.
/**
026.
* ViewPager實現的輪播圖廣告自定義視圖,如京東首頁的廣告輪播圖效果;
027.
* 既支持自動輪播頁面也支持手勢滑動切換頁面
028.
* @author caizhiming
029.
*
030.
*/
031.
032.
public
class
SlideShowView
extends
FrameLayout {
033.
034.
//輪播圖圖片數量
035.
private
final
static
int
IMAGE_COUNT =
5
;
036.
//自動輪播的時間間隔
037.
private
final
static
int
TIME_INTERVAL =
5
;
038.
//自動輪播啓用開關
039.
private
final
static
boolean
isAutoPlay =
true
;
040.
041.
//自定義輪播圖的資源ID
042.
private
int
[] imagesResIds;
043.
//放輪播圖片的ImageView 的list
044.
private
List<ImageView> imageViewsList;
045.
//放圓點的View的list
046.
private
List<View> dotViewsList;
047.
048.
private
ViewPager viewPager;
049.
//當前輪播頁
050.
private
int
currentItem =
0
;
051.
//定時任務
052.
private
ScheduledExecutorService scheduledExecutorService;
053.
//Handler
054.
private
Handler handler =
new
Handler(){
055.
056.
@Override
057.
public
void
handleMessage(Message msg) {
058.
// TODO Auto-generated method stub
059.
super
.handleMessage(msg);
060.
viewPager.setCurrentItem(currentItem);
061.
}
062.
063.
};
064.
065.
public
SlideShowView(Context context) {
066.
this
(context,
null
);
067.
// TODO Auto-generated constructor stub
068.
}
069.
public
SlideShowView(Context context, AttributeSet attrs) {
070.
this
(context, attrs,
0
);
071.
// TODO Auto-generated constructor stub
072.
}
073.
public
SlideShowView(Context context, AttributeSet attrs,
int
defStyle) {
074.
super
(context, attrs, defStyle);
075.
// TODO Auto-generated constructor stub
076.
initData();
077.
initUI(context);
078.
if
(isAutoPlay){
079.
startPlay();
080.
}
081.
082.
}
083.
/**
084.
* 開始輪播圖切換
085.
*/
086.
private
void
startPlay(){
087.
scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
088.
scheduledExecutorService.scheduleAtFixedRate(
new
SlideShowTask(),
1
,
4
, TimeUnit.SECONDS);
089.
}
090.
/**
091.
* 中止輪播圖切換
092.
*/
093.
private
void
stopPlay(){
094.
scheduledExecutorService.shutdown();
095.
}
096.
/**
097.
* 初始化相關Data
098.
*/
099.
private
void
initData(){
100.
imagesResIds =
new
int
[]{
101.
R.drawable.pic1,
102.
R.drawable.pic2,
103.
R.drawable.pic3,
104.
R.drawable.pic4,
105.
R.drawable.pic5,
106.
107.
};
108.
imageViewsList =
new
ArrayList<ImageView>();
109.
dotViewsList =
new
ArrayList<View>();
110.
111.
}
112.
/**
113.
* 初始化Views等UI
114.
*/
115.
private
void
initUI(Context context){
116.
LayoutInflater.from(context).inflate(R.layout.layout_slideshow,
this
,
true
);
117.
for
(
int
imageID : imagesResIds){
118.
ImageView view =
new
ImageView(context);
119.
view.setImageResource(imageID);
120.
view.setScaleType(ScaleType.FIT_XY);
121.
imageViewsList.add(view);
122.
}
123.
dotViewsList.add(findViewById(R.id.v_dot1));
124.
dotViewsList.add(findViewById(R.id.v_dot2));
125.
dotViewsList.add(findViewById(R.id.v_dot3));
126.
dotViewsList.add(findViewById(R.id.v_dot4));
127.
dotViewsList.add(findViewById(R.id.v_dot5));
128.
129.
viewPager = (ViewPager) findViewById(R.id.viewPager);
130.
viewPager.setFocusable(
true
);
131.
132.
viewPager.setAdapter(
new
MyPagerAdapter());
133.
viewPager.setOnPageChangeListener(
new
MyPageChangeListener());
134.
}
135.
136.
/**
137.
* 填充ViewPager的頁面適配器
138.
* @author caizhiming
139.
*/
140.
private
class
MyPagerAdapter
extends
PagerAdapter{
141.
142.
@Override
143.
public
void
destroyItem(View container,
int
position, Object object) {
144.
// TODO Auto-generated method stub
145.
//((ViewPag.er)container).removeView((View)object);
146.
((ViewPager)container).removeView(imageViewsList.get(position));
147.
}
148.
149.
@Override
150.
public
Object instantiateItem(View container,
int
position) {
151.
// TODO Auto-generated method stub
152.
((ViewPager)container).addView(imageViewsList.get(position));
153.
return
imageViewsList.get(position);
154.
}
155.
156.
@Override
157.
public
int
getCount() {
158.
// TODO Auto-generated method stub
159.
return
imageViewsList.size();
160.
}
161.
162.
@Override
163.
public
boolean
isViewFromObject(View arg0, Object arg1) {
164.
// TODO Auto-generated method stub
165.
return
arg0 == arg1;
166.
}
167.
@Override
168.
public
void
restoreState(Parcelable arg0, ClassLoader arg1) {
169.
// TODO Auto-generated method stub
170.
171.
}
172.
173.
@Override
174.
public
Parcelable saveState() {
175.
// TODO Auto-generated method stub
176.
return
null
;
177.
}
178.
179.
@Override
180.
public
void
startUpdate(View arg0) {
181.
// TODO Auto-generated method stub
182.
183.
}
184.
185.
@Override
186.
public
void
finishUpdate(View arg0) {
187.
// TODO Auto-generated method stub
188.
189.
}
190.
191.
}
192.
/**
193.
* ViewPager的監聽器
194.
* 當ViewPager中頁面的狀態發生改變時調用
195.
* @author caizhiming
196.
*/
197.
private
class
MyPageChangeListener
implements
OnPageChangeListener{
198.
199.
boolean
isAutoPlay =
false
;
200.
201.
@Override
202.
public
void
onPageScrollStateChanged(
int
arg0) {
203.
// TODO Auto-generated method stub
204.
switch
(arg0) {
205.
case
1
:
// 手勢滑動,空閒中
206.
isAutoPlay =
false
;
207.
break
;
208.
case
2
:
// 界面切換中
209.
isAutoPlay =
true
;
210.
break
;
211.
case
0
:
// 滑動結束,即切換完畢或者加載完畢
212.
// 當前爲最後一張,此時從右向左滑,則切換到第一張
213.
if
(viewPager.getCurrentItem() == viewPager.getAdapter().getCount() -
1
&& !isAutoPlay) {
214.
viewPager.setCurrentItem(
0
);
215.
}
216.
// 當前爲第一張,此時從左向右滑,則切換到最後一張
217.
else
if
(viewPager.getCurrentItem() ==
0
&& !isAutoPlay) {
218.
viewPager.setCurrentItem(viewPager.getAdapter().getCount() -
1
);
219.
}
220.
break
;
221.
}
222.
}
223.
224.
@Override
225.
public
void
onPageScrolled(
int
arg0,
float
arg1,
int
arg2) {
226.
// TODO Auto-generated method stub
227.
228.
}
229.
230.
@Override
231.
public
void
onPageSelected(
int
pos) {
232.
// TODO Auto-generated method stub
233.
234.
currentItem = pos;
235.
for
(
int
i=
0
;i < dotViewsList.size();i++){
236.
if
(i == pos){
237.
((View)dotViewsList.get(pos)).setBackgroundResource(R.drawable.dot_black);
238.
}
else
{
239.
((View)dotViewsList.get(i)).setBackgroundResource(R.drawable.dot_white);
240.
}
241.
}
242.
}
243.
244.
}
245.
246.
/**
247.
*執行輪播圖切換任務
248.
*@author caizhiming
249.
*/
250.
private
class
SlideShowTask
implements
Runnable{
251.
252.
@Override
253.
public
void
run() {
254.
// TODO Auto-generated method stub
255.
synchronized
(viewPager) {
256.
currentItem = (currentItem+
1
)%imageViewsList.size();
257.
handler.obtainMessage().sendToTarget();
258.
}
259.
}
260.
261.
}
262.
/**
263.
* 銷燬ImageView資源,回收內存
264.
* @author caizhiming
265.
*/
266.
private
void
destoryBitmaps() {
267.
268.
for
(
int
i =
0
; i < IMAGE_COUNT; i++) {
269.
ImageView imageView = imageViewsList.get(i);
270.
Drawable drawable = imageView.getDrawable();
271.
if
(drawable !=
null
) {
272.
//解除drawable對view的引用
273.
drawable.setCallback(
null
);
274.
}
275.
}
276.
}
277.
278.
}
如何引用上面自定義的輪播圖效果視圖View呢?其實很引用普通的View相似,實現以下:佈局
1.
<com.czm.customview.SlideShowView
2.
android:id=
"@+id/slideshowView"
3.
android:layout_width=
"335dp"
4.
android:layout_height=
"120dp"
5.
android:layout_centerHorizontal=
"true"
6.
/>