在Eclipse中新建一个Android项目,项目名就叫做SlidingViewSwitcher。

新建一个类,名叫SlidingSwitcherView,这个类是继承自RelativeLayout的,并且实现了OnTouchListener接口,具体代码如下:


1. public class SlidingSwitcherView extends RelativeLayout implements OnTouchListener {  
2.   
3. /**
4.      * 让菜单滚动,手指滑动需要达到的速度。
5.      */  
6. public static final int SNAP_VELOCITY = 200;  
7.   
8. /**
9.      * SlidingSwitcherView的宽度。
10.      */  
11. private int switcherViewWidth;  
12.   
13. /**
14.      * 当前显示的元素的下标。
15.      */  
16. private int currentItemIndex;  
17.   
18. /**
19.      * 菜单中包含的元素总数。
20.      */  
21. private int itemsCount;  
22.   
23. /**
24.      * 各个元素的偏移边界值。
25.      */  
26. private int[] borders;  
27.   
28. /**
29.      * 最多可以滑动到的左边缘。值由菜单中包含的元素总数来定,marginLeft到达此值之后,不能再减少。
30.      * 
31.      */  
32. private int leftEdge = 0;  
33.   
34. /**
35.      * 最多可以滑动到的右边缘。值恒为0,marginLeft到达此值之后,不能再增加。
36.      */  
37. private int rightEdge = 0;  
38.   
39. /**
40.      * 记录手指按下时的横坐标。
41.      */  
42. private float xDown;  
43.   
44. /**
45.      * 记录手指移动时的横坐标。
46.      */  
47. private float xMove;  
48.   
49. /**
50.      * 记录手机抬起时的横坐标。
51.      */  
52. private float xUp;  
53.   
54. /**
55.      * 菜单布局。
56.      */  
57. private LinearLayout itemsLayout;  
58.   
59. /**
60.      * 标签布局。
61.      */  
62. private LinearLayout dotsLayout;  
63.   
64. /**
65.      * 菜单中的第一个元素。
66.      */  
67. private View firstItem;  
68.   
69. /**
70.      * 菜单中第一个元素的布局,用于改变leftMargin的值,来决定当前显示的哪一个元素。
71.      */  
72. private MarginLayoutParams firstItemParams;  
73.   
74. /**
75.      * 用于计算手指滑动的速度。
76.      */  
77. private VelocityTracker mVelocityTracker;  
78.   
79. /**
80.      * 重写SlidingSwitcherView的构造函数,用于允许在XML中引用当前的自定义布局。
81.      * 
82.      * @param context
83.      * @param attrs
84.      */  
85. public SlidingSwitcherView(Context context, AttributeSet attrs) {  
86. super(context, attrs);  
87.     }  
88.   
89. /**
90.      * 滚动到下一个元素。
91.      */  
92. public void scrollToNext() {  
93. new ScrollTask().execute(-20);  
94.     }  
95.   
96. /**
97.      * 滚动到上一个元素。
98.      */  
99. public void scrollToPrevious() {  
100. new ScrollTask().execute(20);  
101.     }  
102.   
103. /**
104.      * 在onLayout中重新设定菜单元素和标签元素的参数。
105.      */  
106. @Override  
107. protected void onLayout(boolean changed, int l, int t, int r, int b) {  
108. super.onLayout(changed, l, t, r, b);  
109. if (changed) {  
110.             initializeItems();  
111.             initializeDots();  
112.         }  
113.     }  
114.   
115. /**
116.      * 初始化菜单元素,为每一个子元素增加监听事件,并且改变所有子元素的宽度,让它们等于父元素的宽度。
117.      */  
118. private void initializeItems() {  
119.         switcherViewWidth = getWidth();  
120. 0);  
121.         itemsCount = itemsLayout.getChildCount();  
122. new int[itemsCount];  
123. for (int i = 0; i < itemsCount; i++) {  
124.             borders[i] = -i * switcherViewWidth;  
125.             View item = itemsLayout.getChildAt(i);  
126.             MarginLayoutParams params = (MarginLayoutParams) item.getLayoutParams();  
127.             params.width = switcherViewWidth;  
128.             item.setLayoutParams(params);  
129. this);  
130.         }  
131. 1];  
132. 0);  
133.         firstItemParams = (MarginLayoutParams) firstItem.getLayoutParams();  
134.     }  
135.   
136. /**
137.      * 初始化标签元素。
138.      */  
139. private void initializeDots() {  
140. 1);  
141.         refreshDotsLayout();  
142.     }  
143.   
144. @Override  
145. public boolean onTouch(View v, MotionEvent event) {  
146.         createVelocityTracker(event);  
147. switch (event.getAction()) {  
148. case MotionEvent.ACTION_DOWN:  
149. // 手指按下时,记录按下时的横坐标  
150.             xDown = event.getRawX();  
151. break;  
152. case MotionEvent.ACTION_MOVE:  
153. // 手指移动时,对比按下时的横坐标,计算出移动的距离,来调整左侧布局的leftMargin值,从而显示和隐藏左侧布局  
154.             xMove = event.getRawX();  
155. int distanceX = (int) (xMove - xDown) - (currentItemIndex * switcherViewWidth);  
156.             firstItemParams.leftMargin = distanceX;  
157. if (beAbleToScroll()) {  
158.                 firstItem.setLayoutParams(firstItemParams);  
159.             }  
160. break;  
161. case MotionEvent.ACTION_UP:  
162. // 手指抬起时,进行判断当前手势的意图,从而决定是滚动到左侧布局,还是滚动到右侧布局  
163.             xUp = event.getRawX();  
164. if (beAbleToScroll()) {  
165. if (wantScrollToPrevious()) {  
166. if (shouldScrollToPrevious()) {  
167.                         currentItemIndex--;  
168.                         scrollToPrevious();  
169.                         refreshDotsLayout();  
170. else {  
171.                         scrollToNext();  
172.                     }  
173. else if (wantScrollToNext()) {  
174. if (shouldScrollToNext()) {  
175.                         currentItemIndex++;  
176.                         scrollToNext();  
177.                         refreshDotsLayout();  
178. else {  
179.                         scrollToPrevious();  
180.                     }  
181.                 }  
182.             }  
183.             recycleVelocityTracker();  
184. break;  
185.         }  
186. return false;  
187.     }  
188.   
189. /**
190.      * 当前是否能够滚动,滚动到第一个或最后一个元素时将不能再滚动。
191.      * 
192.      * @return 当前leftMargin的值在leftEdge和rightEdge之间返回true,否则返回false。
193.      */  
194. private boolean beAbleToScroll() {  
195. return firstItemParams.leftMargin < rightEdge && firstItemParams.leftMargin > leftEdge;  
196.     }  
197.   
198. /**
199.      * 判断当前手势的意图是不是想滚动到上一个菜单元素。如果手指移动的距离是正数,则认为当前手势是想要滚动到上一个菜单元素。
200.      * 
201.      * @return 当前手势想滚动到上一个菜单元素返回true,否则返回false。
202.      */  
203. private boolean wantScrollToPrevious() {  
204. return xUp - xDown > 0;  
205.     }  
206.   
207. /**
208.      * 判断当前手势的意图是不是想滚动到下一个菜单元素。如果手指移动的距离是负数,则认为当前手势是想要滚动到下一个菜单元素。
209.      * 
210.      * @return 当前手势想滚动到下一个菜单元素返回true,否则返回false。
211.      */  
212. private boolean wantScrollToNext() {  
213. return xUp - xDown < 0;  
214.     }  
215.   
216. /**
217.      * 判断是否应该滚动到下一个菜单元素。如果手指移动距离大于屏幕的1/2,或者手指移动速度大于SNAP_VELOCITY,
218.      * 就认为应该滚动到下一个菜单元素。
219.      * 
220.      * @return 如果应该滚动到下一个菜单元素返回true,否则返回false。
221.      */  
222. private boolean shouldScrollToNext() {  
223. return xDown - xUp > switcherViewWidth / 2 || getScrollVelocity() > SNAP_VELOCITY;  
224.     }  
225.   
226. /**
227.      * 判断是否应该滚动到上一个菜单元素。如果手指移动距离大于屏幕的1/2,或者手指移动速度大于SNAP_VELOCITY,
228.      * 就认为应该滚动到上一个菜单元素。
229.      * 
230.      * @return 如果应该滚动到上一个菜单元素返回true,否则返回false。
231.      */  
232. private boolean shouldScrollToPrevious() {  
233. return xUp - xDown > switcherViewWidth / 2 || getScrollVelocity() > SNAP_VELOCITY;  
234.     }  
235.   
236. /**
237.      * 刷新标签元素布局,每次currentItemIndex值改变的时候都应该进行刷新。
238.      */  
239. private void refreshDotsLayout() {  
240.         dotsLayout.removeAllViews();  
241. for (int i = 0; i < itemsCount; i++) {  
242. new LinearLayout.LayoutParams(0,  
243.                     LayoutParams.FILL_PARENT);  
244. 1;  
245. new RelativeLayout(getContext());  
246. new ImageView(getContext());  
247. if (i == currentItemIndex) {  
248.                 image.setBackgroundResource(R.drawable.dot_selected);  
249. else {  
250.                 image.setBackgroundResource(R.drawable.dot_unselected);  
251.             }  
252. new RelativeLayout.LayoutParams(  
253.                     LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);  
254.             relativeParams.addRule(RelativeLayout.CENTER_IN_PARENT);  
255.             relativeLayout.addView(image, relativeParams);  
256.             dotsLayout.addView(relativeLayout, linearParams);  
257.         }  
258.     }  
259.   
260. /**
261.      * 创建VelocityTracker对象,并将触摸事件加入到VelocityTracker当中。
262.      * 
263.      * @param event
264.      *            右侧布局监听控件的滑动事件
265.      */  
266. private void createVelocityTracker(MotionEvent event) {  
267. if (mVelocityTracker == null) {  
268.             mVelocityTracker = VelocityTracker.obtain();  
269.         }  
270.         mVelocityTracker.addMovement(event);  
271.     }  
272.   
273. /**
274.      * 获取手指在右侧布局的监听View上的滑动速度。
275.      * 
276.      * @return 滑动速度,以每秒钟移动了多少像素值为单位。
277.      */  
278. private int getScrollVelocity() {  
279. 1000);  
280. int velocity = (int) mVelocityTracker.getXVelocity();  
281. return Math.abs(velocity);  
282.     }  
283.   
284. /**
285.      * 回收VelocityTracker对象。
286.      */  
287. private void recycleVelocityTracker() {  
288.         mVelocityTracker.recycle();  
289. null;  
290.     }  
291.   
292. /**
293.      * 检测菜单滚动时,是否有穿越border,border的值都存储在{@link #borders}中。
294.      * 
295.      * @param leftMargin
296.      *            第一个元素的左偏移值
297.      * @param speed
298.      *            滚动的速度,正数说明向右滚动,负数说明向左滚动。
299.      * @return 穿越任何一个border了返回true,否则返回false。
300.      */  
301. private boolean isCrossBorder(int leftMargin, int speed) {  
302. for (int border : borders) {  
303. if (speed > 0) {  
304. if (leftMargin >= border && leftMargin - speed < border) {  
305. return true;  
306.                 }  
307. else {  
308. if (leftMargin <= border && leftMargin - speed > border) {  
309. return true;  
310.                 }  
311.             }  
312.         }  
313. return false;  
314.     }  
315.   
316. /**
317.      * 找到离当前的leftMargin最近的一个border值。
318.      * 
319.      * @param leftMargin
320.      *            第一个元素的左偏移值
321.      * @return 离当前的leftMargin最近的一个border值。
322.      */  
323. private int findClosestBorder(int leftMargin) {  
324. int absLeftMargin = Math.abs(leftMargin);  
325. int closestBorder = borders[0];  
326. int closestMargin = Math.abs(Math.abs(closestBorder) - absLeftMargin);  
327. for (int border : borders) {  
328. int margin = Math.abs(Math.abs(border) - absLeftMargin);  
329. if (margin < closestMargin) {  
330.                 closestBorder = border;  
331.                 closestMargin = margin;  
332.             }  
333.         }  
334. return closestBorder;  
335.     }  
336.   
337. class ScrollTask extends AsyncTask<Integer, Integer, Integer> {  
338.   
339. @Override  
340. protected Integer doInBackground(Integer... speed) {  
341. int leftMargin = firstItemParams.leftMargin;  
342. // 根据传入的速度来滚动界面,当滚动穿越border时,跳出循环。  
343. while (true) {  
344. 0];  
345. if (isCrossBorder(leftMargin, speed[0])) {  
346.                     leftMargin = findClosestBorder(leftMargin);  
347. break;  
348.                 }  
349.                 publishProgress(leftMargin);  
350. // 为了要有滚动效果产生,每次循环使线程睡眠10毫秒,这样肉眼才能够看到滚动动画。  
351. 10);  
352.             }  
353. return leftMargin;  
354.         }  
355.   
356. @Override  
357. protected void onProgressUpdate(Integer... leftMargin) {  
358. 0];  
359.             firstItem.setLayoutParams(firstItemParams);  
360.         }  
361.   
362. @Override  
363. protected void onPostExecute(Integer leftMargin) {  
364.             firstItemParams.leftMargin = leftMargin;  
365.             firstItem.setLayoutParams(firstItemParams);  
366.         }  
367.     }  
368.   
369. /**
370.      * 使当前线程睡眠指定的毫秒数。
371.      * 
372.      * @param millis
373.      *            指定当前线程睡眠多久,以毫秒为单位
374.      */  
375. private void sleep(long millis) {  
376. try {  
377.             Thread.sleep(millis);  
378. catch (InterruptedException e) {  
379.             e.printStackTrace();  
380.         }  
381.     }  
382. }


细心的朋友可以看出来,我还是重用了很多之前的代码,这里有几个重要点我说一下。在onLayout方法里,重定义了各个包含图片的控件的大小,然后为每个包含图片的控件都注册了一个touch事件监听器。这样当我们滑动任何一样图片控件的时候,都会触发onTouch事件,然后通过改变第一个图片控件的leftMargin,去实现动画效果。之后在onLayout里又动态加入了页签View,有几个图片控件就会加入几个页签,然后根据currentItemIndex来决定高亮显示哪一个页签。其它也没什么要特别说明的了,更深的理解大家去看代码和注释吧。

然后看一下布局文件中如何使用我们自定义的这个控件,创建或打开activity_main.xml,里面加入如下代码:



1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
2. xmlns:tools="http://schemas.android.com/tools"  
3. android:layout_width="fill_parent"  
4. android:layout_height="fill_parent"  
5. android:orientation="horizontal"  
6. tools:context=".MainActivity" >  
7.   
8. <com.example.viewswitcher.SlidingSwitcherView  
9. android:id="@+id/slidingLayout"  
10. android:layout_width="fill_parent"  
11. android:layout_height="100dip" >  
12.   
13. <LinearLayout  
14. android:layout_width="fill_parent"  
15. android:layout_height="fill_parent"  
16. android:orientation="horizontal" >  
17.   
18. <Button  
19. android:layout_width="fill_parent"  
20. android:layout_height="fill_parent"  
21. android:background="@drawable/image1" />  
22.   
23. <Button  
24. android:layout_width="fill_parent"  
25. android:layout_height="fill_parent"  
26. android:background="@drawable/image2" />  
27.   
28. <Button  
29. android:layout_width="fill_parent"  
30. android:layout_height="fill_parent"  
31. android:background="@drawable/image3" />  
32.   
33. <Button  
34. android:layout_width="fill_parent"  
35. android:layout_height="fill_parent"  
36. android:background="@drawable/image4" />  
37. </LinearLayout>  
38.   
39. <LinearLayout  
40. android:layout_width="60dip"  
41. android:layout_height="20dip"  
42. android:layout_alignParentBottom="true"  
43. android:layout_alignParentRight="true"  
44. android:layout_margin="15dip"  
45. android:orientation="horizontal" >  
46. </LinearLayout>  
47. </com.example.viewswitcher.SlidingSwitcherView>  
48.   
49. </LinearLayout>


我们可以看到,com.example.viewswitcher.SlidingSwitcherView的根目录下放置了两个LinearLayout。第一个LinearLayout中要放入需要滚动显示的图片,这里我们加入了四个Button,每个Button都设置了一张背景图片。第二个LinearLayout中不需要加入任何东西,只要控制好大小和位置,标签会在运行的时候自动加入到这个layout中。

然后创建或打开MainActivity作为主界面,里面没有加入任何新增的代码:


1. public class MainActivity extends Activity {  
2.   
3. @Override  
4. protected void onCreate(Bundle savedInstanceState) {  
5. super.onCreate(savedInstanceState);  
6.         setContentView(R.layout.activity_main);  
7.     }  
8.   
9. }


最后是给出AndroidManifest.xml的代码,也都是自动生成的内容:


1. <?xml version="1.0" encoding="utf-8"?>  
2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
3. package="com.example.viewswitcher"  
4. android:versionCode="1"  
5. android:versionName="1.0" >  
6.   
7. <uses-sdk  
8. android:minSdkVersion="8"  
9. android:targetSdkVersion="8" />  
10.   
11. <application  
12. android:allowBackup="true"  
13. android:icon="@drawable/ic_launcher"  
14. android:label="@string/app_name"  
15. android:theme="@android:style/Theme.NoTitleBar" >  
16. <activity  
17. android:name="com.example.viewswitcher.MainActivity"  
18. android:label="@string/app_name" >  
19. <intent-filter>  
20. <action android:name="android.intent.action.MAIN" />  
21.   
22. <category android:name="android.intent.category.LAUNCHER" />  
23. </intent-filter>  
24. </activity>  
25. </application>  
26.   
27. </manifest>


好了,现在我们来看下运行效果吧,由于手机坏了,只能在模拟器上运行了。

首先是程序打开的时候,界面显示如下:

                       

Android 图片无限旋转动画_滚动

然后手指在图片上滑动,我们可以看到图片滚动的效果:

                       

Android 图片无限旋转动画_滚动_02

不停的翻页,页签也会跟着一起改变,下图中我们可以看到高亮显示的点是变换的:

                       

Android 图片无限旋转动画_滚动_03

恩,对比一下淘宝客户端的效果,我觉得我们模仿的还是挺好的。咦,好像少了点什么。。。。。。原来图片并不会自动播放。。。。。

既然是要加入自动播放的功能,那么就有一个非常重要的问题需要考虑。如果当前已经滚动到了最后一张图片,应该怎么办?由于我们目前的实现方案是,所有的图片都按照布局文件里面定义的顺序横向排列,然后通过偏移第一个图片的leftMargin,来决定显示哪一张图片。因此当图片滚动在最后一张时,我们可以让程序迅速地回滚到第一张图片,然后从头开始滚动。这种效果和淘宝客户端是有一定差异的(淘宝并没有回滚机制,而是很自然地由最后一张图片滚动到第一张图片),我也研究过淘宝图片滚动器的实现方法,并不难实现。但是由于我们是基于上次的代码进行开发的,方案上无法实现和淘宝客户端一样的效果,因此这里也就不追求和它完全一致了,各有风格也挺好的。

  好了,现在开始实现功能,首先是打开SlidingSwitcherView,在里面加入一个新的AsyncTask,专门用于回滚到第一张图片:
  

1.  [java] view plaincopyprint?
2.    class ScrollToFirstItemTask extends AsyncTask {
3.    @Override
4.    protected Integer doInBackground(Integer... speed) {
5.    int leftMargin = firstItemParams.leftMargin;
6.    while (true) {
7.    leftMargin = leftMargin + speed[0];
8.    // 当leftMargin大于0时,说明已经滚动到了第一个元素,跳出循环
9.    if (leftMargin > 0) {
10.    leftMargin = 0;
11.    break;
12.    }
13.    publishProgress(leftMargin);
14.    sleep(20);
15.    }
16.    return leftMargin;
17.    }
18.    @Override
19.    protected void onProgressUpdate(Integer... leftMargin) {
20.    firstItemParams.leftMargin = leftMargin[0];
21.    firstItem.setLayoutParams(firstItemParams);
22.    }
23.    @Override
24.    protected void onPostExecute(Integer leftMargin) {
25.    firstItemParams.leftMargin = leftMargin;
26.    firstItem.setLayoutParams(firstItemParams);
27.    }
28.    }
29.    然后在SlidingSwitcherView里面加入一个新的方法:
30.    [java] view plaincopyprint?
31.    /**
32.    * 滚动到第一个元素。
33.    */
34.    public void scrollToFirstItem() {
35.    new ScrollToFirstItemTask().execute(20 * itemsCount);
36.    }


复制代码


  这个方法非常简单,就是启动了我们新增的ScrollToFirstItemTask,滚动速度设定为20 * itemsCount,这样当我们需要滚动的图片数量越多,回滚速度就会越快。定义好这个方法后,只要在任意地方调用scrollToFirstItem这个方法,就可以立刻从当前图片回滚到第一张图片了。



  OK,然后我们要定义一个方法用于启动自动播放功能。仍然是在SlidingSwitcherView中新增如下代码:


  


    1.  [java] view plaincopyprint?
    2.    /**
    3.    * 用于在定时器当中操作UI界面。
    4.    */
    5.    private Handler handler = new Handler();
    6.    /**
    7.    * 开启图片自动播放功能,当滚动到最后一张图片的时候,会自动回滚到第一张图片。
    8.    */
    9.    public void startAutoPlay() {
    10.    new Timer().scheduleAtFixedRate(new TimerTask() {
    11.    @Override
    12.    public void run() {
    13.    if (currentItemIndex == itemsCount - 1) {
    14.    currentItemIndex = 0;
    15.    handler.post(new Runnable() {
    16.    @Override
    17.    public void run() {
    18.    scrollToFirstItem();
    19.    refreshDotsLayout();
    20.    }
    21.    });
    22.    } else {
    23.    currentItemIndex++;
    24.    handler.post(new Runnable() {
    25.    @Override
    26.    public void run() {
    27.    scrollToNext();
    28.    refreshDotsLayout();
    29.    }
    30.    });
    31.    }
    32.    }
    33.    }, 3000, 3000);
    34.    }


    复制代码


      我们可以看到,这个方法里启用了一个定时器,每隔三秒就会执行一次。然后在定时器的执行逻辑里面进行判断当前图片是否是最后一张,如果不是最后一张就滚动到下一张图片,如果是最后一张就回滚到第一张图片。其中需要注意,定时器中的代码是在子线程中运行的,而滚动图片操作和更新页签操作都是UI操作,因此需要放到Handler中去执行




      之后只要在Activity创建的时候去调用SlidingSwitcherView的startAutoPlay方法,自动播放功能就实现了!



      结束了?Naive!! 如果就这么结束了,怎么对得起大家的期待,如此简单的功能还要用一篇文章来讲简直是弱爆了。



      接下来才是今天的重点,我们要使用自定义属性来启用自动播放功能,这样才能让你更加接近高手,才能让你更加玩转Android。


      那我们继续,在res/values目录下新建一个attrs.xml文件,里面加入代码:


      

    复制代码


      其中,auto_play是我们将要使用的属性名,格式是布尔型。SlidingSwitcherView这个值可以随意,主要在代码中需要引用相应的id。



      然后重写SlidingSwitcherView的构造函数,在里面加入从布局文件中获取自定义属性的代码:


      

    1.  [java] view plaincopyprint?
    2.    public SlidingSwitcherView(Context context, AttributeSet attrs) {
    3.    super(context, attrs);
    4.    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SlidingSwitcherView);
    5.    boolean isAutoPlay = a.getBoolean(R.styleable.SlidingSwitcherView_auto_play, false);
    6.    if (isAutoPlay) {
    7.    startAutoPlay();
    8.    }
    9.    a.recycle();
    10.    }

    复制代码


      可以看到,我们在构造函数中去获取auto_play的值,如果为true,就调用startAutoPlay方法,从而启用了自动播放的功能。


      接下来就是见证奇迹的时刻!让我们打开activity_main.xml,在里面加入两行关键性代码。在最外层的LinearLayout加入xmlns:myattr="http://schemas.android.com/apk/res/com.example.viewswitcher"。在我们自定义的com.example.viewswitcher.SlidingSwitcherView加入myattr:auto_play="true"。



        完整XML代码如下:


      

    1.  [html] view plaincopyprint?
    2.    xmlns:tools="http://schemas.android.com/tools"
    3.    xmlns:myattr="http://schemas.android.com/apk/res/com.example.viewswitcher"
    4.    android:layout_width="fill_parent"
    5.    android:layout_height="fill_parent"
    6.    android:orientation="vertical"
    7.    tools:context=".MainActivity" >
    8.    android:id="@+id/slidingLayout"
    9.    myattr:auto_play="true"
    10.    android:layout_width="fill_parent"
    11.    android:layout_height="100dip" >
    12.    android:layout_width="fill_parent"
    13.    android:layout_height="fill_parent"
    14.    android:orientation="horizontal" >
    15.    android:layout_width="fill_parent"
    16.    android:layout_height="fill_parent"
    17.    android:background="@drawable/image1" />
    18.    android:layout_width="fill_parent"
    19.    android:layout_height="fill_parent"
    20.    android:background="@drawable/image2" />
    21.    android:layout_width="fill_parent"
    22.    android:layout_height="fill_parent"
    23.    android:background="@drawable/image3" />
    24.    android:layout_width="fill_parent"
    25.    android:layout_height="fill_parent"
    26.    android:background="@drawable/image4" />
    27.    android:layout_width="60dip"
    28.    android:layout_height="20dip"
    29.    android:layout_alignParentBottom="true"
    30.    android:layout_alignParentRight="true"
    31.    android:layout_margin="15dip"
    32.    android:orientation="horizontal" >

    复制代码


      也就是说,我们只需要通过设定myattr:auto_play是等于true还是false,就可以决定是否启用自动播放功能,非常简单方便。