├── README.md
└── TuTu
├── .classpath
├── .project
├── AndroidManifest.xml
├── bin
├── AndroidManifest.xml
├── classes
│ └── com
│ │ └── example
│ │ └── lunbotu
│ │ ├── ADBean.class
│ │ ├── BuildConfig.class
│ │ ├── ImageUtil$1.class
│ │ ├── ImageUtil$ImageCallback.class
│ │ ├── ImageUtil$getImageRunnable.class
│ │ ├── ImageUtil.class
│ │ ├── MainActivityTwo.class
│ │ ├── MyAdapter$1.class
│ │ ├── MyAdapter$OnItemClickListener.class
│ │ ├── MyAdapter.class
│ │ ├── R$attr.class
│ │ ├── R$dimen.class
│ │ ├── R$drawable.class
│ │ ├── R$id.class
│ │ ├── R$layout.class
│ │ ├── R$string.class
│ │ ├── R.class
│ │ ├── ThreadPoolManager.class
│ │ ├── TuTu$1.class
│ │ ├── TuTu$2.class
│ │ ├── TuTu$3.class
│ │ ├── TuTu$4.class
│ │ ├── TuTu$FixedSpeedScroller.class
│ │ └── TuTu.class
└── jarlist.cache
├── gen
└── com
│ └── example
│ └── lunbotu
│ ├── BuildConfig.java
│ └── R.java
├── ic_launcher-web.png
├── libs
└── android-support-v4.jar
├── proguard-project.txt
├── project.properties
├── res
├── drawable-hdpi
│ ├── five.jpg
│ ├── fore.jpg
│ ├── ic_launcher.png
│ ├── one.jpg
│ ├── three.jpg
│ └── two.jpg
├── drawable-mdpi
│ └── ic_launcher.png
├── drawable-xhdpi
│ └── ic_launcher.png
├── drawable-xxhdpi
│ └── ic_launcher.png
├── drawable
│ ├── point_normal.xml
│ ├── point_seletor.xml
│ └── ponit_focus.xml
├── layout
│ ├── activity_main.xml
│ └── image_item.xml
└── values
│ ├── attrs.xml
│ ├── dimens.xml
│ └── strings.xml
└── src
└── com
└── example
└── lunbotu
├── ADBean.java
├── ImageUtil.java
├── MainActivityTwo.java
├── MyAdapter.java
├── ThreadPoolManager.java
├── TuTu.java
└── widget
├── CircleFlowIndicator.java
├── FlowIndicator.java
├── ImageAdapter.java
├── TuTu2.java
└── ViewFlow.java
/README.md:
--------------------------------------------------------------------------------
1 | # 轮播图
2 | 可以加载本地图片或者网络资源的无限循环的轮播图,一行代码调用,图片三级缓存,节省流量,间隔自己设置,使用方便。
3 |
4 |
5 |
6 | 1、你只要写好布局就行,布局写成啥样你自己决定,扩展性强,满足多样化需求
7 | 例如:
8 |
9 |
10 |
11 |
16 |
17 |
18 |
23 |
24 |
31 |
32 |
39 |
40 |
47 |
48 |
49 |
50 |
51 |
52 | 2、添加轮播图对象
53 |
54 | 这是轮播图对象
55 | private String id;
56 | private String adName;//广告词
57 | private String imgUrl;//网络图片资源
58 | private int imgPath=-1;//本地图片资源
59 | private ImageView mImageView;
60 |
61 |
62 |
63 |
64 | 初始化轮播图对象并添加到list里面
65 |
66 | List listADbeans;
67 | /**
68 | * 本地图片资源
69 | */
70 | private int[] ids = { R.drawable.one, R.drawable.two, R.drawable.three,
71 | R.drawable.fore, R.drawable.five };
72 | /**
73 | * 显示文字
74 | */
75 | private String[] des = { "1111111", "22222222", "3333333", "4444444444","55555555555" };
76 | /**
77 | * 网络资源
78 | */
79 | private String[] urls = { "http://a.hiphotos.baidu.com/image/pic/item/0bd162d9f2d3572ce98282e18e13632762d0c3af.jpg",
80 | "http://d.hiphotos.baidu.com/image/pic/item/1b4c510fd9f9d72aebede7a1d62a2834359bbb85.jpg",
81 | "http://h.hiphotos.baidu.com/image/pic/item/91ef76c6a7efce1be2f4f15cad51f3deb58f654c.jpg",
82 | "http://h.hiphotos.baidu.com/image/w%3D230/sign=3e9ec55457fbb2fb342b5f117f4b2043/e850352ac65c1038343303cbb0119313b07e896e.jpg",
83 | "http://e.hiphotos.baidu.com/image/pic/item/d53f8794a4c27d1e3625e52d18d5ad6edcc438dc.jpg" };
84 |
85 | listADbeans = new ArrayList();
86 | for(int i =0;i<5;i++){
87 | ADBean bean = new ADBean();
88 | bean.setAdName(des[i]);//广告文字
89 | bean.setId(i+"");
90 | bean.setImgUrl(urls[i]);//添加网络图片资源,如果不需要可以不用添加
91 | bean.setImgPath(ids[i]);//添加本地图片资源,如果不需要可以不用添加,如果网络资源和本地资源同时添加,默认使用的是本地资源,所以建议本地资源和网络资源添加一个
92 | listADbeans.add(bean);
93 | }
94 |
95 |
96 |
97 | 3、然后你只要把布局和轮播图对象添加进去就好了,同时开启轮播图
98 |
99 | TuTu tu = new TuTu(ad_viewPage, tv_msg, ll_dian, mContext, listADbeans);//把布局添加进去
100 | tu.startViewPager(4000);//动态设置滑动间隔,并且开启轮播图
101 |
102 | 4、在activity销毁时也罢要把轮播图销毁
103 |
104 | /**
105 | * 销毁轮播图
106 | */
107 | @Override
108 | protected void onDestroy() {
109 | if(tu!=null){
110 | tu.destroyView();
111 | }
112 | super.onDestroy();
113 | }
114 |
115 |
116 |
117 |
118 |
119 |
120 |
--------------------------------------------------------------------------------
/TuTu/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/TuTu/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | TuTu
4 |
5 |
6 |
7 |
8 |
9 | com.android.ide.eclipse.adt.ResourceManagerBuilder
10 |
11 |
12 |
13 |
14 | com.android.ide.eclipse.adt.PreCompilerBuilder
15 |
16 |
17 |
18 |
19 | org.eclipse.jdt.core.javabuilder
20 |
21 |
22 |
23 |
24 | com.android.ide.eclipse.adt.ApkBuilder
25 |
26 |
27 |
28 |
29 |
30 | com.android.ide.eclipse.adt.AndroidNature
31 | org.eclipse.jdt.core.javanature
32 |
33 |
34 |
--------------------------------------------------------------------------------
/TuTu/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
10 |
11 |
12 |
13 |
14 |
19 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/TuTu/bin/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
10 |
11 |
12 |
13 |
14 |
19 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/TuTu/bin/classes/com/example/lunbotu/ADBean.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kongdongdong/TuTu/2c964ae0dc4f08ef530610653412dab6ed20ee9f/TuTu/bin/classes/com/example/lunbotu/ADBean.class
--------------------------------------------------------------------------------
/TuTu/bin/classes/com/example/lunbotu/BuildConfig.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kongdongdong/TuTu/2c964ae0dc4f08ef530610653412dab6ed20ee9f/TuTu/bin/classes/com/example/lunbotu/BuildConfig.class
--------------------------------------------------------------------------------
/TuTu/bin/classes/com/example/lunbotu/ImageUtil$1.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kongdongdong/TuTu/2c964ae0dc4f08ef530610653412dab6ed20ee9f/TuTu/bin/classes/com/example/lunbotu/ImageUtil$1.class
--------------------------------------------------------------------------------
/TuTu/bin/classes/com/example/lunbotu/ImageUtil$ImageCallback.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kongdongdong/TuTu/2c964ae0dc4f08ef530610653412dab6ed20ee9f/TuTu/bin/classes/com/example/lunbotu/ImageUtil$ImageCallback.class
--------------------------------------------------------------------------------
/TuTu/bin/classes/com/example/lunbotu/ImageUtil$getImageRunnable.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kongdongdong/TuTu/2c964ae0dc4f08ef530610653412dab6ed20ee9f/TuTu/bin/classes/com/example/lunbotu/ImageUtil$getImageRunnable.class
--------------------------------------------------------------------------------
/TuTu/bin/classes/com/example/lunbotu/ImageUtil.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kongdongdong/TuTu/2c964ae0dc4f08ef530610653412dab6ed20ee9f/TuTu/bin/classes/com/example/lunbotu/ImageUtil.class
--------------------------------------------------------------------------------
/TuTu/bin/classes/com/example/lunbotu/MainActivityTwo.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kongdongdong/TuTu/2c964ae0dc4f08ef530610653412dab6ed20ee9f/TuTu/bin/classes/com/example/lunbotu/MainActivityTwo.class
--------------------------------------------------------------------------------
/TuTu/bin/classes/com/example/lunbotu/MyAdapter$1.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kongdongdong/TuTu/2c964ae0dc4f08ef530610653412dab6ed20ee9f/TuTu/bin/classes/com/example/lunbotu/MyAdapter$1.class
--------------------------------------------------------------------------------
/TuTu/bin/classes/com/example/lunbotu/MyAdapter$OnItemClickListener.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kongdongdong/TuTu/2c964ae0dc4f08ef530610653412dab6ed20ee9f/TuTu/bin/classes/com/example/lunbotu/MyAdapter$OnItemClickListener.class
--------------------------------------------------------------------------------
/TuTu/bin/classes/com/example/lunbotu/MyAdapter.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kongdongdong/TuTu/2c964ae0dc4f08ef530610653412dab6ed20ee9f/TuTu/bin/classes/com/example/lunbotu/MyAdapter.class
--------------------------------------------------------------------------------
/TuTu/bin/classes/com/example/lunbotu/R$attr.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kongdongdong/TuTu/2c964ae0dc4f08ef530610653412dab6ed20ee9f/TuTu/bin/classes/com/example/lunbotu/R$attr.class
--------------------------------------------------------------------------------
/TuTu/bin/classes/com/example/lunbotu/R$dimen.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kongdongdong/TuTu/2c964ae0dc4f08ef530610653412dab6ed20ee9f/TuTu/bin/classes/com/example/lunbotu/R$dimen.class
--------------------------------------------------------------------------------
/TuTu/bin/classes/com/example/lunbotu/R$drawable.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kongdongdong/TuTu/2c964ae0dc4f08ef530610653412dab6ed20ee9f/TuTu/bin/classes/com/example/lunbotu/R$drawable.class
--------------------------------------------------------------------------------
/TuTu/bin/classes/com/example/lunbotu/R$id.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kongdongdong/TuTu/2c964ae0dc4f08ef530610653412dab6ed20ee9f/TuTu/bin/classes/com/example/lunbotu/R$id.class
--------------------------------------------------------------------------------
/TuTu/bin/classes/com/example/lunbotu/R$layout.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kongdongdong/TuTu/2c964ae0dc4f08ef530610653412dab6ed20ee9f/TuTu/bin/classes/com/example/lunbotu/R$layout.class
--------------------------------------------------------------------------------
/TuTu/bin/classes/com/example/lunbotu/R$string.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kongdongdong/TuTu/2c964ae0dc4f08ef530610653412dab6ed20ee9f/TuTu/bin/classes/com/example/lunbotu/R$string.class
--------------------------------------------------------------------------------
/TuTu/bin/classes/com/example/lunbotu/R.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kongdongdong/TuTu/2c964ae0dc4f08ef530610653412dab6ed20ee9f/TuTu/bin/classes/com/example/lunbotu/R.class
--------------------------------------------------------------------------------
/TuTu/bin/classes/com/example/lunbotu/ThreadPoolManager.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kongdongdong/TuTu/2c964ae0dc4f08ef530610653412dab6ed20ee9f/TuTu/bin/classes/com/example/lunbotu/ThreadPoolManager.class
--------------------------------------------------------------------------------
/TuTu/bin/classes/com/example/lunbotu/TuTu$1.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kongdongdong/TuTu/2c964ae0dc4f08ef530610653412dab6ed20ee9f/TuTu/bin/classes/com/example/lunbotu/TuTu$1.class
--------------------------------------------------------------------------------
/TuTu/bin/classes/com/example/lunbotu/TuTu$2.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kongdongdong/TuTu/2c964ae0dc4f08ef530610653412dab6ed20ee9f/TuTu/bin/classes/com/example/lunbotu/TuTu$2.class
--------------------------------------------------------------------------------
/TuTu/bin/classes/com/example/lunbotu/TuTu$3.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kongdongdong/TuTu/2c964ae0dc4f08ef530610653412dab6ed20ee9f/TuTu/bin/classes/com/example/lunbotu/TuTu$3.class
--------------------------------------------------------------------------------
/TuTu/bin/classes/com/example/lunbotu/TuTu$4.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kongdongdong/TuTu/2c964ae0dc4f08ef530610653412dab6ed20ee9f/TuTu/bin/classes/com/example/lunbotu/TuTu$4.class
--------------------------------------------------------------------------------
/TuTu/bin/classes/com/example/lunbotu/TuTu$FixedSpeedScroller.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kongdongdong/TuTu/2c964ae0dc4f08ef530610653412dab6ed20ee9f/TuTu/bin/classes/com/example/lunbotu/TuTu$FixedSpeedScroller.class
--------------------------------------------------------------------------------
/TuTu/bin/classes/com/example/lunbotu/TuTu.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kongdongdong/TuTu/2c964ae0dc4f08ef530610653412dab6ed20ee9f/TuTu/bin/classes/com/example/lunbotu/TuTu.class
--------------------------------------------------------------------------------
/TuTu/bin/jarlist.cache:
--------------------------------------------------------------------------------
1 | # cache for current jar dependency. DO NOT EDIT.
2 | # format is
3 | # Encoding is UTF-8
4 |
--------------------------------------------------------------------------------
/TuTu/gen/com/example/lunbotu/BuildConfig.java:
--------------------------------------------------------------------------------
1 | /** Automatically generated file. DO NOT MODIFY */
2 | package com.example.lunbotu;
3 |
4 | public final class BuildConfig {
5 | public final static boolean DEBUG = true;
6 | }
--------------------------------------------------------------------------------
/TuTu/gen/com/example/lunbotu/R.java:
--------------------------------------------------------------------------------
1 | /* AUTO-GENERATED FILE. DO NOT MODIFY.
2 | *
3 | * This class was automatically generated by the
4 | * aapt tool from the resource data it found. It
5 | * should not be modified by hand.
6 | */
7 |
8 | package com.example.lunbotu;
9 |
10 | public final class R {
11 | public static final class attr {
12 | }
13 | public static final class dimen {
14 | /** Default screen margins, per the Android Design guidelines.
15 | */
16 | public static final int activity_horizontal_margin=0x7f040000;
17 | public static final int activity_vertical_margin=0x7f040001;
18 | }
19 | public static final class drawable {
20 | public static final int five=0x7f020000;
21 | public static final int fore=0x7f020001;
22 | public static final int ic_launcher=0x7f020002;
23 | public static final int one=0x7f020003;
24 | public static final int point_normal=0x7f020004;
25 | public static final int point_seletor=0x7f020005;
26 | public static final int ponit_focus=0x7f020006;
27 | public static final int three=0x7f020007;
28 | public static final int two=0x7f020008;
29 | }
30 | public static final class id {
31 | public static final int ad_viewPage=0x7f060000;
32 | public static final int ll_dian=0x7f060002;
33 | public static final int tv_msg=0x7f060001;
34 | }
35 | public static final class layout {
36 | public static final int activity_main=0x7f030000;
37 | }
38 | public static final class string {
39 | public static final int action_settings=0x7f050002;
40 | public static final int app_name=0x7f050000;
41 | public static final int hello_world=0x7f050001;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/TuTu/ic_launcher-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kongdongdong/TuTu/2c964ae0dc4f08ef530610653412dab6ed20ee9f/TuTu/ic_launcher-web.png
--------------------------------------------------------------------------------
/TuTu/libs/android-support-v4.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kongdongdong/TuTu/2c964ae0dc4f08ef530610653412dab6ed20ee9f/TuTu/libs/android-support-v4.jar
--------------------------------------------------------------------------------
/TuTu/proguard-project.txt:
--------------------------------------------------------------------------------
1 | # To enable ProGuard in your project, edit project.properties
2 | # to define the proguard.config property as described in that file.
3 | #
4 | # Add project specific ProGuard rules here.
5 | # By default, the flags in this file are appended to flags specified
6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt
7 | # You can edit the include path and order by changing the ProGuard
8 | # include property in project.properties.
9 | #
10 | # For more details, see
11 | # http://developer.android.com/guide/developing/tools/proguard.html
12 |
13 | # Add any project specific keep options here:
14 |
15 | # If your project uses WebView with JS, uncomment the following
16 | # and specify the fully qualified class name to the JavaScript interface
17 | # class:
18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
19 | # public *;
20 | #}
21 |
--------------------------------------------------------------------------------
/TuTu/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system edit
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 | #
10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
12 |
13 | # Project target.
14 | target=android-19
15 |
--------------------------------------------------------------------------------
/TuTu/res/drawable-hdpi/five.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kongdongdong/TuTu/2c964ae0dc4f08ef530610653412dab6ed20ee9f/TuTu/res/drawable-hdpi/five.jpg
--------------------------------------------------------------------------------
/TuTu/res/drawable-hdpi/fore.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kongdongdong/TuTu/2c964ae0dc4f08ef530610653412dab6ed20ee9f/TuTu/res/drawable-hdpi/fore.jpg
--------------------------------------------------------------------------------
/TuTu/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kongdongdong/TuTu/2c964ae0dc4f08ef530610653412dab6ed20ee9f/TuTu/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/TuTu/res/drawable-hdpi/one.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kongdongdong/TuTu/2c964ae0dc4f08ef530610653412dab6ed20ee9f/TuTu/res/drawable-hdpi/one.jpg
--------------------------------------------------------------------------------
/TuTu/res/drawable-hdpi/three.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kongdongdong/TuTu/2c964ae0dc4f08ef530610653412dab6ed20ee9f/TuTu/res/drawable-hdpi/three.jpg
--------------------------------------------------------------------------------
/TuTu/res/drawable-hdpi/two.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kongdongdong/TuTu/2c964ae0dc4f08ef530610653412dab6ed20ee9f/TuTu/res/drawable-hdpi/two.jpg
--------------------------------------------------------------------------------
/TuTu/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kongdongdong/TuTu/2c964ae0dc4f08ef530610653412dab6ed20ee9f/TuTu/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/TuTu/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kongdongdong/TuTu/2c964ae0dc4f08ef530610653412dab6ed20ee9f/TuTu/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/TuTu/res/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kongdongdong/TuTu/2c964ae0dc4f08ef530610653412dab6ed20ee9f/TuTu/res/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/TuTu/res/drawable/point_normal.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/TuTu/res/drawable/point_seletor.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/TuTu/res/drawable/ponit_focus.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/TuTu/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
11 |
12 |
17 |
18 |
25 |
26 |
33 |
34 |
41 |
42 |
43 |
44 |
45 |
50 |
51 |
55 |
56 |
57 |
64 |
65 |
77 |
78 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/TuTu/res/layout/image_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/TuTu/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
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 |
--------------------------------------------------------------------------------
/TuTu/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 16dp
5 | 16dp
6 |
7 |
8 |
--------------------------------------------------------------------------------
/TuTu/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 轮播图
5 | Hello world!
6 | Settings
7 |
8 |
9 |
--------------------------------------------------------------------------------
/TuTu/src/com/example/lunbotu/ADBean.java:
--------------------------------------------------------------------------------
1 | package com.example.lunbotu;
2 |
3 | import android.graphics.Bitmap;
4 | import android.widget.ImageView;
5 |
6 | public class ADBean {
7 |
8 | private String id;
9 | private String adName;//广告词
10 | private String imgUrl;//网络图片资源
11 | private int imgPath=-1;//本地图片资源
12 | private ImageView mImageView;
13 | private Bitmap bitmap;
14 |
15 |
16 | public ImageView getmImageView() {
17 | return mImageView;
18 | }
19 | public void setmImageView(ImageView mImageView) {
20 | this.mImageView = mImageView;
21 | }
22 | public String getId() {
23 | return id;
24 | }
25 | public void setId(String id) {
26 | this.id = id;
27 | }
28 | public String getAdName() {
29 | return adName;
30 | }
31 | public void setAdName(String adName) {
32 | this.adName = adName;
33 | }
34 | public String getImgUrl() {
35 | return imgUrl;
36 | }
37 | public void setImgUrl(String imgUrl) {
38 | this.imgUrl = imgUrl;
39 | }
40 | public int getImgPath() {
41 | return imgPath;
42 | }
43 | public void setImgPath(int imgPath) {
44 | this.imgPath = imgPath;
45 | }
46 | public Bitmap getBitmap() {
47 | return bitmap;
48 | }
49 | public void setBitmap(Bitmap bitmap) {
50 | this.bitmap = bitmap;
51 | }
52 |
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/TuTu/src/com/example/lunbotu/ImageUtil.java:
--------------------------------------------------------------------------------
1 | package com.example.lunbotu;
2 |
3 | import java.io.BufferedInputStream;
4 | import java.io.ByteArrayInputStream;
5 | import java.io.ByteArrayOutputStream;
6 | import java.io.File;
7 | import java.io.FileInputStream;
8 | import java.io.FileNotFoundException;
9 | import java.io.FileOutputStream;
10 | import java.io.IOException;
11 | import java.io.InputStream;
12 | import java.lang.ref.SoftReference;
13 | import java.net.HttpURLConnection;
14 | import java.net.URLConnection;
15 | import java.net.URL;
16 | import java.util.HashMap;
17 | import java.util.Map;
18 |
19 | import android.content.Context;
20 | import android.graphics.Bitmap;
21 | import android.graphics.BitmapFactory;
22 | import android.graphics.drawable.Drawable;
23 | import android.os.Environment;
24 | import android.os.Handler;
25 | import android.os.Message;
26 | import android.util.Log;
27 |
28 | /**
29 | *
30 | * 图片缓存类,封装了网络获取图片,本地缓存,内存缓存
31 | *
32 | **/
33 |
34 | public class ImageUtil {
35 | private static HashMap> imageCache = new HashMap>();
36 | public static final String IMAGE_PATH = "/sdcard/images/";
37 | private Context mContext;
38 | public ImageUtil(Context mContext) {
39 | this.mContext = mContext;
40 | }
41 | /**
42 | * 对图片进行质量压�?
43 | * @param image
44 | * @return
45 | */
46 | public Bitmap compressImage(Bitmap image) {
47 |
48 | ByteArrayOutputStream baos = new ByteArrayOutputStream();
49 | image.compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法,这�?00表示不压缩,把压缩后的数据存放到baos�?
50 | int options = 100;
51 | while ( baos.toByteArray().length / 1024 > 800) { //循环判断如果压缩后图片是否大�?00kb,大于继续压缩
52 | baos.reset();//重置baos即清空baos
53 | image.compress(Bitmap.CompressFormat.JPEG, options, baos);//这里压缩options%,把压缩后的数据存放到baos�?
54 | options -= 10;//每次都减�?0
55 | }
56 | ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());//把压缩后的数据baos存放到ByteArrayInputStream�?
57 | Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);//把ByteArrayInputStream数据生成图片
58 | return bitmap;
59 | }
60 | /**
61 | * JPG图片缓存
62 | *
63 | * @param imagePath
64 | * @param bitmap
65 | * @throws IOException
66 | */
67 | public static void saveImageJpeg(String imagePath, Bitmap bitmap)
68 | throws IOException {
69 | ByteArrayOutputStream bos = new ByteArrayOutputStream();
70 | bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);
71 | byte[] b = bos.toByteArray();
72 | saveImage(imagePath, b);
73 | bos.flush();
74 | bos.close();
75 | }
76 |
77 | /**
78 | * PNG图片缓存
79 | *
80 | * @param imagePath
81 | * @param buffer
82 | * @throws IOException
83 | */
84 |
85 | public static void saveImagePng(String imagePath, Bitmap bitmap)
86 | throws IOException {
87 |
88 | ByteArrayOutputStream bos = new ByteArrayOutputStream();
89 | bitmap.compress(Bitmap.CompressFormat.PNG, 100, bos);
90 | byte[] b = bos.toByteArray();
91 | saveImage(imagePath, b);
92 | bos.flush();
93 | bos.close();
94 | }
95 |
96 | /**
97 | * 缓存图片
98 | *
99 | * @param imagePath
100 | * @param buffer
101 | * @throws IOException
102 | */
103 | public static void saveImage(String imagePath, byte[] buffer)
104 | throws IOException {
105 | File f = new File(imagePath);
106 | if (f.exists()) {
107 | return;
108 | } else {
109 | File parentFile = f.getParentFile();
110 | if (!parentFile.exists()) {
111 | parentFile.mkdirs();
112 | }
113 | f.createNewFile();
114 | FileOutputStream fos = new FileOutputStream(imagePath);
115 | fos.write(buffer);
116 | fos.flush();
117 | fos.close();
118 | }
119 | }
120 |
121 | /**
122 | * 从本地获取图片
123 | *
124 | * @param imagePath
125 | * @return Bitmap
126 | */
127 | public static Bitmap getImageFromLocal(String imagePath) {
128 | File file = new File(imagePath);
129 | if (file.exists()) {
130 | Bitmap bitmap = BitmapFactory.decodeFile(imagePath);
131 | file.setLastModified(System.currentTimeMillis());
132 | return bitmap;
133 | }
134 | return null;
135 | }
136 |
137 | /**
138 | * 从网络获取图片并缓存
139 | *
140 | * @return Bitmap
141 | * @throws IOException
142 | */
143 | Bitmap mbitmap = null;
144 | String url = null;
145 | public void loadImage(final String imageName, final String imgUrl,
146 | final boolean isbusy, final ImageCallback callback) {
147 | callback.onStart(imgUrl);
148 | Bitmap bitmap = null;
149 | if (imageCache.containsKey(imgUrl)) {
150 | SoftReference softReference = imageCache.get(imgUrl);
151 | bitmap = softReference.get();
152 | if (bitmap != null) {
153 | Log.i(TuTu.TAG, "从内存获得图片成功。。");
154 | callback.loadImage(bitmap, imgUrl);
155 | }
156 | }
157 | bitmap = getBitmapFromData(imageName, mContext);
158 | if (bitmap != null) {
159 | imageCache.put(imgUrl, new SoftReference(bitmap));
160 | Log.i(TuTu.TAG, "从本地获得图片成功。。");
161 | callback.loadImage(bitmap, imgUrl);
162 | } else {// 从网络获取图片
163 | final Handler handler = new Handler() {
164 | @Override
165 | public void handleMessage(Message msg) {
166 | if (msg.obj != null) {
167 | synchronized (imageCache) {
168 | Map bitmapMap = (Map) msg.obj;
169 | for(String str:bitmapMap.keySet()){
170 | mbitmap = bitmapMap.get(str);
171 | url = str;
172 | imageCache.put(url,new SoftReference(mbitmap));
173 | }
174 |
175 | if (android.os.Environment.getExternalStorageState()
176 | .equals(android.os.Environment.MEDIA_MOUNTED)) {
177 | try {
178 | String imageName = url.substring(url.lastIndexOf("/")+1, url.length());
179 | if(!imageName.endsWith(".jpg") && !imageName.endsWith(".png")){
180 | imageName += ".png";
181 | }
182 | String mImagePath = ImageUtil.IMAGE_PATH+imageName;
183 | saveBitmapToData(imageName, mbitmap, mContext);
184 |
185 | } catch (Exception e) {
186 | e.printStackTrace();
187 | }
188 | }
189 |
190 | callback.loadImage(mbitmap, url);
191 | }
192 |
193 |
194 | }
195 | }
196 | };
197 |
198 | getImageRunnable run = new getImageRunnable(imgUrl,handler,callback);
199 | ThreadPoolManager.getInstance().addTask(run);
200 | }
201 | }
202 |
203 | class getImageRunnable implements Runnable{
204 |
205 | private String url;
206 | private Handler mHandler;
207 | private ImageCallback mCallback;
208 | public getImageRunnable(String imgUrl, Handler handler,ImageCallback callback) {
209 | url = imgUrl;
210 | mHandler = handler;
211 | mCallback = callback;
212 | }
213 |
214 | @Override
215 | public void run() {
216 | try {
217 | synchronized (imageCache) {
218 |
219 | }
220 |
221 | Bitmap bitmap = null;
222 | if (url != null && !"".equals(url)) {
223 | byte[] b = getUrlBytes(url);
224 | bitmap = BitmapFactory.decodeByteArray(b, 0,
225 | b.length);
226 | //bitmap = compressImage(bitmap);
227 | }
228 | Message msg = mHandler.obtainMessage();
229 | Map bitmapMap = new HashMap();
230 | bitmapMap.put(url, bitmap);
231 | msg.obj = bitmapMap;
232 | mHandler.sendMessage(msg);
233 | } catch (Exception e) {
234 | e.printStackTrace();
235 | synchronized (imageCache) {
236 | mCallback.onFailed(url);
237 | }
238 |
239 | }
240 | }
241 |
242 | }
243 |
244 | public static int computeSampleSize(BitmapFactory.Options options,
245 | int minSideLength, int maxNumOfPixels) {
246 | int initialSize = computeInitialSampleSize(options, minSideLength,
247 | maxNumOfPixels);
248 |
249 | int roundedSize;
250 | if (initialSize <= 8) {
251 | roundedSize = 1;
252 | while (roundedSize < initialSize) {
253 | roundedSize <<= 1;
254 | }
255 | } else {
256 | roundedSize = (initialSize + 7) / 8 * 8;
257 | }
258 |
259 | return roundedSize;
260 | }
261 |
262 | private static int computeInitialSampleSize(BitmapFactory.Options options,
263 | int minSideLength, int maxNumOfPixels) {
264 | double w = options.outWidth;
265 | double h = options.outHeight;
266 |
267 | int lowerBound = (maxNumOfPixels == -1) ? 1 : (int) Math.ceil(Math
268 | .sqrt(w * h / maxNumOfPixels));
269 | int upperBound = (minSideLength == -1) ? 128 : (int) Math.min(
270 | Math.floor(w / minSideLength), Math.floor(h / minSideLength));
271 |
272 | if (upperBound < lowerBound) {
273 | // return the larger one when there is no overlapping zone.
274 | return lowerBound;
275 | }
276 |
277 | if ((maxNumOfPixels == -1) && (minSideLength == -1)) {
278 | return 1;
279 | } else if (minSideLength == -1) {
280 | return lowerBound;
281 | } else {
282 | return upperBound;
283 | }
284 | }
285 |
286 | /**
287 | * 获取指定路径的Byte[]数据-通用
288 | *
289 | * @param urlpath
290 | * @return byte[]
291 | * @throws Exception
292 | */
293 | public static byte[] getUrlBytes(String urlpath) throws Exception {
294 | InputStream in_s = getUrlInputStream(urlpath);
295 | return readStream(in_s);
296 | }
297 |
298 | /**
299 | * 获取指定路径的InputStream数据-通用
300 | *
301 | * @param urlpath
302 | * @return byte[]
303 | * @throws Exception
304 | */
305 | public static InputStream getUrlInputStream(String urlpath)
306 | throws Exception {
307 | URL url = new URL(urlpath);
308 | HttpURLConnection conn = (HttpURLConnection) url.openConnection();
309 | // conn.setRequestMethod("GET");
310 | conn.setRequestMethod("GET");
311 | conn.setConnectTimeout(15*1000);// 10秒超时
312 | int responseCode = conn.getResponseCode();
313 | Log.i("image", responseCode + "");
314 | System.out.println(responseCode + "");
315 | if (responseCode == HttpURLConnection.HTTP_OK) {// 返回码200等于返回成功
316 | InputStream inputStream = conn.getInputStream();
317 | return inputStream;
318 | }
319 | return null;
320 | }
321 |
322 | /**
323 | * 从InputStream中读取数据-通用
324 | *
325 | * @param inStream
326 | * @return byte[]
327 | * @throws Exception
328 | */
329 | public static byte[] readStream(InputStream inStream) throws Exception {
330 | ByteArrayOutputStream outstream = new ByteArrayOutputStream();
331 | byte[] buffer = new byte[128];
332 | int len = -1;
333 | while ((len = inStream.read(buffer)) != -1) {
334 | outstream.write(buffer, 0, len);
335 | }
336 | outstream.close();
337 | inStream.close();
338 | return outstream.toByteArray();
339 | }
340 |
341 | /**
342 | * 获取缓存路径
343 | *
344 | * @return sd卡路径
345 | */
346 | public static String getCacheImgPath() {
347 | return Environment.getExternalStorageDirectory().getPath()
348 | + "/ambow/cache/";
349 | }
350 | /**
351 | * 将图片保存到data/data目录下
352 | *
353 | * @param name
354 | * @param bitmap
355 | * @param context
356 | */
357 | public void saveBitmapToData(String name, Bitmap bitmap, Context context) {
358 | try {
359 | FileOutputStream localFileOutputStream1 = context.openFileOutput(
360 | name, 0);
361 |
362 | Bitmap.CompressFormat localCompressFormat = Bitmap.CompressFormat.PNG;
363 | bitmap.compress(localCompressFormat, 100, localFileOutputStream1);
364 |
365 | localFileOutputStream1.close();
366 | } catch (Exception e) {
367 | e.printStackTrace();
368 | }
369 | }
370 |
371 | /**
372 | * 获取data/data下的图片文件
373 | * @param name
374 | * @param context
375 | * @return
376 | */
377 | public Bitmap getBitmapFromData(String name, Context context) {
378 | FileInputStream localStream;
379 | Bitmap bitmap = null;
380 | try {
381 | localStream = context.openFileInput(name);
382 | bitmap = BitmapFactory.decodeStream(localStream);
383 | } catch (FileNotFoundException e) {
384 | e.printStackTrace();
385 | }
386 |
387 | return bitmap;
388 | }
389 |
390 |
391 | /**
392 | * 类功能描述:给网络上获取的图片设置的回调
393 | *
394 | * @version 1.0
修改时间: 修改备注:
395 | */
396 | public interface ImageCallback {
397 | public void onStart(String imageUrl);
398 | public void loadImage(Bitmap bitmap, String imageUrl);
399 | public void onFailed(String imageUrl);
400 | }
401 |
402 | }
403 |
--------------------------------------------------------------------------------
/TuTu/src/com/example/lunbotu/MainActivityTwo.java:
--------------------------------------------------------------------------------
1 | package com.example.lunbotu;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | import android.app.Activity;
7 | import android.content.Context;
8 | import android.os.Bundle;
9 | import android.support.v4.view.ViewPager;
10 | import android.widget.ImageView;
11 | import android.widget.LinearLayout;
12 | import android.widget.TextView;
13 |
14 | import com.example.lunbotu.widget.CircleFlowIndicator;
15 | import com.example.lunbotu.widget.ImageAdapter;
16 | import com.example.lunbotu.widget.TuTu2;
17 | import com.example.lunbotu.widget.ViewFlow;
18 |
19 | public class MainActivityTwo extends Activity{
20 |
21 | private ViewPager ad_viewPage;
22 | /**
23 | * 显示的文字Textview
24 | */
25 | private TextView tv_msg;
26 | /**
27 | * 添加小圆点的线性布局
28 | */
29 | private LinearLayout ll_dian;
30 | /**
31 | * 轮播图对象列表
32 | */
33 | List listADbeans;
34 | List listADbeans2;
35 | /**
36 | * 本地图片资源
37 | */
38 | private int[] ids = { R.drawable.one, R.drawable.two, R.drawable.three,
39 | R.drawable.fore, R.drawable.five };
40 | /**
41 | * 显示文字
42 | */
43 | private String[] des = { "1111111", "22222222", "3333333", "4444444444","55555555555" };
44 | /**
45 | * 网络资源
46 | */
47 | private String[] urls = { "http://a.hiphotos.baidu.com/image/pic/item/0bd162d9f2d3572ce98282e18e13632762d0c3af.jpg",
48 | "http://d.hiphotos.baidu.com/image/pic/item/1b4c510fd9f9d72aebede7a1d62a2834359bbb85.jpg",
49 | "http://h.hiphotos.baidu.com/image/pic/item/91ef76c6a7efce1be2f4f15cad51f3deb58f654c.jpg",
50 | "http://h.hiphotos.baidu.com/image/w%3D230/sign=3e9ec55457fbb2fb342b5f117f4b2043/e850352ac65c1038343303cbb0119313b07e896e.jpg",
51 | "http://e.hiphotos.baidu.com/image/pic/item/d53f8794a4c27d1e3625e52d18d5ad6edcc438dc.jpg" };
52 |
53 | private TuTu tu;
54 | private Context mContext;
55 | private ViewFlow viewFlow;
56 | private ImageAdapter imageAdapter;
57 |
58 | protected void onCreate(Bundle savedInstanceState) {
59 | super.onCreate(savedInstanceState);
60 | setContentView(R.layout.activity_main);
61 | mContext = this;
62 | initView();
63 | //initAD();
64 | initAD2();
65 | }
66 | private void initAD2() {
67 | listADbeans2 = new ArrayList();
68 | for(int i =0;i<5;i++){
69 | ADBean bean = new ADBean();
70 | bean.setmImageView(new ImageView(mContext));
71 | bean.setAdName(des[i]);
72 | bean.setId(i+"");
73 | bean.setImgUrl(urls[i]);//网络图片
74 | //bean.setImgPath(ids[i]);
75 | listADbeans2.add(bean);
76 | }
77 |
78 | imageAdapter = new ImageAdapter(this,listADbeans2);
79 | viewFlow = (ViewFlow) findViewById(R.id.viewflow);
80 | viewFlow.setAdapter(imageAdapter);
81 | viewFlow.setmSideBuffer(listADbeans2.size()); // 实际图片张数, 我的ImageAdapter实际图片张数为3
82 |
83 | CircleFlowIndicator indic = (CircleFlowIndicator) findViewById(R.id.viewflowindic);
84 | TuTu2 tutu2 = new TuTu2(this,viewFlow,listADbeans2,imageAdapter);
85 | tutu2.setFlowIndicator(indic);
86 | tutu2.setTimeSpan(4000);
87 | tutu2.setSelection(3 * 1000); // 设置初始位置
88 | tutu2.startAutoFlowTimer(); // 启动自动播放
89 | tutu2.getNetImage();
90 | /*viewFlow.setFlowIndicator(indic);
91 | viewFlow.setTimeSpan(4000);
92 | viewFlow.setSelection(3 * 1000); // 设置初始位置
93 | viewFlow.startAutoFlowTimer(); // 启动自动播放
94 | */
95 | }
96 | /**
97 | * 初始化轮播图
98 | */
99 | private void initAD() {
100 | listADbeans = new ArrayList();
101 | for(int i =0;i<5;i++){
102 | ADBean bean = new ADBean();
103 | bean.setAdName(des[i]);
104 | bean.setId(i+"");
105 | bean.setImgUrl(urls[i]);
106 | //bean.setImgPath(ids[i]);
107 | listADbeans.add(bean);
108 | }
109 | tu = new TuTu(ad_viewPage, tv_msg, ll_dian, mContext, listADbeans);
110 | tu.startViewPager(4000);//动态设置滑动间隔,并且开启轮播图
111 | }
112 |
113 | /**
114 | * 初始化布局
115 | */
116 | private void initView() {
117 | ad_viewPage = (ViewPager)findViewById(R.id.ad_viewPage);
118 | tv_msg = (TextView)findViewById(R.id.tv_msg);
119 | ll_dian = (LinearLayout)findViewById(R.id.ll_dian);
120 |
121 | }
122 | /**
123 | * 销毁轮播图
124 | */
125 | @Override
126 | protected void onDestroy() {
127 | tu.destroyView();
128 | super.onDestroy();
129 | }
130 |
131 | }
132 |
--------------------------------------------------------------------------------
/TuTu/src/com/example/lunbotu/MyAdapter.java:
--------------------------------------------------------------------------------
1 | package com.example.lunbotu;
2 |
3 | import java.util.List;
4 |
5 | import android.support.v4.view.PagerAdapter;
6 | import android.view.View;
7 | import android.view.View.OnClickListener;
8 | import android.view.ViewGroup;
9 | import android.widget.ImageView;
10 | import android.widget.ImageView.ScaleType;
11 | import android.widget.RelativeLayout;
12 | import android.widget.LinearLayout.LayoutParams;
13 |
14 | public class MyAdapter extends PagerAdapter {
15 | List listADbeans=null;
16 | OnItemClickListener onItemClickListener;
17 | public MyAdapter(List listADbeans) {
18 | this.listADbeans = listADbeans;
19 |
20 | }
21 | public int getCount() {
22 | //把这个条数数值很大很大
23 | if(listADbeans != null && listADbeans.size()==1){
24 | return 1;
25 | }else{
26 | return Integer.MAX_VALUE;
27 | }
28 |
29 | }
30 | /**相当于getView:实例化每个页面的View和添加View
31 | * container:ViewPage 容器
32 | * position 位置
33 | */
34 | public Object instantiateItem(ViewGroup container, final int position) {
35 |
36 | //根据位置取出某一个View
37 | ImageView view = null;
38 | if(listADbeans.size()==1){
39 | view = listADbeans.get(0).getmImageView();
40 | if(listADbeans.get(0).getImgPath() != -1){
41 | view.setBackgroundResource(listADbeans.get(0).getImgPath());
42 | }
43 | }else{
44 | view = listADbeans.get(position%listADbeans.size()).getmImageView();
45 | if(listADbeans.get(position%listADbeans.size()).getImgPath() != -1){
46 | view.setBackgroundResource(listADbeans.get(position%listADbeans.size()).getImgPath());
47 | }
48 | ViewGroup parent = (ViewGroup) view.getParent();
49 | if (parent != null ) {
50 | //parent.removeView(view);
51 | container.removeView(view);
52 | }
53 | }
54 |
55 |
56 |
57 | view.setScaleType(ScaleType.FIT_XY);
58 |
59 | //添加到容器
60 | container.addView(view);
61 | /**
62 | * 添加点击事件
63 | */
64 | view.setOnClickListener(new OnClickListener() {
65 | public void onClick(View v) {
66 | onItemClickListener.OnItemClick(v, position%listADbeans.size());
67 | }
68 | });
69 |
70 | return view;//返回实例化的View
71 | }
72 | /**
73 | * 判断view和instantiateItem返回的对象是否一样
74 | * Object : 时instantiateItem返回的对象
75 | */
76 | public boolean isViewFromObject(View view, Object object) {
77 | if(view == object){
78 | return true;
79 | }else{
80 | return false;
81 | }
82 | }
83 |
84 |
85 | /**|
86 | * 实例化两张图片,最多只能装三张图片
87 | */
88 | public void destroyItem(ViewGroup container, int position, Object object) {
89 |
90 | //释放资源,
91 | //container.removeView((View) object);
92 |
93 | }
94 |
95 | public synchronized void notifyImages(List listADbeans){
96 | this.listADbeans = listADbeans;
97 | notifyDataSetChanged();
98 | }
99 |
100 | public interface OnItemClickListener{
101 | void OnItemClick(View view,int position);
102 | }
103 |
104 | public void setOnItemClickListener(OnItemClickListener onItemClickListener){
105 | this.onItemClickListener = onItemClickListener;
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/TuTu/src/com/example/lunbotu/ThreadPoolManager.java:
--------------------------------------------------------------------------------
1 | package com.example.lunbotu;
2 |
3 | import java.util.concurrent.ExecutorService;
4 | import java.util.concurrent.Executors;
5 |
6 | /**
7 | * 线程管理器
8 | **/
9 | public class ThreadPoolManager {
10 | private ExecutorService service;
11 |
12 | private ThreadPoolManager(){
13 | int num = Runtime.getRuntime().availableProcessors();
14 | service = Executors.newFixedThreadPool(num);
15 |
16 | }
17 |
18 | private static final ThreadPoolManager manager= new ThreadPoolManager();
19 |
20 | public static ThreadPoolManager getInstance(){
21 | return manager;
22 | }
23 |
24 | public void addTask(Runnable runnable){
25 | service.execute(runnable);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/TuTu/src/com/example/lunbotu/TuTu.java:
--------------------------------------------------------------------------------
1 | package com.example.lunbotu;
2 |
3 | import java.lang.reflect.Field;
4 | import java.util.ArrayList;
5 | import java.util.List;
6 | import java.util.Timer;
7 | import java.util.TimerTask;
8 |
9 | import com.example.lunbotu.ImageUtil.ImageCallback;
10 | import com.example.lunbotu.MyAdapter.OnItemClickListener;
11 |
12 | import android.annotation.SuppressLint;
13 | import android.content.Context;
14 | import android.graphics.Bitmap;
15 | import android.graphics.drawable.BitmapDrawable;
16 | import android.graphics.drawable.Drawable;
17 | import android.os.Handler;
18 | import android.support.v4.view.ViewPager;
19 | import android.support.v4.view.ViewPager.OnPageChangeListener;
20 | import android.text.TextUtils;
21 | import android.util.Log;
22 | import android.view.View;
23 | import android.view.View.OnClickListener;
24 | import android.view.animation.AccelerateInterpolator;
25 | import android.view.animation.Interpolator;
26 | import android.widget.ImageView;
27 | import android.widget.LinearLayout;
28 | import android.widget.Scroller;
29 | import android.widget.TextView;
30 | import android.widget.LinearLayout.LayoutParams;
31 |
32 | public class TuTu implements OnItemClickListener {
33 | public static final String TAG = "TuTu";
34 | private ViewPager mViewPager;
35 | private TextView mTextView;
36 | private LinearLayout mLinearLayout;
37 | private MyAdapter myPagerAdapter;
38 | private int lastPoint = 0;
39 | private boolean isRunning = false;
40 | boolean stat = false;
41 | private Timer timer;
42 | private TimerTask timerTask;
43 | private List listADbeans;
44 | private Context mContext;
45 | private ImageUtil imageUtil;
46 | private int newPosition=0;
47 | private long delay=4000;
48 | Handler handler = new Handler() {
49 | public void handleMessage(android.os.Message msg) {
50 | int what = msg.what;
51 | if(what == 0){
52 | if(listADbeans.size()>1){
53 | mViewPager.setCurrentItem(mViewPager.getCurrentItem()+1, true);
54 | }
55 |
56 |
57 | }
58 | if(what ==1){
59 | myPagerAdapter.notifyImages(listADbeans);
60 | }
61 | };
62 | };
63 | public TuTu(ViewPager mViewPager,TextView mTextView,LinearLayout mLinearLayout,Context mContext,List listADbeans) {
64 | this.mContext = mContext;
65 | this.listADbeans = listADbeans;
66 | this.mViewPager = mViewPager;
67 | this.mTextView = mTextView;
68 | this.mLinearLayout = mLinearLayout;
69 | imageUtil = new ImageUtil(mContext);
70 | //changeViewpagerSpace();
71 | initADViewpager();
72 |
73 | }
74 |
75 | /**
76 | * 改变viewpager切换速度
77 | */
78 | private void changeViewpagerSpace() {
79 | try {
80 | Field field = ViewPager.class.getDeclaredField("mScroller");
81 | field.setAccessible(true);
82 | FixedSpeedScroller scroller = new FixedSpeedScroller(mViewPager.getContext(),
83 | new AccelerateInterpolator());
84 | field.set(mViewPager, scroller);
85 | //scroller.setmDuration(200);
86 | } catch (Exception e) {
87 | e.printStackTrace();
88 | }
89 |
90 | }
91 | private void initADViewpager() {
92 | for(int i = 0; i < listADbeans.size(); i++){
93 |
94 | ImageView view = new ImageView(mContext);
95 | //view.setBackgroundResource(listADbeans.get(i).getImgPath());
96 | // 把图片添加到列表
97 | listADbeans.get(i).setmImageView(view);
98 | // 实例化指示点
99 | ImageView point = new ImageView(mContext);
100 | point.setImageResource(R.drawable.point_seletor);
101 | LayoutParams params = new LayoutParams(dip2px(mContext,6), dip2px(mContext,6));
102 | params.leftMargin = dip2px(mContext,10);
103 | point.setLayoutParams(params);
104 | // 将指示点添加到线性布局里
105 | mLinearLayout.addView(point);
106 |
107 | // 设置第一个高亮显示
108 | if (i == 0) {
109 | point.setEnabled(true);
110 | } else {
111 | point.setEnabled(false);
112 | }
113 |
114 |
115 | }
116 | // 设置适配器
117 | myPagerAdapter = new MyAdapter(listADbeans);
118 | myPagerAdapter.setOnItemClickListener(this);
119 | mViewPager.setAdapter(myPagerAdapter);
120 | // 设置默认文字信息
121 | if(listADbeans!= null && listADbeans.size()>0 && mTextView!= null){
122 | mTextView.setText(listADbeans.get(0).getAdName());
123 | }
124 | int midPosition = Integer.MAX_VALUE / 2 - Integer.MAX_VALUE / 2
125 | % listADbeans.size();
126 | if(listADbeans.size()==1){
127 | midPosition = 0;
128 | }
129 | mViewPager.setCurrentItem(midPosition);
130 | // 设置页面改变监听
131 | mViewPager.setOnPageChangeListener(new OnPageChangeListener() {
132 | private float mPreviousOffset = -1;
133 | private float mPreviousPosition = -1;
134 | /**
135 | * 当某个页面被选中的时候回调
136 | */
137 | @Override
138 | public void onPageSelected(int position) {
139 | newPosition = position % listADbeans.size();
140 |
141 |
142 | // 取出广告文字
143 | String msg = listADbeans.get(position % listADbeans.size()).getAdName();
144 | if(mTextView!=null){
145 | mTextView.setText(msg);
146 | }
147 |
148 | // 设置对应的页面高亮
149 | mLinearLayout.getChildAt(newPosition).setEnabled(true);
150 | // 是上次的点不显示高亮
151 | mLinearLayout.getChildAt(lastPoint).setEnabled(false);
152 |
153 | lastPoint = newPosition;
154 |
155 | }
156 |
157 | /**
158 | * 当某个页面被滚动的时候回调
159 | */
160 | @Override
161 | public void onPageScrolled(int position, float positionOffset,
162 | int positionOffsetPixels) {
163 |
164 | }
165 |
166 | /**
167 | * 当状态发生改变的时候回调, 静止-滚动-静止
168 | */
169 | @Override
170 | public void onPageScrollStateChanged(int state) {
171 |
172 | if(state ==1){
173 | timer.cancel();
174 | //timerTask.cancel();
175 | stat = true;
176 | }
177 | if(state ==0){
178 | if(stat){
179 | startViewPager(delay);
180 | }
181 | stat = false;
182 | }
183 | }
184 | });
185 |
186 | isRunning = true;
187 | getNetImages();
188 |
189 | }
190 | /**
191 | * 加载网络图片
192 | */
193 | private void getNetImages() {
194 | for(ADBean ad:listADbeans){
195 | String url = ad.getImgUrl();
196 | if(url ==null || TextUtils.isEmpty(url)){
197 | return;
198 | }
199 | String imageName = url.substring(url.lastIndexOf("/")+1, url.length());
200 | if(!imageName.endsWith(".jpg") && !imageName.endsWith(".png")){
201 | imageName += ".png";
202 | }
203 | String imagePath = ImageUtil.IMAGE_PATH+imageName;
204 | if(url!= null && !TextUtils.isEmpty(url)){
205 | imageUtil.loadImage(imageName, url, true, new ImageCallback() {
206 |
207 | @Override
208 | public void onStart(String imageUrl) {
209 | Log.i(TAG, "开始=="+imageUrl);
210 |
211 | }
212 |
213 | @Override
214 | public void onFailed(String imageUrl) {
215 | Log.i(TAG, "失败=="+imageUrl);
216 |
217 | }
218 |
219 | @Override
220 | public void loadImage(Bitmap bitmap, String imageUrl) {
221 | Log.i(TAG, imageUrl);
222 | for(ADBean bean :listADbeans){
223 | if(imageUrl.equals(bean.getImgUrl())){
224 | bean.getmImageView().setImageBitmap(bitmap);
225 | }
226 | }
227 | handler.sendEmptyMessage(1);
228 |
229 | }
230 | });
231 | }
232 | }
233 |
234 | }
235 | /**
236 | * 开启轮播图
237 | * @param delay
238 | */
239 | public void startViewPager(long delay) {
240 | this.delay = delay;
241 | timer = new Timer();
242 | timerTask = new TimerTask() {
243 | public void run() {
244 | handler.sendEmptyMessage(0);
245 | }
246 | };
247 | timer.schedule(timerTask, delay,delay);
248 | }
249 |
250 | public void destroyView() {
251 | if(timer != null){
252 | timer.cancel();
253 | }
254 | if(timerTask!= null){
255 | timerTask.cancel();
256 | }
257 | }
258 |
259 | public class FixedSpeedScroller extends Scroller {
260 | private int mDuration = 400;
261 |
262 | public FixedSpeedScroller(Context context) {
263 | super(context);
264 | }
265 |
266 | public FixedSpeedScroller(Context context, Interpolator interpolator) {
267 | super(context, interpolator);
268 | }
269 |
270 | @Override
271 | public void startScroll(int startX, int startY, int dx, int dy, int duration) {
272 | // Ignore received duration, use fixed one instead
273 | super.startScroll(startX, startY, dx, dy, mDuration);
274 | }
275 |
276 | @Override
277 | public void startScroll(int startX, int startY, int dx, int dy) {
278 | // Ignore received duration, use fixed one instead
279 | super.startScroll(startX, startY, dx, dy, mDuration);
280 | }
281 |
282 | public void setmDuration(int time) {
283 | mDuration = time;
284 | }
285 |
286 | public int getmDuration() {
287 | return mDuration;
288 | }
289 | }
290 | /**
291 | * 根据手机的分辨率从 dip 的单位 转成为 px(像素)
292 | */
293 | public static int dip2px(Context context, float dpValue) {
294 | final float scale = context.getResources().getDisplayMetrics().density;
295 | return (int) (dpValue * scale + 0.5f);
296 | }
297 |
298 | /**
299 | * 根据手机的分辨率从 px(像素) 的单位 转成为 dp
300 | */
301 | public static int px2dip(Context context, float pxValue) {
302 | final float scale = context.getResources().getDisplayMetrics().density;
303 | return (int) (pxValue / scale + 0.5f);
304 | }
305 | /**
306 | * viewpager的item点击事件
307 | */
308 | @Override
309 | public void OnItemClick(View view, int position) {
310 | System.out.println(position+"");
311 |
312 | }
313 |
314 | }
315 |
--------------------------------------------------------------------------------
/TuTu/src/com/example/lunbotu/widget/CircleFlowIndicator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2011 Patrik �kerfeldt
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.example.lunbotu.widget;
17 |
18 |
19 |
20 | import android.content.Context;
21 | import android.content.res.TypedArray;
22 | import android.graphics.Canvas;
23 | import android.graphics.Paint;
24 | import android.graphics.Paint.Style;
25 | import android.os.AsyncTask;
26 | import android.util.AttributeSet;
27 | import android.view.View;
28 | import android.view.animation.Animation;
29 | import android.view.animation.Animation.AnimationListener;
30 | import android.view.animation.AnimationUtils;
31 |
32 | import com.example.lunbotu.R;
33 |
34 | /**
35 | * A FlowIndicator which draws circles (one for each view).
36 | *
37 | * Availables attributes are:
38 | *
39 | * activeColor: Define the color used to draw the active circle (default to white)
40 | *
41 | *
42 | * inactiveColor: Define the color used to draw the inactive circles (default to 0x44FFFFFF)
43 | *
44 | *
45 | * inactiveType: Define how to draw the inactive circles, either stroke or fill (default to stroke)
46 | *
47 | *
48 | * activeType: Define how to draw the active circle, either stroke or fill (default to fill)
49 | *
50 | *
51 | * fadeOut: Define the time (in ms) until the indicator will fade out (default to 0 = never fade out)
52 | *
53 | *
54 | * radius: Define the circle radius (default to 4.0)
55 | *
56 | */
57 | public class CircleFlowIndicator extends View implements FlowIndicator,
58 | AnimationListener {
59 | private static final int STYLE_STROKE = 0;
60 | private static final int STYLE_FILL = 1;
61 |
62 | private float radius = 4;
63 | private float circleSeparation = 2*radius+radius;
64 | private float activeRadius = 0.5f;
65 | private int fadeOutTime = 0;
66 | private final Paint mPaintInactive = new Paint(Paint.ANTI_ALIAS_FLAG);
67 | private final Paint mPaintActive = new Paint(Paint.ANTI_ALIAS_FLAG);
68 | private ViewFlow viewFlow;
69 | private int currentScroll = 0;
70 | private int flowWidth = 0;
71 | private FadeTimer timer;
72 | public AnimationListener animationListener = this;
73 | private Animation animation;
74 | private boolean mCentered = false;
75 |
76 | /**
77 | * Default constructor
78 | *
79 | * @param context
80 | */
81 | public CircleFlowIndicator(Context context) {
82 | super(context);
83 | initColors(0xFFFFFFFF, 0xFFFFFFFF, STYLE_FILL, STYLE_STROKE);
84 | }
85 |
86 | /**
87 | * The contructor used with an inflater
88 | *
89 | * @param context
90 | * @param attrs
91 | */
92 | public CircleFlowIndicator(Context context, AttributeSet attrs) {
93 | super(context, attrs);
94 | // Retrieve styles attributs
95 | TypedArray a = context.obtainStyledAttributes(attrs,
96 | R.styleable.CircleFlowIndicator);
97 |
98 | // Gets the inactive circle type, defaulting to "fill"
99 | int activeType = a.getInt(R.styleable.CircleFlowIndicator_activeType,
100 | STYLE_FILL);
101 |
102 | int activeDefaultColor = 0xFFFFFFFF;
103 |
104 | // Get a custom inactive color if there is one
105 | int activeColor = a
106 | .getColor(R.styleable.CircleFlowIndicator_activeColor,
107 | activeDefaultColor);
108 |
109 | // Gets the inactive circle type, defaulting to "stroke"
110 | int inactiveType = a.getInt(
111 | R.styleable.CircleFlowIndicator_inactiveType, STYLE_STROKE);
112 |
113 | int inactiveDefaultColor = 0x44FFFFFF;
114 | // Get a custom inactive color if there is one
115 | int inactiveColor = a.getColor(
116 | R.styleable.CircleFlowIndicator_inactiveColor,
117 | inactiveDefaultColor);
118 |
119 | // Retrieve the radius
120 | radius = a.getDimension(R.styleable.CircleFlowIndicator_radius, 4.0f);
121 |
122 | circleSeparation = a.getDimension(R.styleable.CircleFlowIndicator_circleSeparation, 2*radius+radius);
123 | activeRadius = a.getDimension(R.styleable.CircleFlowIndicator_activeRadius, 0.5f);
124 | // Retrieve the fade out time
125 | fadeOutTime = a.getInt(R.styleable.CircleFlowIndicator_fadeOut, 0);
126 |
127 | mCentered = a.getBoolean(R.styleable.CircleFlowIndicator_centered, false);
128 |
129 | initColors(activeColor, inactiveColor, activeType, inactiveType);
130 | }
131 |
132 | private void initColors(int activeColor, int inactiveColor, int activeType,
133 | int inactiveType) {
134 | // Select the paint type given the type attr
135 | switch (inactiveType) {
136 | case STYLE_FILL:
137 | mPaintInactive.setStyle(Style.FILL);
138 | break;
139 | default:
140 | mPaintInactive.setStyle(Style.STROKE);
141 | }
142 | mPaintInactive.setColor(inactiveColor);
143 |
144 | // Select the paint type given the type attr
145 | switch (activeType) {
146 | case STYLE_STROKE:
147 | mPaintActive.setStyle(Style.STROKE);
148 | break;
149 | default:
150 | mPaintActive.setStyle(Style.FILL);
151 | }
152 | mPaintActive.setColor(activeColor);
153 | }
154 |
155 | /*
156 | * (non-Javadoc)
157 | *
158 | * @see android.view.View#onDraw(android.graphics.Canvas)
159 | */
160 | @Override
161 | protected void onDraw(Canvas canvas) {
162 | super.onDraw(canvas);
163 | int count = 3;
164 | if (viewFlow != null) {
165 | count = viewFlow.getViewsCount();
166 | }
167 |
168 | //this is the amount the first circle should be offset to make the entire thing centered
169 | float centeringOffset = 0;
170 |
171 | int leftPadding = getPaddingLeft();
172 |
173 | // Draw stroked circles
174 | for (int iLoop = 0; iLoop < count; iLoop++) {
175 | canvas.drawCircle(leftPadding + radius
176 | + (iLoop * circleSeparation) + centeringOffset,
177 | getPaddingTop() + radius, radius, mPaintInactive);
178 | }
179 | float cx = 0;
180 | if (flowWidth != 0) {
181 | // Draw the filled circle according to the current scroll
182 | cx = (currentScroll * circleSeparation) / flowWidth;
183 | }
184 | // The flow width has been upadated yet. Draw the default position
185 | canvas.drawCircle(leftPadding + radius + cx+centeringOffset, getPaddingTop()
186 | + radius, radius + activeRadius, mPaintActive);
187 | }
188 |
189 | /*
190 | * (non-Javadoc)
191 | *
192 | * @see
193 | * org.taptwo.android.widget.ViewFlow.ViewSwitchListener#onSwitched(android
194 | * .view.View, int)
195 | */
196 | @Override
197 | public void onSwitched(View view, int position) {
198 | }
199 |
200 | /*
201 | * (non-Javadoc)
202 | *
203 | * @see
204 | * org.taptwo.android.widget.FlowIndicator#setViewFlow(org.taptwo.android
205 | * .widget.ViewFlow)
206 | */
207 | @Override
208 | public void setViewFlow(ViewFlow view) {
209 | resetTimer();
210 | viewFlow = view;
211 | flowWidth = viewFlow.getWidth();
212 | invalidate();
213 | }
214 |
215 | /*
216 | * (non-Javadoc)
217 | *
218 | * @see org.taptwo.android.widget.FlowIndicator#onScrolled(int, int, int,
219 | * int)
220 | */
221 | @Override
222 | public void onScrolled(int h, int v, int oldh, int oldv) {
223 | setVisibility(View.VISIBLE);
224 | resetTimer();
225 | flowWidth = viewFlow.getWidth();
226 | if(viewFlow.getViewsCount()*flowWidth!=0){
227 | currentScroll = h%(viewFlow.getViewsCount()*flowWidth);
228 | }else {
229 | currentScroll = h;
230 | }
231 | invalidate();
232 | }
233 |
234 | /*
235 | * (non-Javadoc)
236 | *
237 | * @see android.view.View#onMeasure(int, int)
238 | */
239 | @Override
240 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
241 | setMeasuredDimension(measureWidth(widthMeasureSpec),
242 | measureHeight(heightMeasureSpec));
243 | }
244 |
245 | /**
246 | * Determines the width of this view
247 | *
248 | * @param measureSpec
249 | * A measureSpec packed into an int
250 | * @return The width of the view, honoring constraints from measureSpec
251 | */
252 | private int measureWidth(int measureSpec) {
253 | int result = 0;
254 | int specMode = MeasureSpec.getMode(measureSpec);
255 | int specSize = MeasureSpec.getSize(measureSpec);
256 |
257 | // We were told how big to be
258 | if (specMode == MeasureSpec.EXACTLY) {
259 | result = specSize;
260 | }
261 | // Calculate the width according the views count
262 | else {
263 | int count = 3;
264 | if (viewFlow != null) {
265 | count = viewFlow.getViewsCount();
266 | }
267 | float temp = circleSeparation - 2*radius;
268 | result = (int) (getPaddingLeft() + getPaddingRight()
269 | + (count * 2 * radius) + (count - 1) * temp + 1);
270 | // Respect AT_MOST value if that was what is called for by
271 | // measureSpec
272 | if (specMode == MeasureSpec.AT_MOST) {
273 | result = Math.min(result, specSize);
274 | }
275 | }
276 | return result;
277 | }
278 |
279 | /**
280 | * Determines the height of this view
281 | *
282 | * @param measureSpec
283 | * A measureSpec packed into an int
284 | * @return The height of the view, honoring constraints from measureSpec
285 | */
286 | private int measureHeight(int measureSpec) {
287 | int result = 0;
288 | int specMode = MeasureSpec.getMode(measureSpec);
289 | int specSize = MeasureSpec.getSize(measureSpec);
290 |
291 | // We were told how big to be
292 | if (specMode == MeasureSpec.EXACTLY) {
293 | result = specSize;
294 | }
295 | // Measure the height
296 | else {
297 | result = (int) (2 * radius + getPaddingTop() + getPaddingBottom() + 1);
298 | // Respect AT_MOST value if that was what is called for by
299 | // measureSpec
300 | if (specMode == MeasureSpec.AT_MOST) {
301 | result = Math.min(result, specSize);
302 | }
303 | }
304 | return result;
305 | }
306 |
307 | /**
308 | * Sets the fill color
309 | *
310 | * @param color
311 | * ARGB value for the text
312 | */
313 | public void setFillColor(int color) {
314 | mPaintActive.setColor(color);
315 | invalidate();
316 | }
317 |
318 | /**
319 | * Sets the stroke color
320 | *
321 | * @param color
322 | * ARGB value for the text
323 | */
324 | public void setStrokeColor(int color) {
325 | mPaintInactive.setColor(color);
326 | invalidate();
327 | }
328 |
329 | /**
330 | * Resets the fade out timer to 0. Creating a new one if needed
331 | */
332 | private void resetTimer() {
333 | // Only set the timer if we have a timeout of at least 1 millisecond
334 | if (fadeOutTime > 0) {
335 | // Check if we need to create a new timer
336 | if (timer == null || timer._run == false) {
337 | // Create and start a new timer
338 | timer = new FadeTimer();
339 | timer.execute();
340 | } else {
341 | // Reset the current tiemr to 0
342 | timer.resetTimer();
343 | }
344 | }
345 | }
346 |
347 | /**
348 | * Counts from 0 to the fade out time and animates the view away when
349 | * reached
350 | */
351 | private class FadeTimer extends AsyncTask {
352 | // The current count
353 | private int timer = 0;
354 | // If we are inside the timing loop
355 | private boolean _run = true;
356 |
357 | public void resetTimer() {
358 | timer = 0;
359 | }
360 |
361 | @Override
362 | protected Void doInBackground(Void... arg0) {
363 | while (_run) {
364 | try {
365 | // Wait for a millisecond
366 | Thread.sleep(1);
367 | // Increment the timer
368 | timer++;
369 |
370 | // Check if we've reached the fade out time
371 | if (timer == fadeOutTime) {
372 | // Stop running
373 | _run = false;
374 | }
375 | } catch (InterruptedException e) {
376 | // TODO Auto-generated catch block
377 | e.printStackTrace();
378 | }
379 | }
380 | return null;
381 | }
382 |
383 | @Override
384 | protected void onPostExecute(Void result) {
385 | animation = AnimationUtils.loadAnimation(getContext(),
386 | android.R.anim.fade_out);
387 | animation.setAnimationListener(animationListener);
388 | startAnimation(animation);
389 | }
390 | }
391 |
392 | @Override
393 | public void onAnimationEnd(Animation animation) {
394 | setVisibility(View.GONE);
395 | }
396 |
397 | @Override
398 | public void onAnimationRepeat(Animation animation) {
399 | }
400 |
401 | @Override
402 | public void onAnimationStart(Animation animation) {
403 | }
404 | }
--------------------------------------------------------------------------------
/TuTu/src/com/example/lunbotu/widget/FlowIndicator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2011 Patrik �kerfeldt
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.example.lunbotu.widget;
17 |
18 | import com.example.lunbotu.widget.ViewFlow.ViewSwitchListener;
19 |
20 | /**
21 | * An interface which defines the contract between a ViewFlow and a
22 | * FlowIndicator.
23 | * A FlowIndicator is responsible to show an visual indicator on the total views
24 | * number and the current visible view.
25 | *
26 | */
27 | public interface FlowIndicator extends ViewSwitchListener {
28 |
29 | /**
30 | * Set the current ViewFlow. This method is called by the ViewFlow when the
31 | * FlowIndicator is attached to it.
32 | *
33 | * @param view
34 | */
35 | public void setViewFlow(ViewFlow view);
36 |
37 | /**
38 | * The scroll position has been changed. A FlowIndicator may implement this
39 | * method to reflect the current position
40 | *
41 | * @param h
42 | * @param v
43 | * @param oldh
44 | * @param oldv
45 | */
46 | public void onScrolled(int h, int v, int oldh, int oldv);
47 | }
48 |
--------------------------------------------------------------------------------
/TuTu/src/com/example/lunbotu/widget/ImageAdapter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2011 Patrik �kerfeldt
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.example.lunbotu.widget;
17 |
18 | import java.util.List;
19 |
20 | import android.content.Context;
21 | import android.content.Intent;
22 | import android.graphics.Bitmap;
23 | import android.os.Bundle;
24 | import android.view.LayoutInflater;
25 | import android.view.View;
26 | import android.view.View.OnClickListener;
27 | import android.view.ViewGroup;
28 | import android.widget.BaseAdapter;
29 | import android.widget.ImageView;
30 |
31 | import com.example.lunbotu.ADBean;
32 | import com.example.lunbotu.R;
33 |
34 | public class ImageAdapter extends BaseAdapter {
35 | List listADbeans=null;
36 | private Context mContext;
37 | private LayoutInflater mInflater;
38 | private int[] ids = {R.drawable.fore, R.drawable.two,R.drawable.five};
39 |
40 | public ImageAdapter(Context context,List listADbeans) {
41 | mContext = context;
42 | mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
43 | this.listADbeans = listADbeans;
44 | }
45 |
46 | @Override
47 | public int getCount() {
48 | return Integer.MAX_VALUE; //返回很大的值使得getView中的position不断增大来实现循环
49 | }
50 |
51 | @Override
52 | public Object getItem(int position) {
53 | return position;
54 | }
55 |
56 | @Override
57 | public long getItemId(int position) {
58 | return position;
59 | }
60 |
61 | @Override
62 | public View getView(final int position, View convertView, ViewGroup parent) {
63 | if (convertView == null) {
64 | convertView = mInflater.inflate(R.layout.image_item, null);
65 | }
66 | //ImageView imageView = ((ImageView) convertView.findViewById(R.id.imgView));
67 | ImageView imageView = listADbeans.get(position%listADbeans.size()).getmImageView();
68 | if(listADbeans.get(position%listADbeans.size()).getImgPath() != -1){
69 | imageView.setImageResource(listADbeans.get(position%listADbeans.size()).getImgPath());
70 | }else{
71 | if(listADbeans.get(position%listADbeans.size()).getBitmap() != null){
72 | System.out.println("不为空。。。");
73 | imageView.setImageBitmap(listADbeans.get(position%listADbeans.size()).getBitmap());
74 | }
75 | }
76 | //imageView.setImageResource(ids[position%ids.length]);
77 | convertView.setOnClickListener(new OnClickListener() {
78 | @Override
79 | public void onClick(View v) {
80 |
81 | }
82 | });
83 | return imageView;
84 | }
85 | /**
86 | * 判断view和instantiateItem返回的对象是否一样
87 | * Object : 时instantiateItem返回的对象
88 | */
89 | public boolean isViewFromObject(View view, Object object) {
90 | if(view == object){
91 | return true;
92 | }else{
93 | return false;
94 | }
95 | }
96 |
97 |
98 | /**
99 | * 实例化两张图片,最多只能装三张图片
100 | */
101 | public void destroyItem(ViewGroup container, int position, Object object) {
102 |
103 | //释放资源,
104 | container.removeView((View) object);
105 | }
106 |
107 | public void notifyImages(String imageUrl,Bitmap bitmap){
108 | for(ADBean ad:listADbeans){
109 | if(imageUrl.equals(ad.getImgUrl())){
110 | System.out.println(imageUrl);
111 | ad.setBitmap(bitmap);
112 | }
113 | }
114 | }
115 |
116 | }
117 |
--------------------------------------------------------------------------------
/TuTu/src/com/example/lunbotu/widget/TuTu2.java:
--------------------------------------------------------------------------------
1 | package com.example.lunbotu.widget;
2 |
3 | import java.util.List;
4 |
5 | import android.content.Context;
6 | import android.graphics.Bitmap;
7 | import android.os.Handler;
8 | import android.text.TextUtils;
9 | import android.util.Log;
10 | import android.widget.ImageView;
11 |
12 | import com.example.lunbotu.ADBean;
13 | import com.example.lunbotu.ImageUtil;
14 | import com.example.lunbotu.ImageUtil.ImageCallback;
15 |
16 | public class TuTu2 {
17 | private static String TAG = "tutu2";
18 | private List listADbeans2;
19 | private ViewFlow viewFlow;
20 | private ImageUtil imageUtil;
21 | private Context mContext;
22 | private ImageAdapter imageAdapter;
23 |
24 | Handler handler = new Handler() {
25 | public void handleMessage(android.os.Message msg) {
26 | int what = msg.what;
27 | if(what ==1){
28 | //imageAdapter.notifyImages(listADbeans2);
29 | }
30 | };
31 | };
32 |
33 | public TuTu2(Context mContext,ViewFlow viewFlow, List listADbeans2, ImageAdapter imageAdapter) {
34 | this.mContext = mContext;
35 | this.viewFlow = viewFlow;
36 | this.imageAdapter = imageAdapter;
37 | this.listADbeans2 = listADbeans2;
38 | imageUtil = new ImageUtil(mContext);
39 | //getNetImage();
40 | }
41 | public void getNetImage() {
42 | for(ADBean ad:listADbeans2){
43 | String url = ad.getImgUrl();
44 | if(url ==null || TextUtils.isEmpty(url)){
45 | return;
46 | }
47 | String imageName = url.substring(url.lastIndexOf("/")+1, url.length());
48 | if(!imageName.endsWith(".jpg") && !imageName.endsWith(".png")){
49 | imageName += ".png";
50 | }
51 | String imagePath = ImageUtil.IMAGE_PATH+imageName;
52 | if(url!= null && !TextUtils.isEmpty(url)){
53 | imageUtil.loadImage(imageName, url, true, new ImageCallback() {
54 |
55 | @Override
56 | public void onStart(String imageUrl) {
57 | // TODO Auto-generated method stub
58 |
59 | }
60 |
61 | @Override
62 | public void onFailed(String imageUrl) {
63 | // TODO Auto-generated method stub
64 |
65 | }
66 |
67 | @Override
68 | public void loadImage(Bitmap bitmap, String imageUrl) {
69 | /*for(ADBean ad:listADbeans2){
70 | if(imageUrl.equals(ad.getImgUrl())){
71 | ad.getmImageView().setImageBitmap(bitmap);
72 | }
73 | }
74 | handler.sendEmptyMessage(1);*/
75 | imageAdapter.notifyImages(imageUrl, bitmap);
76 |
77 | };
78 | });
79 | }
80 | }
81 |
82 | }
83 | /**
84 | * 设置指示器
85 | * @param indic
86 | */
87 | public void setFlowIndicator(CircleFlowIndicator indic){
88 | viewFlow.setFlowIndicator(indic);
89 | }
90 | /**
91 | * 设置间隔时间
92 | * @param time
93 | */
94 | public void setTimeSpan(long time){
95 | viewFlow.setTimeSpan(time);
96 | }
97 | /**
98 | * 设置初始位置
99 | * @param position
100 | */
101 | public void setSelection(int position){
102 | viewFlow.setSelection(position);
103 | }
104 | /**
105 | * 开始
106 | */
107 | public void startAutoFlowTimer(){
108 | viewFlow.startAutoFlowTimer();
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/TuTu/src/com/example/lunbotu/widget/ViewFlow.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2011 Patrik Åkerfeldt
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.example.lunbotu.widget;
17 |
18 | import java.util.ArrayList;
19 | import java.util.LinkedList;
20 |
21 | import android.content.Context;
22 | import android.content.res.Configuration;
23 | import android.content.res.TypedArray;
24 | import android.database.DataSetObserver;
25 | import android.os.Handler;
26 | import android.os.Message;
27 | import android.util.AttributeSet;
28 | import android.view.MotionEvent;
29 | import android.view.VelocityTracker;
30 | import android.view.View;
31 | import android.view.ViewConfiguration;
32 | import android.view.ViewGroup;
33 | import android.view.ViewTreeObserver.OnGlobalLayoutListener;
34 | import android.widget.AbsListView;
35 | import android.widget.Adapter;
36 | import android.widget.AdapterView;
37 | import android.widget.Scroller;
38 |
39 | import com.example.lunbotu.R;
40 |
41 | /**
42 | * A horizontally scrollable {@link ViewGroup} with items populated from an
43 | * {@link Adapter}. The ViewFlow uses a buffer to store loaded {@link View}s in.
44 | * The default size of the buffer is 3 elements on both sides of the currently
45 | * visible {@link View}, making up a total buffer size of 3 * 2 + 1 = 7. The
46 | * buffer size can be changed using the {@code sidebuffer} xml attribute.
47 | *
48 | */
49 | public class ViewFlow extends AdapterView {
50 |
51 | private static final int SNAP_VELOCITY = 1000;
52 | private static final int INVALID_SCREEN = -1;
53 | private final static int TOUCH_STATE_REST = 0;
54 | private final static int TOUCH_STATE_SCROLLING = 1;
55 |
56 | private LinkedList mLoadedViews;
57 | private int mCurrentBufferIndex;
58 | private int mCurrentAdapterIndex;
59 | private int mSideBuffer = 2;
60 | private Scroller mScroller;
61 | private VelocityTracker mVelocityTracker;
62 | private int mTouchState = TOUCH_STATE_REST;
63 | private float mLastMotionX;
64 | private int mTouchSlop;
65 | private int mMaximumVelocity;
66 | private int mCurrentScreen;
67 | private int mNextScreen = INVALID_SCREEN;
68 | private boolean mFirstLayout = true;
69 | private ViewSwitchListener mViewSwitchListener;
70 | private Adapter mAdapter;
71 | private int mLastScrollDirection;
72 | private AdapterDataSetObserver mDataSetObserver;
73 | private FlowIndicator mIndicator;
74 | private int mLastOrientation = -1;
75 | private long timeSpan = 3000;
76 | private Handler handler;
77 | private OnGlobalLayoutListener orientationChangeListener = new OnGlobalLayoutListener() {
78 |
79 | @Override
80 | public void onGlobalLayout() {
81 | getViewTreeObserver().removeGlobalOnLayoutListener(
82 | orientationChangeListener);
83 | setSelection(mCurrentAdapterIndex);
84 | }
85 | };
86 |
87 | /**
88 | * Receives call backs when a new {@link View} has been scrolled to.
89 | */
90 | public static interface ViewSwitchListener {
91 |
92 | /**
93 | * This method is called when a new View has been scrolled to.
94 | *
95 | * @param view
96 | * the {@link View} currently in focus.
97 | * @param position
98 | * The position in the adapter of the {@link View} currently in focus.
99 | */
100 | void onSwitched(View view, int position);
101 |
102 | }
103 |
104 | public ViewFlow(Context context) {
105 | super(context);
106 | mSideBuffer = 3;
107 | init();
108 | }
109 |
110 | public ViewFlow(Context context, int sideBuffer) {
111 | super(context);
112 | mSideBuffer = sideBuffer;
113 | init();
114 | }
115 |
116 | public ViewFlow(Context context, AttributeSet attrs) {
117 | super(context, attrs);
118 | TypedArray styledAttrs = context.obtainStyledAttributes(attrs,
119 | R.styleable.ViewFlow);
120 | mSideBuffer = styledAttrs.getInt(R.styleable.ViewFlow_sidebuffer, 3);
121 | init();
122 | }
123 |
124 | private void init() {
125 | mLoadedViews = new LinkedList();
126 | mScroller = new Scroller(getContext());
127 | final ViewConfiguration configuration = ViewConfiguration
128 | .get(getContext());
129 | mTouchSlop = configuration.getScaledTouchSlop();
130 | mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
131 | }
132 |
133 | public void startAutoFlowTimer(){
134 | handler = new Handler(){
135 | @Override
136 | public void handleMessage(Message msg) {
137 |
138 | snapToScreen((mCurrentScreen+1)%getChildCount());
139 | Message message = handler.obtainMessage(0);
140 | sendMessageDelayed(message, timeSpan);
141 | }
142 | };
143 |
144 | Message message = handler.obtainMessage(0);
145 | handler.sendMessageDelayed(message, timeSpan);
146 | }
147 | public void stopAutoFlowTimer(){
148 | if(handler!=null)
149 | handler.removeMessages(0);
150 | handler = null;
151 | }
152 |
153 | public void onConfigurationChanged(Configuration newConfig) {
154 | if (newConfig.orientation != mLastOrientation) {
155 | mLastOrientation = newConfig.orientation;
156 | getViewTreeObserver().addOnGlobalLayoutListener(orientationChangeListener);
157 | }
158 | }
159 |
160 | public int getViewsCount() {
161 | return mSideBuffer;
162 | }
163 |
164 | @Override
165 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
166 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
167 |
168 | final int width = MeasureSpec.getSize(widthMeasureSpec);
169 | final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
170 | if (widthMode != MeasureSpec.EXACTLY && !isInEditMode()) {
171 | throw new IllegalStateException(
172 | "ViewFlow can only be used in EXACTLY mode.");
173 | }
174 |
175 | final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
176 | if (heightMode != MeasureSpec.EXACTLY && !isInEditMode()) {
177 | throw new IllegalStateException(
178 | "ViewFlow can only be used in EXACTLY mode.");
179 | }
180 |
181 | // The children are given the same width and height as the workspace
182 | final int count = getChildCount();
183 | for (int i = 0; i < count; i++) {
184 | getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec);
185 | }
186 |
187 | if (mFirstLayout) {
188 | mScroller.startScroll(0, 0, mCurrentScreen * width, 0, 0);
189 | mFirstLayout = false;
190 | }
191 | }
192 |
193 | @Override
194 | protected void onLayout(boolean changed, int l, int t, int r, int b) {
195 | int childLeft = 0;
196 |
197 | final int count = getChildCount();
198 | for (int i = 0; i < count; i++) {
199 | final View child = getChildAt(i);
200 | if (child.getVisibility() != View.GONE) {
201 | final int childWidth = child.getMeasuredWidth();
202 | child.layout(childLeft, 0, childLeft + childWidth,
203 | child.getMeasuredHeight());
204 | childLeft += childWidth;
205 | }
206 | }
207 | }
208 |
209 | @Override
210 | public boolean onInterceptTouchEvent(MotionEvent ev) {
211 | if (getChildCount() == 0)
212 | return false;
213 |
214 | if (mVelocityTracker == null) {
215 | mVelocityTracker = VelocityTracker.obtain();
216 | }
217 | mVelocityTracker.addMovement(ev);
218 |
219 | final int action = ev.getAction();
220 | final float x = ev.getX();
221 |
222 | switch (action) {
223 | case MotionEvent.ACTION_DOWN:
224 | /*
225 | * If being flinged and user touches, stop the fling. isFinished
226 | * will be false if being flinged.
227 | */
228 | if (!mScroller.isFinished()) {
229 | mScroller.abortAnimation();
230 | }
231 |
232 | // Remember where the motion event started
233 | mLastMotionX = x;
234 |
235 | mTouchState = mScroller.isFinished() ? TOUCH_STATE_REST
236 | : TOUCH_STATE_SCROLLING;
237 | if(handler!=null)
238 | handler.removeMessages(0);
239 | break;
240 |
241 | case MotionEvent.ACTION_MOVE:
242 | final int xDiff = (int) Math.abs(x - mLastMotionX);
243 |
244 | boolean xMoved = xDiff > mTouchSlop;
245 |
246 | if (xMoved) {
247 | // Scroll if the user moved far enough along the X axis
248 | mTouchState = TOUCH_STATE_SCROLLING;
249 | }
250 |
251 | if (mTouchState == TOUCH_STATE_SCROLLING) {
252 | // Scroll to follow the motion event
253 | final int deltaX = (int) (mLastMotionX - x);
254 | mLastMotionX = x;
255 |
256 | final int scrollX = getScrollX();
257 | if (deltaX < 0) {
258 | if (scrollX > 0) {
259 | scrollBy(Math.max(-scrollX, deltaX), 0);
260 | }
261 | } else if (deltaX > 0) {
262 | final int availableToScroll = getChildAt(
263 | getChildCount() - 1).getRight()
264 | - scrollX - getWidth();
265 | if (availableToScroll > 0) {
266 | scrollBy(Math.min(availableToScroll, deltaX), 0);
267 | }
268 | }
269 | return true;
270 | }
271 | break;
272 |
273 | case MotionEvent.ACTION_UP:
274 | if (mTouchState == TOUCH_STATE_SCROLLING) {
275 | final VelocityTracker velocityTracker = mVelocityTracker;
276 | velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
277 | int velocityX = (int) velocityTracker.getXVelocity();
278 |
279 | if (velocityX > SNAP_VELOCITY && mCurrentScreen > 0) {
280 | // Fling hard enough to move left
281 | snapToScreen(mCurrentScreen - 1);
282 | } else if (velocityX < -SNAP_VELOCITY
283 | && mCurrentScreen < getChildCount() - 1) {
284 | // Fling hard enough to move right
285 | snapToScreen(mCurrentScreen + 1);
286 | } else {
287 | snapToDestination();
288 | }
289 |
290 | if (mVelocityTracker != null) {
291 | mVelocityTracker.recycle();
292 | mVelocityTracker = null;
293 | }
294 | }
295 |
296 | mTouchState = TOUCH_STATE_REST;
297 | if(handler!=null){
298 | Message message = handler.obtainMessage(0);
299 | handler.sendMessageDelayed(message, timeSpan);
300 | }
301 | break;
302 | case MotionEvent.ACTION_CANCEL:
303 | mTouchState = TOUCH_STATE_REST;
304 | }
305 | return false;
306 | }
307 |
308 | @Override
309 | public boolean onTouchEvent(MotionEvent ev) {
310 | if (getChildCount() == 0)
311 | return false;
312 |
313 | if (mVelocityTracker == null) {
314 | mVelocityTracker = VelocityTracker.obtain();
315 | }
316 | mVelocityTracker.addMovement(ev);
317 |
318 | final int action = ev.getAction();
319 | final float x = ev.getX();
320 |
321 | switch (action) {
322 | case MotionEvent.ACTION_DOWN:
323 | /*
324 | * If being flinged and user touches, stop the fling. isFinished
325 | * will be false if being flinged.
326 | */
327 | if (!mScroller.isFinished()) {
328 | mScroller.abortAnimation();
329 | }
330 |
331 | // Remember where the motion event started
332 | mLastMotionX = x;
333 |
334 | mTouchState = mScroller.isFinished() ? TOUCH_STATE_REST
335 | : TOUCH_STATE_SCROLLING;
336 | if(handler!=null)
337 | handler.removeMessages(0);
338 | break;
339 |
340 | case MotionEvent.ACTION_MOVE:
341 | final int xDiff = (int) Math.abs(x - mLastMotionX);
342 |
343 | boolean xMoved = xDiff > mTouchSlop;
344 |
345 | if (xMoved) {
346 | // Scroll if the user moved far enough along the X axis
347 | mTouchState = TOUCH_STATE_SCROLLING;
348 | }
349 |
350 | if (mTouchState == TOUCH_STATE_SCROLLING) {
351 | // Scroll to follow the motion event
352 | final int deltaX = (int) (mLastMotionX - x);
353 | mLastMotionX = x;
354 |
355 | final int scrollX = getScrollX();
356 | if (deltaX < 0) {
357 | if (scrollX > 0) {
358 | scrollBy(Math.max(-scrollX, deltaX), 0);
359 | }
360 | } else if (deltaX > 0) {
361 | final int availableToScroll = getChildAt(
362 | getChildCount() - 1).getRight()
363 | - scrollX - getWidth();
364 | if (availableToScroll > 0) {
365 | scrollBy(Math.min(availableToScroll, deltaX), 0);
366 | }
367 | }
368 | return true;
369 | }
370 | break;
371 |
372 | case MotionEvent.ACTION_UP:
373 | if (mTouchState == TOUCH_STATE_SCROLLING) {
374 | final VelocityTracker velocityTracker = mVelocityTracker;
375 | velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
376 | int velocityX = (int) velocityTracker.getXVelocity();
377 |
378 | if (velocityX > SNAP_VELOCITY && mCurrentScreen > 0) {
379 | // Fling hard enough to move left
380 | snapToScreen(mCurrentScreen - 1);
381 | } else if (velocityX < -SNAP_VELOCITY
382 | && mCurrentScreen < getChildCount() - 1) {
383 | // Fling hard enough to move right
384 | snapToScreen(mCurrentScreen + 1);
385 | }
386 | // else if (velocityX < -SNAP_VELOCITY
387 | // && mCurrentScreen == getChildCount() - 1) {
388 | // snapToScreen(0);
389 | // }
390 | // else if (velocityX > SNAP_VELOCITY
391 | // && mCurrentScreen == 0) {
392 | // snapToScreen(getChildCount() - 1);
393 | // }
394 | else {
395 | snapToDestination();
396 | }
397 |
398 | if (mVelocityTracker != null) {
399 | mVelocityTracker.recycle();
400 | mVelocityTracker = null;
401 | }
402 | }
403 |
404 | mTouchState = TOUCH_STATE_REST;
405 |
406 | if(handler!=null){
407 | Message message = handler.obtainMessage(0);
408 | handler.sendMessageDelayed(message, timeSpan);
409 | }
410 | break;
411 | case MotionEvent.ACTION_CANCEL:
412 | snapToDestination();
413 | mTouchState = TOUCH_STATE_REST;
414 | }
415 | return true;
416 | }
417 |
418 | @Override
419 | protected void onScrollChanged(int h, int v, int oldh, int oldv) {
420 | super.onScrollChanged(h, v, oldh, oldv);
421 | if (mIndicator != null) {
422 | /*
423 | * The actual horizontal scroll origin does typically not match the
424 | * perceived one. Therefore, we need to calculate the perceived
425 | * horizontal scroll origin here, since we use a view buffer.
426 | */
427 | int hPerceived = h + (mCurrentAdapterIndex - mCurrentBufferIndex)
428 | * getWidth();
429 | mIndicator.onScrolled(hPerceived, v, oldh, oldv);
430 | }
431 | }
432 |
433 | private void snapToDestination() {
434 | final int screenWidth = getWidth();
435 | final int whichScreen = (getScrollX() + (screenWidth / 2))
436 | / screenWidth;
437 |
438 | snapToScreen(whichScreen);
439 | }
440 |
441 | private void snapToScreen(int whichScreen) {
442 | mLastScrollDirection = whichScreen - mCurrentScreen;
443 | if (!mScroller.isFinished())
444 | return;
445 |
446 | whichScreen = Math.max(0, Math.min(whichScreen, getChildCount() - 1));
447 |
448 | mNextScreen = whichScreen;
449 |
450 | final int newX = whichScreen * getWidth();
451 | final int delta = newX - getScrollX();
452 | mScroller.startScroll(getScrollX(), 0, delta, 0, Math.abs(delta) * 2);
453 | invalidate();
454 | }
455 |
456 | @Override
457 | public void computeScroll() {
458 | if (mScroller.computeScrollOffset()) {
459 | scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
460 | postInvalidate();
461 | } else if (mNextScreen != INVALID_SCREEN) {
462 | mCurrentScreen = Math.max(0,
463 | Math.min(mNextScreen, getChildCount() - 1));
464 | mNextScreen = INVALID_SCREEN;
465 | postViewSwitched(mLastScrollDirection);
466 | }
467 | }
468 |
469 | /**
470 | * Scroll to the {@link View} in the view buffer specified by the index.
471 | *
472 | * @param indexInBuffer
473 | * Index of the view in the view buffer.
474 | */
475 | private void setVisibleView(int indexInBuffer, boolean uiThread) {
476 | mCurrentScreen = Math.max(0,
477 | Math.min(indexInBuffer, getChildCount() - 1));
478 | int dx = (mCurrentScreen * getWidth()) - mScroller.getCurrX();
479 | mScroller.startScroll(mScroller.getCurrX(), mScroller.getCurrY(), dx,
480 | 0, 0);
481 | if(dx == 0)
482 | onScrollChanged(mScroller.getCurrX() + dx, mScroller.getCurrY(), mScroller.getCurrX() + dx, mScroller.getCurrY());
483 | if (uiThread)
484 | invalidate();
485 | else
486 | postInvalidate();
487 | }
488 |
489 | /**
490 | * Set the listener that will receive notifications every time the {code
491 | * ViewFlow} scrolls.
492 | *
493 | * @param l
494 | * the scroll listener
495 | */
496 | public void setOnViewSwitchListener(ViewSwitchListener l) {
497 | mViewSwitchListener = l;
498 | }
499 |
500 | @Override
501 | public Adapter getAdapter() {
502 | return mAdapter;
503 | }
504 |
505 | @Override
506 | public void setAdapter(Adapter adapter) {
507 | setAdapter(adapter, 0);
508 | }
509 |
510 | public void setAdapter(Adapter adapter, int initialPosition) {
511 | if (mAdapter != null) {
512 | mAdapter.unregisterDataSetObserver(mDataSetObserver);
513 | }
514 |
515 | mAdapter = adapter;
516 |
517 | if (mAdapter != null) {
518 | mDataSetObserver = new AdapterDataSetObserver();
519 | mAdapter.registerDataSetObserver(mDataSetObserver);
520 |
521 | }
522 | if (mAdapter == null || mAdapter.getCount() == 0)
523 | return;
524 |
525 | setSelection(initialPosition);
526 | }
527 |
528 | @Override
529 | public View getSelectedView() {
530 | return (mCurrentBufferIndex < mLoadedViews.size() ? mLoadedViews
531 | .get(mCurrentBufferIndex) : null);
532 | }
533 |
534 | @Override
535 | public int getSelectedItemPosition() {
536 | return mCurrentAdapterIndex;
537 | }
538 |
539 | /**
540 | * Set the FlowIndicator
541 | *
542 | * @param flowIndicator
543 | */
544 | public void setFlowIndicator(FlowIndicator flowIndicator) {
545 | mIndicator = flowIndicator;
546 | mIndicator.setViewFlow(this);
547 | }
548 |
549 | @Override
550 | public void setSelection(int position) {
551 | mNextScreen = INVALID_SCREEN;
552 | mScroller.forceFinished(true);
553 | if (mAdapter == null)
554 | return;
555 |
556 | position = Math.max(position, 0);
557 | position = Math.min(position, mAdapter.getCount()-1);
558 |
559 | ArrayList recycleViews = new ArrayList();
560 | View recycleView;
561 | while (!mLoadedViews.isEmpty()) {
562 | recycleViews.add(recycleView = mLoadedViews.remove());
563 | detachViewFromParent(recycleView);
564 | }
565 |
566 | View currentView = makeAndAddView(position, true,
567 | (recycleViews.isEmpty() ? null : recycleViews.remove(0)));
568 | mLoadedViews.addLast(currentView);
569 |
570 | for(int offset = 1; mSideBuffer - offset >= 0; offset++) {
571 | int leftIndex = position - offset;
572 | int rightIndex = position + offset;
573 | if(leftIndex >= 0)
574 | mLoadedViews.addFirst(makeAndAddView(leftIndex, false,
575 | (recycleViews.isEmpty() ? null : recycleViews.remove(0))));
576 | if(rightIndex < mAdapter.getCount())
577 | mLoadedViews.addLast(makeAndAddView(rightIndex, true,
578 | (recycleViews.isEmpty() ? null : recycleViews.remove(0))));
579 | }
580 |
581 | mCurrentBufferIndex = mLoadedViews.indexOf(currentView);
582 | mCurrentAdapterIndex = position;
583 |
584 | for (View view : recycleViews) {
585 | removeDetachedView(view, false);
586 | }
587 | requestLayout();
588 | setVisibleView(mCurrentBufferIndex, false);
589 | if (mIndicator != null) {
590 | mIndicator.onSwitched(mLoadedViews.get(mCurrentBufferIndex),
591 | mCurrentAdapterIndex);
592 | }
593 | if (mViewSwitchListener != null) {
594 | mViewSwitchListener
595 | .onSwitched(mLoadedViews.get(mCurrentBufferIndex),
596 | mCurrentAdapterIndex);
597 | }
598 | }
599 |
600 | private void resetFocus() {
601 | mLoadedViews.clear();
602 | removeAllViewsInLayout();
603 |
604 | for (int i = Math.max(0, mCurrentAdapterIndex - mSideBuffer); i < Math
605 | .min(mAdapter.getCount(), mCurrentAdapterIndex + mSideBuffer
606 | + 1); i++) {
607 | mLoadedViews.addLast(makeAndAddView(i, true, null));
608 | if (i == mCurrentAdapterIndex)
609 | mCurrentBufferIndex = mLoadedViews.size() - 1;
610 | }
611 | requestLayout();
612 | }
613 |
614 | private void postViewSwitched(int direction) {
615 | if (direction == 0)
616 | return;
617 |
618 | if (direction > 0) { // to the right
619 | mCurrentAdapterIndex++;
620 | mCurrentBufferIndex++;
621 |
622 | // if(direction > 1) {
623 | // mCurrentAdapterIndex += mAdapter.getCount() - 2;
624 | // mCurrentBufferIndex += mAdapter.getCount() - 2;
625 | // }
626 |
627 | View recycleView = null;
628 |
629 | // Remove view outside buffer range
630 | if (mCurrentAdapterIndex > mSideBuffer) {
631 | recycleView = mLoadedViews.removeFirst();
632 | detachViewFromParent(recycleView);
633 | // removeView(recycleView);
634 | mCurrentBufferIndex--;
635 | }
636 |
637 | // Add new view to buffer
638 | int newBufferIndex = mCurrentAdapterIndex + mSideBuffer;
639 | if (newBufferIndex < mAdapter.getCount())
640 | mLoadedViews.addLast(makeAndAddView(newBufferIndex, true,
641 | recycleView));
642 |
643 | } else { // to the left
644 | mCurrentAdapterIndex--;
645 | mCurrentBufferIndex--;
646 |
647 | // if(direction < -1) {
648 | // mCurrentAdapterIndex -= mAdapter.getCount() - 2;
649 | // mCurrentBufferIndex -= mAdapter.getCount() - 2;
650 | // }
651 |
652 | View recycleView = null;
653 |
654 | // Remove view outside buffer range
655 | if (mAdapter.getCount() - 1 - mCurrentAdapterIndex > mSideBuffer) {
656 | recycleView = mLoadedViews.removeLast();
657 | detachViewFromParent(recycleView);
658 | }
659 |
660 | // Add new view to buffer
661 | int newBufferIndex = mCurrentAdapterIndex - mSideBuffer;
662 | if (newBufferIndex > -1) {
663 | mLoadedViews.addFirst(makeAndAddView(newBufferIndex, false,
664 | recycleView));
665 | mCurrentBufferIndex++;
666 | }
667 |
668 | }
669 |
670 | requestLayout();
671 | setVisibleView(mCurrentBufferIndex, true);
672 | if (mIndicator != null) {
673 | mIndicator.onSwitched(mLoadedViews.get(mCurrentBufferIndex),
674 | mCurrentAdapterIndex);
675 | }
676 | if (mViewSwitchListener != null) {
677 | mViewSwitchListener
678 | .onSwitched(mLoadedViews.get(mCurrentBufferIndex),
679 | mCurrentAdapterIndex);
680 | }
681 | }
682 |
683 | private View setupChild(View child, boolean addToEnd, boolean recycle) {
684 | ViewGroup.LayoutParams p = (ViewGroup.LayoutParams) child
685 | .getLayoutParams();
686 | if (p == null) {
687 | p = new AbsListView.LayoutParams(
688 | ViewGroup.LayoutParams.FILL_PARENT,
689 | ViewGroup.LayoutParams.WRAP_CONTENT, 0);
690 | }
691 | if (recycle)
692 | attachViewToParent(child, (addToEnd ? -1 : 0), p);
693 | else
694 | addViewInLayout(child, (addToEnd ? -1 : 0), p, true);
695 | return child;
696 | }
697 |
698 | private View makeAndAddView(int position, boolean addToEnd, View convertView) {
699 | View view = mAdapter.getView(position, convertView, this);
700 | return setupChild(view, addToEnd, convertView != null);
701 | }
702 |
703 | class AdapterDataSetObserver extends DataSetObserver {
704 |
705 | @Override
706 | public void onChanged() {
707 | View v = getChildAt(mCurrentBufferIndex);
708 | if (v != null) {
709 | for (int index = 0; index < mAdapter.getCount(); index++) {
710 | if (v.equals(mAdapter.getItem(index))) {
711 | mCurrentAdapterIndex = index;
712 | break;
713 | }
714 | }
715 | }
716 | resetFocus();
717 | }
718 |
719 | @Override
720 | public void onInvalidated() {
721 | // Not yet implemented!
722 | }
723 |
724 | }
725 |
726 | public void setTimeSpan(long timeSpan) {
727 | this.timeSpan = timeSpan;
728 | }
729 |
730 | public void setmSideBuffer(int mSideBuffer) {
731 | this.mSideBuffer = mSideBuffer;
732 | }
733 | }
734 |
--------------------------------------------------------------------------------