├── README.md ├── adlibrary ├── .gitignore ├── adlibrary.iml ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── uuch │ │ └── adlibrary │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── uuch │ │ │ └── adlibrary │ │ │ ├── AdConstant.java │ │ │ ├── AdManager.java │ │ │ ├── AnimDialogUtils.java │ │ │ ├── LApplication.java │ │ │ ├── anim │ │ │ └── AnimSpring.java │ │ │ ├── bean │ │ │ └── AdInfo.java │ │ │ ├── transformer │ │ │ ├── DepthPageTransformer.java │ │ │ ├── RotateDownPageTransformer.java │ │ │ └── ZoomOutPageTransformer.java │ │ │ ├── utils │ │ │ └── DisplayUtil.java │ │ │ └── view │ │ │ ├── MetaballView.java │ │ │ └── ProgressLayout.java │ └── res │ │ ├── drawable │ │ └── image_disable.png │ │ ├── layout │ │ ├── ad_dialog_content_layout.xml │ │ ├── anim_dialog_layout.xml │ │ ├── progress_empty_custom_view.xml │ │ ├── progress_empty_view.xml │ │ ├── progress_error_view.xml │ │ ├── progress_error_view_small.xml │ │ ├── progress_loading_view.xml │ │ └── viewpager_item.xml │ │ ├── mipmap-xhdpi │ │ ├── ic_cancel_popup.png │ │ ├── ic_nodata_reminder.png │ │ ├── image_disable.png │ │ └── image_loading.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_cancel_popup.png │ │ ├── ic_nodata_reminder.png │ │ ├── image_disable.png │ │ └── image_loading.png │ │ └── values │ │ ├── attrs.xml │ │ ├── colors.xml │ │ └── strings.xml │ └── test │ └── java │ └── com │ └── uuch │ └── adlibrary │ └── ExampleUnitTest.java ├── android-adDialog.iml ├── app ├── .gitignore ├── app.iml ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── uuch │ │ └── android_addialog │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── uuch │ │ │ └── android_addialog │ │ │ ├── DataBean.java │ │ │ ├── MainActivity.java │ │ │ └── SpinnerAdapter.java │ └── res │ │ ├── layout │ │ ├── activity_main.xml │ │ └── adapter_item.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── uuch │ └── android_addialog │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── images ├── ezgif.com-video-to-gif1.gif ├── ezgif.com-video-to-gif2.gif ├── ezgif.com-video-to-gif3.gif ├── ezgif.com-video-to-gif4.gif ├── ezgif.com-video-to-gif5.gif ├── ezgif.com-video-to-gif6.gif ├── testImage1.png └── testImage2.png ├── local.properties └── settings.gradle /README.md: -------------------------------------------------------------------------------- 1 | # android-adDialog 2 | 3 | **更新日志** 4 | 5 | - compile 1.0 2016/08/08 完成广告活动弹窗1.0版本 6 | 7 | - compile 1.0 2016/08/08 删除demo中约束引用(否则AS2.2以下编译有问题) 8 | 9 | 10 | 11 | 在介绍具体的使用说明之前,我们先看一下简单的实现效果: 12 |

![image](https://github.com/yipianfengye/android-adDialog/blob/master/images/ezgif.com-video-to-gif1.gif) 13 | 14 | **使用说明** 15 | 16 | - 显示一个默认广告弹窗,支持单广告活动、多广告活动,当弹窗显示多广告是默认显示底部小圆圈,当显示单活动时默认不显示底部小圆圈; 17 | 18 | - 默认支持弹窗从上,下,左,右,左上,右上,左下,右下等八个方向弹出,更可以设置从任意指定的角度(0-360)弹出; 19 | 20 | - 默认继承了弹性动画效果,可以设定弹性动画弹性参数,动画速度等; 21 | 22 | - 支持对弹窗背景透明色的更改,支持对弹窗透明,支持设置弹窗背景全屏显示或者是只在内容区域显示; 23 | 24 | - 支持设定弹窗宽高比,支持设置弹窗距离屏幕两侧距离,支持设置关闭按钮是否显示; 25 | 26 | - 支持对关闭按钮点击事件的回调,对每一项广告活动点击事件的回调等; 27 | 28 | - 支持对ViewPager滑动动画效果的设定,支持自定义ViewPager滑动动画效果; 29 | 30 | **API说明:** 31 | 32 | 所有的设置参数均返回AdManager对象,所以可以直接链式调用。 33 | ``` 34 | AdManager adManager = new AdManager(MainActivity.this, advList); 35 | aDMamager. 36 | /** 37 | * 设置弹窗背景全屏显示还是在内容区域显示 38 | */ 39 | .setOverScreen(true) 40 | /** 41 | * 设置ViewPager的滑动动画 42 | */ 43 | .setPageTransformer(new DepthPageTransformer()) 44 | /** 45 | * 设置弹窗距离屏幕两侧的距离(单位dp) 46 | */ 47 | .setPadding(100) 48 | /** 49 | * 设置弹窗的宽高比 50 | */ 51 | .setWidthPerHeight(0.75f) 52 | /** 53 | * 设置弹窗的背景色(当弹窗背景设置透明时,此设置失效) 54 | */ 55 | .setBackViewColor(Color.parseColor("#AA333333")) 56 | /** 57 | * 设置弹窗背景是否透明 58 | */ 59 | .setAnimBackViewTransparent(true) 60 | /** 61 | * 设置弹窗关闭图标是否可见 62 | */ 63 | .setDialogCloseable(false) 64 | /** 65 | * 设置弹窗弹性滑动弹性值 66 | */ 67 | .setBounciness(15) 68 | /** 69 | * 设置弹窗弹性滑动速度值 70 | */ 71 | .setSpeed(5) 72 | /** 73 | * 设定弹窗点击事件回调 74 | */ 75 | .setOnImageClickListener(new AdManager.OnImageClickListener() {}) 76 | /** 77 | * 设定关闭按钮点击事件回调 78 | */ 79 | .setOnCliseClickListener(new OnClickListener() {}) 80 | /** 81 | * 开始执行弹窗的显示操作,可传值为0-360,0表示从右开始弹出,逆时针方向,也可以传入自定义的方向值 82 | */ 83 | .showAdDialog(AdConstant.ANIM_UP_TO_DOWN) 84 | ``` 85 | 86 | **使用方式:** 87 | 88 | - 在module的build.gradle中执行compile操作 89 | 90 | ``` 91 | compile 'cn.yipianfengye.android:ad-library:1.0' 92 | ``` 93 | 94 | - 在代码中初始化数据 95 | 96 | ``` 97 | /** 98 | * 初始化数据 99 | */ 100 | private void initData() { 101 | advList = new ArrayList<>(); 102 | AdInfo adInfo = new AdInfo(); 103 | adInfo.setActivityImg("https://raw.githubusercontent.com/yipianfengye/android-adDialog/master/images/testImage1.png"); 104 | advList.add(adInfo); 105 | 106 | adInfo = new AdInfo(); 107 | adInfo.setActivityImg("https://raw.githubusercontent.com/yipianfengye/android-adDialog/master/images/testImage2.png"); 108 | advList.add(adInfo); 109 | } 110 | ``` 111 | 这里只要是初始化图片的UI地址信息,方便我们的后续下载操作。 112 | 113 | - 执行弹窗的初始化与现实操作 114 | 115 | ``` 116 | /** 117 | * 创建广告活动管理对象 118 | */ 119 | AdManager adManager = new AdManager(MainActivity.this, advList); 120 | adManager.setOverScreen(true) 121 | .setPageTransformer(new DepthPageTransformer()); 122 | /** 123 | * 执行弹窗的显示操作 124 | */ 125 | adManager.showAdDialog(AdConstant.ANIM_DOWN_TO_UP); 126 | ``` 127 | 128 | 怎么样是不是很简单?下面我们可以来看一下具体API。 129 | 130 | **具体的API说明:** 131 | 132 | - (1)自定义的弹窗弹出方向API 133 | 134 | 在执行AdManager的showAdDialog方法时,需要传递一个int型的animType参数,我们默认定义了八个该类型的参数,默认如下: 135 | 136 | ``` 137 | // ####################### 弹出动画效果 ########################### 138 | /** 139 | * 广告活动弹窗动画-从上至下 140 | */ 141 | public static final int ANIM_UP_TO_DOWN = -11; 142 | /** 143 | * 广告活动弹窗动画-从下至上 144 | */ 145 | public static final int ANIM_DOWN_TO_UP = -12; 146 | /** 147 | * 广告活动弹窗动画-从左至右 148 | */ 149 | public static final int ANIM_LEFT_TO_RIGHT = -13; 150 | /** 151 | * 广告活动弹窗动画-从右至左 152 | */ 153 | public static final int ANIM_RIGHT_TO_LEFT = -14; 154 | /** 155 | * 广告活动弹窗动画-从左上弹出 156 | */ 157 | public static final int ANIM_UPLEFT_TO_CENTER = -15; 158 | /** 159 | * 广告活动弹窗动画-从右上弹出 160 | */ 161 | public static final int ANIM_UPRIGHT_TO_CENTER = -16; 162 | /** 163 | * 广告活动弹窗动画-从左下弹出 164 | */ 165 | public static final int ANIM_DOWNLEFT_TO_CENTER = -17; 166 | /** 167 | * 广告活动弹窗动画-从右下弹出 168 | */ 169 | public static final int ANIM_DOWNRIGHT_TO_CENTER = -18; 170 | ``` 171 | 172 | 好吧,如果你觉得还不够好,我想让弹窗从右上侧30度角的弹出可以么?这也是支持的,只需要你传递的int型的animType的时候传递30就好了,如下: 173 | 174 | ``` 175 | /** 176 | * 执行弹窗的显示操作(参数的范围:0-360,0表示从右侧弹出,逆时针旋转) 177 | */ 178 | adManager.showAdDialog(30); 179 | ``` 180 | 181 | 那么我们看一下执行效果呢: 182 | 183 | ![image](https://github.com/yipianfengye/android-adDialog/blob/master/images/ezgif.com-video-to-gif2.gif) 184 | 185 | - (2)自定义弹窗距离屏幕两侧的距离以及弹窗的宽高比: 186 | 187 | ``` 188 | /** 189 | * 自定义设置广告活动弹窗距离屏幕两侧距离以及宽高比 190 | */ 191 | button2.setOnClickListener(new View.OnClickListener() { 192 | @Override 193 | public void onClick(View v) { 194 | AdManager adManager = new AdManager(MainActivity.this, advList); 195 | 196 | adManager.setOnImageClickListener(new AdManager.OnImageClickListener() { 197 | @Override 198 | public void onImageClick(View view, AdInfo advInfo) { 199 | Toast.makeText(MainActivity.this, "您点击了ViewPagerItem...", Toast.LENGTH_SHORT).show(); 200 | } 201 | }) 202 | .setPadding(100) 203 | .setWidthPerHeight(0.5f) 204 | .showAdDialog(AdConstant.ANIM_UP_TO_DOWN); 205 | } 206 | }); 207 | ``` 208 | 209 | 然后我们看一下执行效果: 210 | 211 | ![image](https://github.com/yipianfengye/android-adDialog/blob/master/images/ezgif.com-video-to-gif3.gif) 212 | 213 | 怎么样?是不是发现弹窗的宽高比和距离屏幕两侧的距离发生了变化? 214 | 215 | - (3)自定义背景颜色,自定义弹窗是否覆盖全屏,关闭按钮是否显示 216 | 217 | ``` 218 | /** 219 | * 自定义弹窗背景颜色,弹窗是否覆盖全屏,关闭按钮是否显示等 220 | */ 221 | button3.setOnClickListener(new View.OnClickListener() { 222 | @Override 223 | public void onClick(View v) { 224 | AdManager adManager = new AdManager(MainActivity.this, advList); 225 | 226 | adManager.setOnImageClickListener(new AdManager.OnImageClickListener() { 227 | @Override 228 | public void onImageClick(View view, AdInfo advInfo) { 229 | Toast.makeText(MainActivity.this, "您点击了ViewPagerItem...", Toast.LENGTH_SHORT).show(); 230 | } 231 | }) 232 | .setBackViewColor(Color.parseColor("#AA333333")) 233 | .setDialogCloseable(false) 234 | .showAdDialog(AdConstant.ANIM_UP_TO_DOWN); 235 | } 236 | }); 237 | ``` 238 | 239 | 然后我们来看一下具体的实现效果: 240 | 241 | ![image](https://github.com/yipianfengye/android-adDialog/blob/master/images/ezgif.com-video-to-gif4.gif) 242 | 243 | 可以看到我们更改了弹窗的背景颜色以及未显示关闭按钮 244 | 245 | - (4)自定义设置弹性动画弹性参数和速度参数 246 | 247 | ``` 248 | /** 249 | * 自定义设定弹窗弹性参数和速度参数 250 | */ 251 | button4.setOnClickListener(new View.OnClickListener() { 252 | @Override 253 | public void onClick(View v) { 254 | AdManager adManager = new AdManager(MainActivity.this, advList); 255 | 256 | adManager.setOnImageClickListener(new AdManager.OnImageClickListener() { 257 | @Override 258 | public void onImageClick(View view, AdInfo advInfo) { 259 | Toast.makeText(MainActivity.this, "您点击了ViewPagerItem...", Toast.LENGTH_SHORT).show(); 260 | } 261 | }) 262 | .setBounciness(20) 263 | .setSpeed(4) 264 | .showAdDialog(AdConstant.ANIM_UP_TO_DOWN); 265 | } 266 | }); 267 | ``` 268 | 269 | 然后我们看一下动画效果: 270 |
![image](https://github.com/yipianfengye/android-adDialog/blob/master/images/ezgif.com-video-to-gif5.gif) 271 | 272 | 为了明显的展示出动画效果,我们设置的弹性参数和速度参数比较大,是不是比较出来了这两个参数的作用? 273 | 274 | - (5)自定义设置弹窗ViewPager滑动动画: 275 | 276 | ``` 277 | /** 278 | * 自定义设置弹窗ViewPager滑动动画 279 | */ 280 | button5.setOnClickListener(new View.OnClickListener() { 281 | @Override 282 | public void onClick(View v) { 283 | AdManager adManager = new AdManager(MainActivity.this, advList); 284 | 285 | adManager.setOnImageClickListener(new AdManager.OnImageClickListener() { 286 | @Override 287 | public void onImageClick(View view, AdInfo advInfo) { 288 | Toast.makeText(MainActivity.this, "您点击了ViewPagerItem...", Toast.LENGTH_SHORT).show(); 289 | } 290 | }) 291 | .setPageTransformer(new RotateDownPageTransformer()) 292 | .showAdDialog(AdConstant.ANIM_UP_TO_DOWN); 293 | } 294 | }); 295 | ``` 296 | 297 | 然后我们看一下弹窗的滑动动画: 298 | 299 | ![image](https://github.com/yipianfengye/android-adDialog/blob/master/images/ezgif.com-video-to-gif6.gif) 300 | 301 | 这里我内置了三种ViewPager的滑动动画效果: 302 | 303 | ``` 304 | DepthPageTransformer; 305 | RotateDownPageTransformer; 306 | ZoomOutPageTransformer; 307 | ``` 308 | 我们还可以自定义实现:PageTransformer自定义出自己的滑动动画效果,更多关于PageTransformer的知识,可参考鸿洋大神的: Android 实现个性的ViewPager切换动画 实战PageTransformer(兼容Android3.0以下) 309 | 310 | - (6)自定义关闭按钮点击事件回调,ViewPagerItem点击事件回调 311 | 312 | ``` 313 | /** 314 | * 自定义设置弹窗ViewPagerItem点击事件,关闭按钮点击事件回调 315 | */ 316 | button6.setOnClickListener(new View.OnClickListener() { 317 | @Override 318 | public void onClick(View v) { 319 | AdManager adManager = new AdManager(MainActivity.this, advList); 320 | 321 | adManager.setOnImageClickListener(new AdManager.OnImageClickListener() { 322 | @Override 323 | public void onImageClick(View view, AdInfo advInfo) { 324 | Toast.makeText(MainActivity.this, "您点击了ViewPagerItem...", Toast.LENGTH_SHORT).show(); 325 | } 326 | }) 327 | .setOnCloseClickListener(new View.OnClickListener() { 328 | @Override 329 | public void onClick(View v) { 330 | Toast.makeText(MainActivity.this, "您点击了关闭按钮...", Toast.LENGTH_SHORT).show(); 331 | } 332 | }) 333 | .showAdDialog(AdConstant.ANIM_UP_TO_DOWN); 334 | } 335 | }); 336 | ``` 337 | 338 | 好吧,以上就是广告活动弹窗的API,除了以上还可以添加其他的一些API,欢迎提出。 339 | 340 | 以上就是这个控件的相关内容,欢迎star和follow,也可参考我的blog:Github项目解析(十一)-->一个简单强大的自定义广告活动弹窗 341 | -------------------------------------------------------------------------------- /adlibrary/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /adlibrary/adlibrary.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /adlibrary/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "24.0.0" 6 | 7 | defaultConfig { 8 | minSdkVersion 14 9 | targetSdkVersion 22 10 | versionCode 1 11 | versionName "1.0" 12 | 13 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 14 | 15 | } 16 | buildTypes { 17 | release { 18 | minifyEnabled false 19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 20 | } 21 | } 22 | } 23 | 24 | dependencies { 25 | compile fileTree(dir: 'libs', include: ['*.jar']) 26 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 27 | exclude group: 'com.android.support', module: 'support-annotations' 28 | }) 29 | compile 'com.android.support:appcompat-v7:23.4.0' 30 | compile 'com.facebook.rebound:rebound:0.3.8' 31 | compile 'com.nineoldandroids:library:2.4.0' 32 | compile 'com.flyco.pageindicator:FlycoPageIndicator_Lib:1.0.0@aar' 33 | compile 'com.facebook.fresco:fresco:0.12.0' 34 | compile 'com.malinskiy:materialicons:1.0.2' 35 | compile 'com.android.support:support-v4:23.0.0' 36 | testCompile 'junit:junit:4.12' 37 | } 38 | 39 | ext { 40 | PUBLISH_GROUP_ID = 'cn.yipianfengye.android' 41 | PUBLISH_ARTIFACT_ID = 'ad-library' 42 | PUBLISH_VERSION = '1.0' 43 | } 44 | 45 | apply from: 'https://raw.githubusercontent.com/blundell/release-android-library/master/android-release-aar.gradle' -------------------------------------------------------------------------------- /adlibrary/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/aaron/document/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /adlibrary/src/androidTest/java/com/uuch/adlibrary/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.uuch.adlibrary; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumentation test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.uuch.adlibrary.test", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /adlibrary/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /adlibrary/src/main/java/com/uuch/adlibrary/AdConstant.java: -------------------------------------------------------------------------------- 1 | package com.uuch.adlibrary; 2 | 3 | /** 4 | * Created by aaron on 16/8/2. 5 | * 广告、活动弹窗静态变量 6 | */ 7 | public class AdConstant { 8 | 9 | // ####################### 弹出动画效果 ########################### 10 | /** 11 | * 广告活动弹窗动画-从上至下 12 | */ 13 | public static final int ANIM_UP_TO_DOWN = -11; 14 | /** 15 | * 广告活动弹窗动画-从下至上 16 | */ 17 | public static final int ANIM_DOWN_TO_UP = -12; 18 | /** 19 | * 广告活动弹窗动画-从左至右 20 | */ 21 | public static final int ANIM_LEFT_TO_RIGHT = -13; 22 | /** 23 | * 广告活动弹窗动画-从右至左 24 | */ 25 | public static final int ANIM_RIGHT_TO_LEFT = -14; 26 | /** 27 | * 广告活动弹窗动画-从左上弹出 28 | */ 29 | public static final int ANIM_UPLEFT_TO_CENTER = -15; 30 | /** 31 | * 广告活动弹窗动画-从右上弹出 32 | */ 33 | public static final int ANIM_UPRIGHT_TO_CENTER = -16; 34 | /** 35 | * 广告活动弹窗动画-从左下弹出 36 | */ 37 | public static final int ANIM_DOWNLEFT_TO_CENTER = -17; 38 | /** 39 | * 广告活动弹窗动画-从右下弹出 40 | */ 41 | public static final int ANIM_DOWNRIGHT_TO_CENTER = -18; 42 | 43 | /** 44 | * 判断是否是常量类型动画 45 | * @param animType 46 | * @return 47 | */ 48 | public static boolean isConstantAnim(int animType) { 49 | if (animType == ANIM_UP_TO_DOWN || animType == ANIM_DOWN_TO_UP 50 | || animType == ANIM_LEFT_TO_RIGHT || animType == ANIM_RIGHT_TO_LEFT 51 | || animType == ANIM_UPLEFT_TO_CENTER || animType == ANIM_UPRIGHT_TO_CENTER 52 | || animType == ANIM_DOWNLEFT_TO_CENTER || animType == ANIM_DOWNRIGHT_TO_CENTER) { 53 | return true; 54 | } 55 | 56 | return false; 57 | } 58 | 59 | /** 60 | * 判断是否是自定义角度动画 61 | * @param animType 62 | * @return 63 | */ 64 | public static boolean isCircleAnim(int animType) { 65 | if (animType >= 0 && animType <= 360) { 66 | return true; 67 | } 68 | 69 | return false; 70 | } 71 | 72 | // ########################## 弹出动画效果 ################################# 73 | 74 | // ########################## 退出动画效果 ################################# 75 | 76 | /** 77 | * 退出动画-默认无动画效果 78 | */ 79 | public static final int ANIM_STOP_DEFAULT = 1; 80 | /** 81 | * 退出动画-默认渐变透明效果 82 | */ 83 | public static final int ANIM_STOP_TRANSPARENT = 2; 84 | 85 | // ########################## 退出动画效果 ################################# 86 | 87 | 88 | // ########################## 弹性动画参数 ################################## 89 | /** 90 | * 弹性动画弹性参数 91 | */ 92 | public static final double BOUNCINESS = 8; 93 | /** 94 | * 弹性动画速度参数 95 | */ 96 | public static final double SPEED = 2; 97 | 98 | 99 | } 100 | -------------------------------------------------------------------------------- /adlibrary/src/main/java/com/uuch/adlibrary/AdManager.java: -------------------------------------------------------------------------------- 1 | package com.uuch.adlibrary; 2 | 3 | import android.app.Activity; 4 | import android.graphics.Color; 5 | import android.graphics.drawable.Animatable; 6 | import android.net.Uri; 7 | import android.os.Handler; 8 | import android.support.annotation.Nullable; 9 | import android.support.v4.view.PagerAdapter; 10 | import android.support.v4.view.ViewPager; 11 | import android.util.DisplayMetrics; 12 | import android.util.Log; 13 | import android.view.LayoutInflater; 14 | import android.view.View; 15 | import android.view.ViewGroup; 16 | import android.widget.RelativeLayout; 17 | 18 | import com.facebook.drawee.backends.pipeline.Fresco; 19 | import com.facebook.drawee.controller.BaseControllerListener; 20 | import com.facebook.drawee.controller.ControllerListener; 21 | import com.facebook.drawee.interfaces.DraweeController; 22 | import com.facebook.drawee.view.SimpleDraweeView; 23 | import com.facebook.imagepipeline.image.ImageInfo; 24 | import com.flyco.pageindicator.indicator.FlycoPageIndicaor; 25 | import com.uuch.adlibrary.bean.AdInfo; 26 | import com.uuch.adlibrary.utils.DisplayUtil; 27 | 28 | import java.util.List; 29 | 30 | /** 31 | * Created by Administrator on 2015/10/20 0020. 32 | * 首页广告管理类 33 | */ 34 | public class AdManager { 35 | 36 | private Activity context; 37 | private DisplayMetrics displayMetrics = new DisplayMetrics(); 38 | private View contentView; 39 | private ViewPager viewPager; 40 | private RelativeLayout adRootContent; 41 | private AdAdapter adAdapter; 42 | private FlycoPageIndicaor mIndicator; 43 | private AnimDialogUtils animDialogUtils; 44 | List advInfoListList; 45 | /** 46 | * 广告弹窗距离两侧的距离-单位(dp) 47 | */ 48 | private int padding = 44; 49 | /** 50 | * 广告弹窗的宽高比 51 | */ 52 | private float widthPerHeight = 0.75f; 53 | 54 | // 弹窗背景是否透明 55 | private boolean isAnimBackViewTransparent = false; 56 | // 弹窗是否可关闭 57 | private boolean isDialogCloseable = true; 58 | // 弹窗关闭点击事件 59 | private View.OnClickListener onCloseClickListener = null; 60 | // 设置弹窗背景颜色 61 | private int backViewColor = Color.parseColor("#bf000000"); 62 | // 弹性动画弹性参数 63 | private double bounciness = AdConstant.BOUNCINESS; 64 | // 弹性动画速度参数 65 | private double speed = AdConstant.SPEED; 66 | // viewPager滑动动画效果 67 | private ViewPager.PageTransformer pageTransformer = null; 68 | // 是否覆盖全屏幕 69 | private boolean isOverScreen = true; 70 | 71 | private OnImageClickListener onImageClickListener = null; 72 | 73 | 74 | public AdManager(Activity context, List advInfoListList) { 75 | this.context = context; 76 | this.advInfoListList = advInfoListList; 77 | } 78 | 79 | private View.OnClickListener imageOnClickListener = new View.OnClickListener() { 80 | @Override 81 | public void onClick(View view) { 82 | 83 | AdInfo advInfo = (AdInfo) view.getTag(); 84 | if (advInfo != null && onImageClickListener != null) { 85 | onImageClickListener.onImageClick(view, advInfo); 86 | } 87 | } 88 | }; 89 | 90 | /** 91 | * 开始执行显示广告弹窗的操作 92 | * @param animType 93 | */ 94 | public void showAdDialog(final int animType) { 95 | 96 | contentView = LayoutInflater.from(context).inflate(R.layout.ad_dialog_content_layout, null); 97 | adRootContent = (RelativeLayout) contentView.findViewById(R.id.ad_root_content); 98 | 99 | viewPager = (ViewPager) contentView.findViewById(R.id.viewPager); 100 | mIndicator = (FlycoPageIndicaor) contentView.findViewById(R.id.indicator); 101 | 102 | adAdapter = new AdAdapter(); 103 | viewPager.setAdapter(adAdapter); 104 | 105 | if (pageTransformer != null) { 106 | viewPager.setPageTransformer(true, pageTransformer); 107 | } 108 | 109 | mIndicator.setViewPager(viewPager); 110 | isShowIndicator(); 111 | 112 | animDialogUtils = AnimDialogUtils.getInstance(context) 113 | .setAnimBackViewTransparent(isAnimBackViewTransparent) 114 | .setDialogCloseable(isDialogCloseable) 115 | .setDialogBackViewColor(backViewColor) 116 | .setOnCloseClickListener(onCloseClickListener) 117 | .setOverScreen(isOverScreen) 118 | .initView(contentView); 119 | setRootContainerHeight(); 120 | 121 | // 延迟1s展示,为了避免ImageLoader还为加载完缓存图片时就展示了弹窗的情况 122 | new Handler().postDelayed(new Runnable() { 123 | @Override 124 | public void run() { 125 | animDialogUtils.show(animType, bounciness, speed); 126 | } 127 | }, 1000); 128 | } 129 | 130 | /** 131 | * 开始执行销毁弹窗的操作 132 | */ 133 | public void dismissAdDialog() { 134 | animDialogUtils.dismiss(AdConstant.ANIM_STOP_DEFAULT); 135 | } 136 | 137 | 138 | private void setRootContainerHeight() { 139 | 140 | context.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); 141 | int widthPixels = displayMetrics.widthPixels; 142 | int totalPadding = DisplayUtil.dip2px(context, padding * 2); 143 | int width = widthPixels - totalPadding; 144 | final int height = (int) (width / widthPerHeight); 145 | ViewGroup.LayoutParams params = adRootContent.getLayoutParams(); 146 | params.height = height; 147 | } 148 | 149 | /** 150 | * 根据页面数量,判断是否显示Indicator 151 | */ 152 | private void isShowIndicator() { 153 | if (advInfoListList.size() > 1) { 154 | mIndicator.setVisibility(View.VISIBLE); 155 | } else { 156 | mIndicator.setVisibility(View.INVISIBLE); 157 | } 158 | } 159 | 160 | class AdAdapter extends PagerAdapter { 161 | 162 | @Override 163 | public int getCount() { 164 | return advInfoListList.size(); 165 | } 166 | 167 | @Override 168 | public boolean isViewFromObject(View view, Object object) { 169 | return view == object; 170 | } 171 | 172 | @Override 173 | public void destroyItem(ViewGroup container, int position, Object object) { 174 | container.removeView((View) object); 175 | } 176 | 177 | @Override 178 | public Object instantiateItem(ViewGroup container, int position) { 179 | AdInfo advInfo = advInfoListList.get(position); 180 | 181 | View rootView = context.getLayoutInflater().inflate(R.layout.viewpager_item, null); 182 | final ViewGroup errorView = (ViewGroup) rootView.findViewById(R.id.error_view); 183 | final ViewGroup loadingView = (ViewGroup) rootView.findViewById(R.id.loading_view); 184 | final SimpleDraweeView simpleDraweeView = (SimpleDraweeView) rootView.findViewById(R.id.simpleDraweeView); 185 | ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); 186 | container.addView(rootView, params); 187 | simpleDraweeView.setTag(advInfo); 188 | simpleDraweeView.setOnClickListener(imageOnClickListener); 189 | 190 | 191 | ControllerListener controllerListener = new BaseControllerListener() { 192 | @Override 193 | public void onFinalImageSet( 194 | String id, 195 | @Nullable ImageInfo imageInfo, 196 | @Nullable Animatable anim) { 197 | if (imageInfo == null) { 198 | return; 199 | } 200 | errorView.setVisibility(View.GONE); 201 | loadingView.setVisibility(View.GONE); 202 | simpleDraweeView.setVisibility(View.VISIBLE); 203 | } 204 | 205 | @Override 206 | public void onIntermediateImageSet(String id, @Nullable ImageInfo imageInfo) { 207 | Log.i("##########", "onIntermediateImageSet()"); 208 | } 209 | 210 | @Override 211 | public void onFailure(String id, Throwable throwable) { 212 | errorView.setVisibility(View.VISIBLE); 213 | loadingView.setVisibility(View.GONE); 214 | simpleDraweeView.setVisibility(View.GONE); 215 | } 216 | }; 217 | 218 | Uri uri = Uri.parse(advInfo.getActivityImg()); 219 | DraweeController controller = Fresco.newDraweeControllerBuilder() 220 | .setControllerListener(controllerListener) 221 | .setUri(uri) 222 | .build(); 223 | simpleDraweeView.setController(controller); 224 | 225 | 226 | return rootView; 227 | } 228 | } 229 | 230 | 231 | 232 | // ######################## 点击事件处理操作类 ######################## 233 | 234 | /** 235 | * ViewPager每一项的单击事件 236 | */ 237 | public interface OnImageClickListener { 238 | 239 | public void onImageClick(View view, AdInfo advInfo); 240 | 241 | } 242 | 243 | // ######################## get set方法 ######################### 244 | 245 | /** 246 | * 设置弹窗距离屏幕左右两侧的距离 247 | * @param padding 248 | * @return 249 | */ 250 | public AdManager setPadding(int padding) { 251 | this.padding = padding; 252 | 253 | return this; 254 | } 255 | 256 | /** 257 | * 设置弹窗宽高比 258 | * @param widthPerHeight 259 | * @return 260 | */ 261 | public AdManager setWidthPerHeight(float widthPerHeight) { 262 | this.widthPerHeight = widthPerHeight; 263 | 264 | return this; 265 | } 266 | 267 | /** 268 | * 设置ViewPager Item点击事件 269 | * @param onImageClickListener 270 | * @return 271 | */ 272 | public AdManager setOnImageClickListener(OnImageClickListener onImageClickListener) { 273 | this.onImageClickListener = onImageClickListener; 274 | 275 | return this; 276 | } 277 | 278 | /** 279 | * 设置背景是否透明 280 | * @param animBackViewTransparent 281 | * @return 282 | */ 283 | public AdManager setAnimBackViewTransparent(boolean animBackViewTransparent) { 284 | isAnimBackViewTransparent = animBackViewTransparent; 285 | 286 | return this; 287 | } 288 | 289 | /** 290 | * 设置弹窗关闭按钮是否可见 291 | * @param dialogCloseable 292 | * @return 293 | */ 294 | public AdManager setDialogCloseable(boolean dialogCloseable) { 295 | isDialogCloseable = dialogCloseable; 296 | 297 | return this; 298 | } 299 | 300 | /** 301 | * 设置弹窗关闭按钮点击事件 302 | * @param onCloseClickListener 303 | * @return 304 | */ 305 | public AdManager setOnCloseClickListener(View.OnClickListener onCloseClickListener) { 306 | this.onCloseClickListener = onCloseClickListener; 307 | 308 | return this; 309 | } 310 | 311 | /** 312 | * 设置弹窗背景颜色 313 | * @param backViewColor 314 | * @return 315 | */ 316 | public AdManager setBackViewColor(int backViewColor) { 317 | this.backViewColor = backViewColor; 318 | 319 | return this; 320 | } 321 | 322 | /** 323 | * 设置弹窗弹性动画弹性参数 324 | * @param bounciness 325 | * @return 326 | */ 327 | public AdManager setBounciness(double bounciness) { 328 | this.bounciness = bounciness; 329 | 330 | return this; 331 | } 332 | 333 | /** 334 | * 设置弹窗弹性动画速度参数 335 | * @param speed 336 | * @return 337 | */ 338 | public AdManager setSpeed(double speed) { 339 | this.speed = speed; 340 | 341 | return this; 342 | } 343 | 344 | /** 345 | * 设置ViewPager滑动动画效果 346 | * @param pageTransformer 347 | */ 348 | public AdManager setPageTransformer(ViewPager.PageTransformer pageTransformer) { 349 | this.pageTransformer = pageTransformer; 350 | 351 | return this; 352 | } 353 | 354 | /** 355 | * 设置弹窗背景是否覆盖全屏幕 356 | * @param overScreen 357 | * @return 358 | */ 359 | public AdManager setOverScreen(boolean overScreen) { 360 | isOverScreen = overScreen; 361 | 362 | return this; 363 | } 364 | } 365 | -------------------------------------------------------------------------------- /adlibrary/src/main/java/com/uuch/adlibrary/AnimDialogUtils.java: -------------------------------------------------------------------------------- 1 | package com.uuch.adlibrary; 2 | 3 | import android.app.Activity; 4 | import android.graphics.Color; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.view.Window; 9 | import android.widget.FrameLayout; 10 | import android.widget.ImageView; 11 | import android.widget.RelativeLayout; 12 | 13 | import com.uuch.adlibrary.anim.AnimSpring; 14 | 15 | /** 16 | * 使用弹性动画 17 | */ 18 | public class AnimDialogUtils { 19 | private Activity context; 20 | private ViewGroup androidContentView; 21 | private View rootView; 22 | private RelativeLayout animBackView; 23 | private FrameLayout flContentContainer; 24 | private RelativeLayout animContainer; 25 | private ImageView ivClose; 26 | 27 | public static final String ANIM_DIALOG_TAG = "AnimDialogTag"; 28 | 29 | private boolean isShowing = false; 30 | // 弹窗背景是否透明 31 | private boolean isAnimBackViewTransparent = false; 32 | // 弹窗是否可关闭 33 | private boolean isDialogCloseable = true; 34 | // 弹窗关闭点击事件 35 | private View.OnClickListener onCloseClickListener = null; 36 | // 设置弹窗背景颜色 37 | private int backViewColor = Color.parseColor("#bf000000"); 38 | // 弹窗背景是否覆盖全屏幕 39 | private boolean isOverScreen = true; 40 | 41 | private AnimDialogUtils(Activity context) { 42 | this.context = context; 43 | } 44 | 45 | public static AnimDialogUtils getInstance(Activity context) { 46 | return new AnimDialogUtils(context); 47 | } 48 | 49 | /** 50 | * 初始化弹窗中的界面,添加传入的customView界面,并监听关闭按钮点击事件 51 | * 52 | * @param customView 53 | * @return 54 | */ 55 | public AnimDialogUtils initView(final View customView) { 56 | if (isOverScreen) { 57 | androidContentView = (ViewGroup) context.getWindow().getDecorView(); 58 | } else { 59 | androidContentView = (ViewGroup) context.getWindow().findViewById(Window.ID_ANDROID_CONTENT); 60 | } 61 | rootView = LayoutInflater.from(context).inflate(R.layout.anim_dialog_layout, null); 62 | rootView.setTag(ANIM_DIALOG_TAG); 63 | 64 | animBackView = (RelativeLayout) rootView.findViewById(R.id.anim_back_view); 65 | animContainer = (RelativeLayout) rootView.findViewById(R.id.anim_container); 66 | animContainer.setVisibility(View.INVISIBLE); 67 | flContentContainer = (FrameLayout) rootView.findViewById(R.id.fl_content_container); 68 | ViewGroup.LayoutParams contentParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); 69 | flContentContainer.addView(customView, contentParams); 70 | ivClose = (ImageView) rootView.findViewById(R.id.iv_close); 71 | 72 | 73 | return this; 74 | } 75 | 76 | /** 77 | * 开始执行弹窗的展示动画 78 | * @param animType 79 | */ 80 | public void show(int animType, double bounciness, double speed) { 81 | // 判断是否设置背景透明 82 | if (isAnimBackViewTransparent) { 83 | backViewColor = Color.TRANSPARENT; 84 | } 85 | // 判断背景颜色 86 | animBackView.setBackgroundColor(backViewColor); 87 | 88 | // 判断弹窗是否可关闭 89 | if (isDialogCloseable) { 90 | ivClose.setVisibility(View.VISIBLE); 91 | ivClose.setOnClickListener(new View.OnClickListener() { 92 | @Override 93 | public void onClick(View view) { 94 | if (onCloseClickListener != null) { 95 | onCloseClickListener.onClick(view); 96 | } 97 | dismiss(AdConstant.ANIM_STOP_TRANSPARENT); 98 | } 99 | }); 100 | } else { 101 | ivClose.setVisibility(View.GONE); 102 | } 103 | ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); 104 | androidContentView.addView(rootView, params); 105 | AnimSpring.getInstance().startAnim(animType, animContainer, bounciness, speed); 106 | isShowing = true; 107 | } 108 | 109 | /** 110 | * 开始执行关闭动画的操作 111 | */ 112 | public void dismiss(int animType) { 113 | AnimSpring.getInstance().stopAnim(animType, this); 114 | } 115 | 116 | 117 | /** 118 | * 设置背景组件颜色 119 | * @param color 120 | * @return 121 | */ 122 | public AnimDialogUtils setDialogBackViewColor(int color) { 123 | 124 | backViewColor = color; 125 | 126 | return this; 127 | } 128 | 129 | /** 130 | * 设置弹窗关闭按钮是否可见 131 | * @param dialogCloseable 132 | * @return 133 | */ 134 | public AnimDialogUtils setDialogCloseable(boolean dialogCloseable) { 135 | isDialogCloseable = dialogCloseable; 136 | 137 | return this; 138 | } 139 | 140 | public AnimDialogUtils setOnCloseClickListener(View.OnClickListener onCloseClickListener) { 141 | this.onCloseClickListener = onCloseClickListener; 142 | 143 | return this; 144 | } 145 | 146 | /** 147 | * 设置背景是否透明 148 | * @param animBackViewTransparent 149 | * @return 150 | */ 151 | public AnimDialogUtils setAnimBackViewTransparent(boolean animBackViewTransparent) { 152 | isAnimBackViewTransparent = animBackViewTransparent; 153 | 154 | return this; 155 | } 156 | 157 | /** 158 | * 设置弹窗背景是否覆盖全屏幕 159 | * @param overScreen 160 | */ 161 | public AnimDialogUtils setOverScreen(boolean overScreen) { 162 | isOverScreen = overScreen; 163 | 164 | return this; 165 | } 166 | 167 | // ################### get方法 #################### 168 | 169 | public RelativeLayout getAnimContainer() { 170 | return animContainer; 171 | } 172 | 173 | public boolean isShowing() { 174 | return isShowing; 175 | } 176 | 177 | public ViewGroup getAndroidContentView() { 178 | return androidContentView; 179 | } 180 | 181 | public View getRootView() { 182 | return rootView; 183 | } 184 | 185 | public void setShowing(boolean showing) { 186 | isShowing = showing; 187 | } 188 | } 189 | 190 | -------------------------------------------------------------------------------- /adlibrary/src/main/java/com/uuch/adlibrary/LApplication.java: -------------------------------------------------------------------------------- 1 | package com.uuch.adlibrary; 2 | 3 | import android.app.Application; 4 | import android.util.DisplayMetrics; 5 | 6 | import com.facebook.drawee.backends.pipeline.Fresco; 7 | import com.uuch.adlibrary.utils.DisplayUtil; 8 | 9 | /** 10 | * Created by aaron on 16/8/2. 11 | * 自定义Application 12 | */ 13 | public class LApplication extends Application{ 14 | 15 | @Override 16 | public void onCreate() { 17 | super.onCreate(); 18 | 19 | initDisplayOpinion(); 20 | 21 | Fresco.initialize(this); 22 | } 23 | 24 | private void initDisplayOpinion() { 25 | DisplayMetrics dm = getResources().getDisplayMetrics(); 26 | DisplayUtil.density = dm.density; 27 | DisplayUtil.densityDPI = dm.densityDpi; 28 | DisplayUtil.screenWidthPx = dm.widthPixels; 29 | DisplayUtil.screenhightPx = dm.heightPixels; 30 | DisplayUtil.screenWidthDip = DisplayUtil.px2dip(getApplicationContext(), dm.widthPixels); 31 | DisplayUtil.screenHightDip = DisplayUtil.px2dip(getApplicationContext(), dm.heightPixels); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /adlibrary/src/main/java/com/uuch/adlibrary/anim/AnimSpring.java: -------------------------------------------------------------------------------- 1 | package com.uuch.adlibrary.anim; 2 | 3 | import android.animation.Animator; 4 | import android.animation.AnimatorListenerAdapter; 5 | import android.view.View; 6 | import android.view.animation.AccelerateInterpolator; 7 | import android.widget.RelativeLayout; 8 | 9 | import com.facebook.rebound.SimpleSpringListener; 10 | import com.facebook.rebound.Spring; 11 | import com.facebook.rebound.SpringConfig; 12 | import com.facebook.rebound.SpringSystem; 13 | import com.uuch.adlibrary.AdConstant; 14 | import com.uuch.adlibrary.AnimDialogUtils; 15 | import com.uuch.adlibrary.utils.DisplayUtil; 16 | 17 | /** 18 | * Created by aaron on 16/8/3. 19 | * 弹性动画操作类 20 | */ 21 | public class AnimSpring { 22 | 23 | public static AnimSpring animSpring = null; 24 | public static SpringSystem springSystem = null; 25 | public SpringConfig springConfig = SpringConfig.fromBouncinessAndSpeed(8, 2); 26 | 27 | public static AnimSpring getInstance() { 28 | if (springSystem == null) { 29 | springSystem = SpringSystem.create(); 30 | } 31 | if (animSpring == null) { 32 | animSpring = new AnimSpring(); 33 | } 34 | 35 | return animSpring; 36 | } 37 | 38 | 39 | // #################### 弹窗打开时的动画效果 ############################# 40 | /** 41 | * 弹窗打开时的动画效果 42 | * @param animType 43 | * @param animContainer 44 | */ 45 | public void startAnim(final int animType, final RelativeLayout animContainer, double bounciness, double speed) { 46 | springConfig = SpringConfig.fromBouncinessAndSpeed(bounciness, speed); 47 | // 常量类型动画效果 48 | if (AdConstant.isConstantAnim(animType)) { 49 | startConstantAnim(animType, animContainer); 50 | } else if (AdConstant.isCircleAnim(animType)) { 51 | startCircleAnim(animType, animContainer); 52 | } else { 53 | animContainer.setVisibility(View.VISIBLE); 54 | } 55 | } 56 | 57 | /** 58 | * 开始动画-定义动画开始角度 59 | * @param animType 60 | * @param animContainer 61 | */ 62 | public void startCircleAnim(final int animType, final RelativeLayout animContainer) { 63 | double radius = Math.sqrt(DisplayUtil.screenhightPx * DisplayUtil.screenhightPx + DisplayUtil.screenWidthPx * DisplayUtil.screenWidthPx); 64 | double heightY = - Math.sin(Math.toRadians(animType)) * radius; 65 | double widthX = Math.cos(Math.toRadians(animType)) * radius; 66 | 67 | Spring tranSpring = springSystem.createSpring(); 68 | Spring tranSpring1 = springSystem.createSpring(); 69 | tranSpring.addListener(new SimpleSpringListener() { 70 | @Override 71 | public void onSpringActivate(Spring spring) { 72 | animContainer.setVisibility(View.VISIBLE); 73 | } 74 | 75 | @Override 76 | public void onSpringUpdate(Spring spring) { 77 | animContainer.setTranslationX((float) spring.getCurrentValue()); 78 | } 79 | }); 80 | 81 | tranSpring1.addListener(new SimpleSpringListener() { 82 | @Override 83 | public void onSpringActivate(Spring spring) { 84 | animContainer.setVisibility(View.VISIBLE); 85 | } 86 | 87 | @Override 88 | public void onSpringUpdate(Spring spring) { 89 | animContainer.setTranslationY((float) spring.getCurrentValue()); 90 | } 91 | }); 92 | 93 | tranSpring.setSpringConfig(springConfig); 94 | tranSpring1.setSpringConfig(springConfig); 95 | tranSpring.setCurrentValue(widthX); 96 | tranSpring.setEndValue(0); 97 | tranSpring1.setCurrentValue(heightY); 98 | tranSpring1.setEndValue(0); 99 | } 100 | 101 | 102 | /** 103 | * 开始动画-固定类型动画 104 | */ 105 | public void startConstantAnim(final int animType, final RelativeLayout animContainer) { 106 | 107 | if (animType == AdConstant.ANIM_DOWN_TO_UP) { 108 | startCircleAnim(270, animContainer); 109 | } else if (animType == AdConstant.ANIM_UP_TO_DOWN){ 110 | startCircleAnim(90, animContainer); 111 | } else if (animType == AdConstant.ANIM_LEFT_TO_RIGHT) { 112 | startCircleAnim(180, animContainer); 113 | } else if (animType == AdConstant.ANIM_RIGHT_TO_LEFT) { 114 | startCircleAnim(0, animContainer); 115 | } else if (animType == AdConstant.ANIM_UPLEFT_TO_CENTER) { 116 | startCircleAnim(135, animContainer); 117 | } else if (animType == AdConstant.ANIM_UPRIGHT_TO_CENTER) { 118 | startCircleAnim(45, animContainer); 119 | } else if (animType == AdConstant.ANIM_DOWNLEFT_TO_CENTER) { 120 | startCircleAnim(225, animContainer); 121 | } else if (animType == AdConstant.ANIM_DOWNRIGHT_TO_CENTER) { 122 | startCircleAnim(315, animContainer); 123 | } 124 | } 125 | 126 | // ############################## 弹窗关闭时的动画效果 ################################## 127 | 128 | /** 129 | * 弹窗退出时的动画 130 | * @param animType 131 | * @param animDialogUtils 132 | */ 133 | public void stopAnim(int animType, final AnimDialogUtils animDialogUtils) { 134 | if (animDialogUtils == null) { 135 | return; 136 | } 137 | 138 | if (animType == AdConstant.ANIM_STOP_TRANSPARENT) { 139 | animDialogUtils.getAnimContainer().animate().alpha(0).setListener(new AnimatorListenerAdapter() { 140 | @Override 141 | public void onAnimationEnd(Animator animation) { 142 | animDialogUtils.getAndroidContentView().removeView(animDialogUtils.getRootView()); 143 | animDialogUtils.setShowing(false); 144 | } 145 | }).setDuration(500).setInterpolator(new AccelerateInterpolator()).start(); 146 | } else { 147 | animDialogUtils.getAndroidContentView().removeView(animDialogUtils.getRootView()); 148 | animDialogUtils.setShowing(false); 149 | } 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /adlibrary/src/main/java/com/uuch/adlibrary/bean/AdInfo.java: -------------------------------------------------------------------------------- 1 | package com.uuch.adlibrary.bean; 2 | 3 | import android.os.Parcel; 4 | import android.os.Parcelable; 5 | 6 | /** 7 | * Created by aaron on 16/8/2. 8 | * 广告弹窗实体类 9 | */ 10 | public class AdInfo implements Parcelable{ 11 | 12 | private String adId = null; 13 | private String title = null; 14 | private String url = null; 15 | private String activityImg = null; 16 | private int activityImgId = -1; 17 | 18 | public String getAdId() { 19 | return adId; 20 | } 21 | 22 | public void setAdId(String adId) { 23 | this.adId = adId; 24 | } 25 | 26 | public String getTitle() { 27 | return title; 28 | } 29 | 30 | public void setTitle(String title) { 31 | this.title = title; 32 | } 33 | 34 | public String getUrl() { 35 | return url; 36 | } 37 | 38 | public void setUrl(String url) { 39 | this.url = url; 40 | } 41 | 42 | public String getActivityImg() { 43 | return activityImg; 44 | } 45 | 46 | public void setActivityImg(String activityImg) { 47 | this.activityImg = activityImg; 48 | } 49 | 50 | public int getActivityImgId() { 51 | return activityImgId; 52 | } 53 | 54 | public void setActivityImgId(int activityImgId) { 55 | this.activityImgId = activityImgId; 56 | } 57 | 58 | 59 | @Override 60 | public int describeContents() { 61 | return 0; 62 | } 63 | 64 | @Override 65 | public void writeToParcel(Parcel dest, int flags) { 66 | dest.writeString(this.adId); 67 | dest.writeString(this.title); 68 | dest.writeString(this.url); 69 | dest.writeString(this.activityImg); 70 | dest.writeInt(this.activityImgId); 71 | } 72 | 73 | public AdInfo() { 74 | } 75 | 76 | protected AdInfo(Parcel in) { 77 | this.adId = in.readString(); 78 | this.title = in.readString(); 79 | this.url = in.readString(); 80 | this.activityImg = in.readString(); 81 | this.activityImgId = in.readInt(); 82 | } 83 | 84 | public static final Creator CREATOR = new Creator() { 85 | @Override 86 | public AdInfo createFromParcel(Parcel source) { 87 | return new AdInfo(source); 88 | } 89 | 90 | @Override 91 | public AdInfo[] newArray(int size) { 92 | return new AdInfo[size]; 93 | } 94 | }; 95 | } 96 | -------------------------------------------------------------------------------- /adlibrary/src/main/java/com/uuch/adlibrary/transformer/DepthPageTransformer.java: -------------------------------------------------------------------------------- 1 | package com.uuch.adlibrary.transformer; 2 | 3 | import com.nineoldandroids.view.ViewHelper; 4 | 5 | import android.annotation.SuppressLint; 6 | import android.support.v4.view.ViewPager; 7 | import android.view.View; 8 | 9 | public class DepthPageTransformer implements ViewPager.PageTransformer { 10 | private static final float MIN_SCALE = 0.75f; 11 | 12 | public void transformPage(View view, float position) { 13 | int pageWidth = view.getWidth(); 14 | 15 | if (position < -1) { // [-Infinity,-1) 16 | // This page is way off-screen to the left. 17 | // view.setAlpha(0); 18 | ViewHelper.setAlpha(view, 0); 19 | } else if (position <= 0)// a页滑动至b页 ; a页从 0.0 -1 ;b页从1 ~ 0.0 20 | { // [-1,0] 21 | // Use the default slide transition when moving to the left page 22 | // view.setAlpha(1); 23 | ViewHelper.setAlpha(view, 1); 24 | // view.setTranslationX(0); 25 | ViewHelper.setTranslationX(view, 0); 26 | // view.setScaleX(1); 27 | ViewHelper.setScaleX(view, 1); 28 | // view.setScaleY(1); 29 | ViewHelper.setScaleY(view, 1); 30 | 31 | } else if (position <= 1) { // (0,1] 32 | // Fade the page out. 33 | // view.setAlpha(1 - position); 34 | ViewHelper.setAlpha(view, 1 - position); 35 | 36 | // Counteract the default slide transition 37 | // view.setTranslationX(pageWidth * -position); 38 | ViewHelper.setTranslationX(view, pageWidth * -position); 39 | 40 | // Scale the page down (between MIN_SCALE and 1) 41 | float scaleFactor = MIN_SCALE + (1 - MIN_SCALE) * (1 - position); 42 | // view.setScaleX(scaleFactor); 43 | ViewHelper.setScaleX(view, scaleFactor); 44 | // view.setScaleY(1); 45 | ViewHelper.setScaleY(view, scaleFactor); 46 | 47 | } else { // (1,+Infinity] 48 | // This page is way off-screen to the right. 49 | // view.setAlpha(0); 50 | ViewHelper.setAlpha(view, 0); 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /adlibrary/src/main/java/com/uuch/adlibrary/transformer/RotateDownPageTransformer.java: -------------------------------------------------------------------------------- 1 | package com.uuch.adlibrary.transformer; 2 | 3 | import com.nineoldandroids.view.ViewHelper; 4 | 5 | import android.annotation.SuppressLint; 6 | import android.support.v4.view.ViewPager; 7 | import android.util.Log; 8 | import android.view.View; 9 | 10 | /** 11 | * http://blog.csdn.net/lmj623565791/article/details/40411921 12 | * 13 | * @author zhy 14 | */ 15 | public class RotateDownPageTransformer implements ViewPager.PageTransformer { 16 | private static final float MIN_SCALE = 0.85f; 17 | private static final float MIN_ALPHA = 0.5f; 18 | private static final float ROT_MAX = 20.0f; 19 | private float mRot; 20 | private float mTrans; 21 | 22 | @SuppressLint("NewApi") 23 | public void transformPage(View view, float position) { 24 | 25 | Log.e("TAG", view + " , " + position + ""); 26 | 27 | if (position < -1) { // [-Infinity,-1) 28 | // This page is way off-screen to the left. 29 | ViewHelper.setRotation(view, 0); 30 | 31 | } else if (position <= 1) // a页滑动至b页 ; a页从 0.0 ~ -1 ;b页从1 ~ 0.0 32 | { // [-1,1] 33 | // Modify the default slide transition to shrink the page as well 34 | if (position < 0) { 35 | 36 | mRot = (ROT_MAX * position); 37 | ViewHelper.setPivotX(view, view.getMeasuredWidth() * 0.5f); 38 | ViewHelper.setPivotY(view, view.getMeasuredHeight()); 39 | ViewHelper.setRotation(view, mRot); 40 | } else { 41 | 42 | mRot = (ROT_MAX * position); 43 | ViewHelper.setPivotX(view, view.getMeasuredWidth() * 0.5f); 44 | ViewHelper.setPivotY(view, view.getMeasuredHeight()); 45 | ViewHelper.setRotation(view, mRot); 46 | } 47 | 48 | // Scale the page down (between MIN_SCALE and 1) 49 | 50 | // Fade the page relative to its size. 51 | 52 | } else { // (1,+Infinity] 53 | // This page is way off-screen to the right. 54 | ViewHelper.setRotation(view, 0); 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /adlibrary/src/main/java/com/uuch/adlibrary/transformer/ZoomOutPageTransformer.java: -------------------------------------------------------------------------------- 1 | package com.uuch.adlibrary.transformer; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.support.v4.view.ViewPager; 5 | import android.util.Log; 6 | import android.view.View; 7 | 8 | public class ZoomOutPageTransformer implements ViewPager.PageTransformer { 9 | private static final float MIN_SCALE = 0.85f; 10 | private static final float MIN_ALPHA = 0.5f; 11 | 12 | @SuppressLint("NewApi") 13 | public void transformPage(View view, float position) { 14 | int pageWidth = view.getWidth(); 15 | int pageHeight = view.getHeight(); 16 | 17 | Log.e("TAG", view + " , " + position + ""); 18 | 19 | if (position < -1) { // [-Infinity,-1) 20 | // This page is way off-screen to the left. 21 | view.setAlpha(0); 22 | 23 | } else if (position <= 1) //a页滑动至b页 ; a页从 0.0 -1 ;b页从1 ~ 0.0 24 | { // [-1,1] 25 | // Modify the default slide transition to shrink the page as well 26 | float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position)); 27 | float vertMargin = pageHeight * (1 - scaleFactor) / 2; 28 | float horzMargin = pageWidth * (1 - scaleFactor) / 2; 29 | if (position < 0) { 30 | view.setTranslationX(horzMargin - vertMargin / 2); 31 | } else { 32 | view.setTranslationX(-horzMargin + vertMargin / 2); 33 | } 34 | 35 | // Scale the page down (between MIN_SCALE and 1) 36 | view.setScaleX(scaleFactor); 37 | view.setScaleY(scaleFactor); 38 | 39 | // Fade the page relative to its size. 40 | view.setAlpha(MIN_ALPHA + (scaleFactor - MIN_SCALE) 41 | / (1 - MIN_SCALE) * (1 - MIN_ALPHA)); 42 | 43 | } else { // (1,+Infinity] 44 | // This page is way off-screen to the right. 45 | view.setAlpha(0); 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /adlibrary/src/main/java/com/uuch/adlibrary/utils/DisplayUtil.java: -------------------------------------------------------------------------------- 1 | package com.uuch.adlibrary.utils; 2 | 3 | import android.content.Context; 4 | 5 | /** 6 | * Created by aaron on 16/8/3. 7 | */ 8 | public class DisplayUtil 9 | { 10 | 11 | public static int screenWidthPx; //屏幕宽 px 12 | public static int screenhightPx; //屏幕高 px 13 | public static float density;//屏幕密度 14 | public static int densityDPI;//屏幕密度 15 | public static float screenWidthDip;// dp单位 16 | public static float screenHightDip;// dp单位 17 | 18 | 19 | 20 | /** 21 | * 根据手机的分辨率从 dp 的单位 转成为 px(像素) 22 | */ 23 | public static int dip2px(Context context, float dpValue) { 24 | final float scale = context.getResources().getDisplayMetrics().density; 25 | return (int) (dpValue * scale + 0.5f); 26 | } 27 | 28 | /** 29 | * 根据手机的分辨率从 px(像素) 的单位 转成为 dp 30 | */ 31 | public static int px2dip(Context context, float pxValue) { 32 | final float scale = context.getResources().getDisplayMetrics().density; 33 | return (int) (pxValue / scale + 0.5f); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /adlibrary/src/main/java/com/uuch/adlibrary/view/MetaballView.java: -------------------------------------------------------------------------------- 1 | package com.uuch.adlibrary.view; 2 | 3 | import android.content.Context; 4 | import android.graphics.Canvas; 5 | import android.graphics.Paint; 6 | import android.graphics.Path; 7 | import android.graphics.RectF; 8 | import android.util.AttributeSet; 9 | import android.view.View; 10 | import android.view.animation.AccelerateDecelerateInterpolator; 11 | import android.view.animation.Animation; 12 | import android.view.animation.Transformation; 13 | 14 | 15 | import com.uuch.adlibrary.utils.DisplayUtil; 16 | 17 | import java.util.ArrayList; 18 | 19 | /** 20 | * 加载进度View 21 | */ 22 | public class MetaballView extends View { 23 | 24 | private Paint paint = new Paint(); 25 | private float handle_len_rate = 2f; 26 | private float radius = 20; 27 | private final int ITEM_COUNT = 5; 28 | private final int ITEM_DIVIDER = 30; 29 | private final float SCALE_RATE = 0.3f; 30 | private float maxLength; 31 | private ArrayList circlePaths = new ArrayList<>(); 32 | private float mInterpolatedTime; 33 | private MoveAnimation wa; 34 | private Circle circle; 35 | 36 | public MetaballView(Context context) { 37 | super(context); 38 | init(); 39 | } 40 | 41 | public MetaballView(Context context, AttributeSet attrs) { 42 | super(context, attrs); 43 | init(); 44 | } 45 | 46 | public MetaballView(Context context, AttributeSet attrs, int defStyleAttr) { 47 | super(context, attrs, defStyleAttr); 48 | init(); 49 | 50 | } 51 | 52 | private class Circle { 53 | float[] center; 54 | float radius; 55 | } 56 | 57 | public void setPaintMode(int mode) { 58 | paint.setStyle(mode == 0 ? Paint.Style.STROKE : Paint.Style.FILL); 59 | invalidate(); 60 | } 61 | 62 | private void init() { 63 | radius = DisplayUtil.dip2px(getContext(), 8); 64 | paint.setColor(0xff4db9ff); 65 | paint.setStyle(Paint.Style.FILL); 66 | paint.setAntiAlias(true); 67 | Circle circlePath = new Circle(); 68 | circlePath.center = new float[]{(radius + ITEM_DIVIDER), radius * (1f + SCALE_RATE)}; 69 | circlePath.radius = radius / 4 * 3; 70 | circlePaths.add(circlePath); 71 | 72 | for (int i = 1; i < ITEM_COUNT; i++) { 73 | circlePath = new Circle(); 74 | circlePath.center = new float[]{(radius * 2 + ITEM_DIVIDER) * i + getPaddingLeft(), radius * (1f + SCALE_RATE)}; 75 | circlePath.radius = radius; 76 | circlePaths.add(circlePath); 77 | } 78 | maxLength = (radius * 2 + ITEM_DIVIDER) * ITEM_COUNT; 79 | } 80 | 81 | private float[] getVector(float radians, float length) { 82 | float x = (float) (Math.cos(radians) * length); 83 | float y = (float) (Math.sin(radians) * length); 84 | return new float[]{ 85 | x, y 86 | }; 87 | } 88 | 89 | private class MoveAnimation extends Animation { 90 | 91 | @Override 92 | protected void applyTransformation(float interpolatedTime, Transformation t) { 93 | super.applyTransformation(interpolatedTime, t); 94 | mInterpolatedTime = interpolatedTime; 95 | invalidate(); 96 | } 97 | } 98 | 99 | /** 100 | * @param canvas 画布 101 | * @param j 102 | * @param i 103 | * @param v 控制两个圆连接时候长度,间接控制连接线的粗细,该值为1的时候连接线为直线 104 | * @param handle_len_rate 105 | * @param maxDistance 106 | */ 107 | private void metaball(Canvas canvas, int j, int i, float v, float handle_len_rate, float maxDistance) { 108 | final Circle circle1 = circlePaths.get(i); 109 | final Circle circle2 = circlePaths.get(j); 110 | 111 | RectF ball1 = new RectF(); 112 | ball1.left = circle1.center[0] - circle1.radius + getPaddingLeft(); 113 | ball1.top = circle1.center[1] - circle1.radius; 114 | ball1.right = ball1.left + circle1.radius * 2; 115 | ball1.bottom = ball1.top + circle1.radius * 2; 116 | 117 | RectF ball2 = new RectF(); 118 | ball2.left = circle2.center[0] - circle2.radius; 119 | ball2.top = circle2.center[1] - circle2.radius; 120 | ball2.right = ball2.left + circle2.radius * 2; 121 | ball2.bottom = ball2.top + circle2.radius * 2; 122 | 123 | float[] center1 = new float[]{ 124 | ball1.centerX(), 125 | ball1.centerY() 126 | }; 127 | float[] center2 = new float[]{ 128 | ball2.centerX(), 129 | ball2.centerY() 130 | }; 131 | float d = getDistance(center1, center2); 132 | 133 | float radius1 = ball1.width() / 2; 134 | float radius2 = ball2.width() / 2; 135 | float pi2 = (float) (Math.PI / 2); 136 | float u1, u2; 137 | 138 | 139 | if (d > maxDistance) { 140 | // canvas.drawCircle(ball1.centerX(), ball1.centerY(), circle1.radius, paint); 141 | canvas.drawCircle(ball2.centerX(), ball2.centerY(), circle2.radius, paint); 142 | } else { 143 | float scale2 = 1 + SCALE_RATE * (1 - d / maxDistance); 144 | float scale1 = 1 - SCALE_RATE * (1 - d / maxDistance); 145 | radius2 *= scale2; 146 | // radius1 *= scale1; 147 | // canvas.drawCircle(ball1.centerX(), ball1.centerY(), radius1, paint); 148 | canvas.drawCircle(ball2.centerX(), ball2.centerY(), radius2, paint); 149 | 150 | } 151 | 152 | // Log.d("Metaball_radius", "radius1:" + radius1 + ",radius2:" + radius2); 153 | if (radius1 == 0 || radius2 == 0) { 154 | return; 155 | } 156 | 157 | if (d > maxDistance || d <= Math.abs(radius1 - radius2)) { 158 | return; 159 | } else if (d < radius1 + radius2) { 160 | u1 = (float) Math.acos((radius1 * radius1 + d * d - radius2 * radius2) / 161 | (2 * radius1 * d)); 162 | u2 = (float) Math.acos((radius2 * radius2 + d * d - radius1 * radius1) / 163 | (2 * radius2 * d)); 164 | } else { 165 | u1 = 0; 166 | u2 = 0; 167 | } 168 | // Log.d("Metaball", "center2:" + Arrays.toString(center2) + ",center1:" + Arrays.toString(center1)); 169 | float[] centermin = new float[]{center2[0] - center1[0], center2[1] - center1[1]}; 170 | 171 | float angle1 = (float) Math.atan2(centermin[1], centermin[0]); 172 | float angle2 = (float) Math.acos((radius1 - radius2) / d); 173 | float angle1a = angle1 + u1 + (angle2 - u1) * v; 174 | float angle1b = angle1 - u1 - (angle2 - u1) * v; 175 | float angle2a = (float) (angle1 + Math.PI - u2 - (Math.PI - u2 - angle2) * v); 176 | float angle2b = (float) (angle1 - Math.PI + u2 + (Math.PI - u2 - angle2) * v); 177 | 178 | // Log.d("Metaball", "angle1:" + angle1 + ",angle2:" + angle2 + ",angle1a:" + angle1a + ",angle1b:" + angle1b + ",angle2a:" + angle2a + ",angle2b:" + angle2b); 179 | 180 | 181 | float[] p1a1 = getVector(angle1a, radius1); 182 | float[] p1b1 = getVector(angle1b, radius1); 183 | float[] p2a1 = getVector(angle2a, radius2); 184 | float[] p2b1 = getVector(angle2b, radius2); 185 | 186 | float[] p1a = new float[]{p1a1[0] + center1[0], p1a1[1] + center1[1]}; 187 | float[] p1b = new float[]{p1b1[0] + center1[0], p1b1[1] + center1[1]}; 188 | float[] p2a = new float[]{p2a1[0] + center2[0], p2a1[1] + center2[1]}; 189 | float[] p2b = new float[]{p2b1[0] + center2[0], p2b1[1] + center2[1]}; 190 | 191 | 192 | // Log.d("Metaball", "p1a:" + Arrays.toString(p1a) + ",p1b:" + Arrays.toString(p1b) + ",p2a:" + Arrays.toString(p2a) + ",p2b:" + Arrays.toString(p2b)); 193 | 194 | float[] p1_p2 = new float[]{p1a[0] - p2a[0], p1a[1] - p2a[1]}; 195 | 196 | float totalRadius = (radius1 + radius2); 197 | float d2 = Math.min(v * handle_len_rate, getLength(p1_p2) / totalRadius); 198 | d2 *= Math.min(1, d * 2 / (radius1 + radius2)); 199 | // Log.d("Metaball", "d2:" + d2); 200 | radius1 *= d2; 201 | radius2 *= d2; 202 | 203 | float[] sp1 = getVector(angle1a - pi2, radius1); 204 | float[] sp2 = getVector(angle2a + pi2, radius2); 205 | float[] sp3 = getVector(angle2b - pi2, radius2); 206 | float[] sp4 = getVector(angle1b + pi2, radius1); 207 | // Log.d("Metaball", "sp1:" + Arrays.toString(sp1) + ",sp2:" + Arrays.toString(sp2) + ",sp3:" + Arrays.toString(sp3) + ",sp4:" + Arrays.toString(sp4)); 208 | 209 | 210 | Path path1 = new Path(); 211 | path1.moveTo(p1a[0], p1a[1]); 212 | path1.cubicTo(p1a[0] + sp1[0], p1a[1] + sp1[1], p2a[0] + sp2[0], p2a[1] + sp2[1], p2a[0], p2a[1]); 213 | path1.lineTo(p2b[0], p2b[1]); 214 | path1.cubicTo(p2b[0] + sp3[0], p2b[1] + sp3[1], p1b[0] + sp4[0], p1b[1] + sp4[1], p1b[0], p1b[1]); 215 | path1.lineTo(p1a[0], p1a[1]); 216 | path1.close(); 217 | canvas.drawPath(path1, paint); 218 | 219 | } 220 | 221 | private float getLength(float[] b) { 222 | return (float) Math.sqrt(b[0] * b[0] + b[1] * b[1]); 223 | } 224 | 225 | private float getDistance(float[] b1, float[] b2) { 226 | float x = b1[0] - b2[0]; 227 | float y = b1[1] - b2[1]; 228 | float d = x * x + y * y; 229 | return (float) Math.sqrt(d); 230 | } 231 | 232 | 233 | //测试用 234 | // @Override 235 | // public boolean onTouchEvent(MotionEvent event) { 236 | // switch (event.getAction()) { 237 | // case MotionEvent.ACTION_DOWN: 238 | // break; 239 | // case MotionEvent.ACTION_MOVE: 240 | // Circle circle = circlePaths.get(0); 241 | // circle.center[0] = event.getX(); 242 | // circle.center[1] = event.getY(); 243 | // invalidate(); 244 | // break; 245 | // case MotionEvent.ACTION_UP: 246 | // break; 247 | // } 248 | // 249 | // return true; 250 | // } 251 | 252 | @Override 253 | protected void onDraw(Canvas canvas) { 254 | super.onDraw(canvas); 255 | circle = circlePaths.get(0); 256 | circle.center[0] = maxLength * mInterpolatedTime; 257 | 258 | RectF ball1 = new RectF(); 259 | ball1.left = circle.center[0] - circle.radius + getPaddingLeft(); 260 | ball1.top = circle.center[1] - circle.radius; 261 | ball1.right = ball1.left + circle.radius * 2; 262 | ball1.bottom = ball1.top + circle.radius * 2; 263 | canvas.drawCircle(ball1.centerX(), ball1.centerY(), circle.radius, paint); 264 | 265 | 266 | for (int i = 1, l = circlePaths.size(); i < l; i++) { 267 | metaball(canvas, i, 0, 0.6f, handle_len_rate, radius * 4f); 268 | } 269 | } 270 | 271 | @Override 272 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 273 | setMeasuredDimension(resolveSizeAndState((int) (ITEM_COUNT * (radius * 2 + ITEM_DIVIDER)) + getPaddingLeft() + getPaddingRight(), widthMeasureSpec, 0), 274 | resolveSizeAndState((int) (2 * radius * 1.4f), heightMeasureSpec, 0)); 275 | } 276 | 277 | 278 | private void stopAnimation() { 279 | this.clearAnimation(); 280 | postInvalidate(); 281 | } 282 | 283 | private void startAnimation() { 284 | wa = new MoveAnimation(); 285 | wa.setDuration(2500); 286 | wa.setInterpolator(new AccelerateDecelerateInterpolator()); 287 | wa.setRepeatCount(Animation.INFINITE); 288 | wa.setRepeatMode(Animation.REVERSE); 289 | startAnimation(wa); 290 | } 291 | 292 | @Override 293 | protected void onVisibilityChanged(View changedView, int visibility) { 294 | super.onVisibilityChanged(changedView, visibility); 295 | 296 | if (visibility == GONE || visibility == INVISIBLE) { 297 | stopAnimation(); 298 | } else { 299 | startAnimation(); 300 | } 301 | } 302 | 303 | @Override 304 | protected void onAttachedToWindow() { 305 | super.onAttachedToWindow(); 306 | startAnimation(); 307 | } 308 | 309 | @Override 310 | protected void onDetachedFromWindow() { 311 | stopAnimation(); 312 | super.onDetachedFromWindow(); 313 | } 314 | } 315 | -------------------------------------------------------------------------------- /adlibrary/src/main/java/com/uuch/adlibrary/view/ProgressLayout.java: -------------------------------------------------------------------------------- 1 | package com.uuch.adlibrary.view; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.content.res.TypedArray; 6 | import android.graphics.Color; 7 | import android.graphics.drawable.Drawable; 8 | import android.text.TextUtils; 9 | import android.util.AttributeSet; 10 | import android.view.GestureDetector; 11 | import android.view.LayoutInflater; 12 | import android.view.MotionEvent; 13 | import android.view.VelocityTracker; 14 | import android.view.View; 15 | import android.view.ViewGroup; 16 | import android.widget.Button; 17 | import android.widget.ImageView; 18 | import android.widget.RelativeLayout; 19 | import android.widget.TextView; 20 | 21 | import com.malinskiy.materialicons.IconDrawable; 22 | import com.malinskiy.materialicons.Iconify; 23 | import com.uuch.adlibrary.R; 24 | 25 | /** 26 | * 显示加载中、无数据、无网络时的公用界面 27 | */ 28 | public class ProgressLayout extends RelativeLayout { 29 | 30 | private static final String tag = "ProgressLayout"; 31 | 32 | LayoutInflater inflater; 33 | View view; 34 | LayoutParams layoutParams; 35 | 36 | RelativeLayout loadingStateRelativeLayout; 37 | MetaballView loadingStateProgressBar; 38 | 39 | RelativeLayout emptyStateRelativeLayout; 40 | ImageView emptyStateImageView; 41 | 42 | RelativeLayout errorStateRelativeLayout; 43 | ImageView errorStateImageView; 44 | Button errorStateButton; 45 | 46 | int loadingStateBackgroundColor; 47 | 48 | int emptyStateBackgroundColor; 49 | 50 | int errorStateBackgroundColor; 51 | 52 | private State state = State.CONTENT; 53 | /** 54 | * 各种状态下的布局使用圆角的资源ID 55 | */ 56 | private int cornerResId = -1; 57 | /** 58 | * 是否使用滑动返回 59 | */ 60 | private boolean isUseSlideBack = false; 61 | /** 62 | * 滑动返回依附的Activity,finish()该Activity 63 | */ 64 | private Activity attachActivity; 65 | 66 | private GestureDetector gestureDetector; 67 | 68 | private VelocityTracker mVelocityTracker; 69 | 70 | public ProgressLayout(Context context) { 71 | super(context); 72 | } 73 | 74 | public ProgressLayout(Context context, AttributeSet attrs) { 75 | this(context, attrs, 0); 76 | } 77 | 78 | public ProgressLayout(Context context, AttributeSet attrs, int defStyle) { 79 | super(context, attrs, defStyle); 80 | init(attrs); 81 | } 82 | 83 | private void init(AttributeSet attrs) { 84 | inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); 85 | 86 | TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.ProgressLayout); 87 | 88 | loadingStateBackgroundColor = 89 | typedArray.getColor(R.styleable.ProgressLayout_progressLoadingStateBackgroundColor, Color.TRANSPARENT); 90 | 91 | emptyStateBackgroundColor = 92 | typedArray.getColor(R.styleable.ProgressLayout_progressEmptyStateBackgroundColor, Color.TRANSPARENT); 93 | 94 | errorStateBackgroundColor = 95 | typedArray.getColor(R.styleable.ProgressLayout_progressErrorStateBackgroundColor, Color.TRANSPARENT); 96 | 97 | typedArray.recycle(); 98 | } 99 | 100 | public void setAttachActivity(Activity activity) { 101 | this.attachActivity = activity; 102 | } 103 | 104 | public void setUseSlideBack(boolean useSlideBack) { 105 | isUseSlideBack = useSlideBack; 106 | if (isUseSlideBack) { 107 | gestureDetector = new GestureDetector(getContext(), onGestureListener); 108 | mVelocityTracker = VelocityTracker.obtain(); 109 | } 110 | } 111 | 112 | public void showContent() { 113 | switchState(State.CONTENT, null); 114 | } 115 | 116 | public void showLoading() { 117 | switchState(State.LOADING, null); 118 | } 119 | 120 | String loadingText; 121 | 122 | public void showLoading(String loadText) { 123 | loadingText = loadText; 124 | switchState(State.LOADING_TEXT, null); 125 | } 126 | 127 | 128 | public void showEmpty() { 129 | switchState(State.EMPTY, null); 130 | } 131 | 132 | 133 | public void showError(OnClickListener onClickListener) { 134 | switchState(State.ERROR, onClickListener); 135 | } 136 | 137 | public void showError(OnClickListener onClickListener, String errorMessage, String button) { 138 | this.errorMessage = errorMessage; 139 | this.errorButton = button; 140 | switchState(State.ERROR_SMALL, onClickListener); 141 | } 142 | public void showErrorSmall(OnClickListener onClickListener) { 143 | switchState(State.ERROR_SMALL, onClickListener); 144 | } 145 | 146 | 147 | String errorMessage, errorButton; 148 | 149 | public void showErrorSmall(OnClickListener onClickListener, String errorMessage, String button) { 150 | this.errorMessage = errorMessage; 151 | this.errorButton = button; 152 | switchState(State.ERROR_SMALL, onClickListener); 153 | } 154 | 155 | /** 156 | * Get which state is set 157 | * 158 | * @return State 159 | */ 160 | public State getState() { 161 | return state; 162 | } 163 | 164 | /** 165 | * Check if content is shown 166 | * 167 | * @return boolean 168 | */ 169 | public boolean isContent() { 170 | return state == State.CONTENT; 171 | } 172 | 173 | /** 174 | * Check if loading state is shown 175 | * 176 | * @return boolean 177 | */ 178 | public boolean isLoading() { 179 | return state == State.LOADING; 180 | } 181 | 182 | /** 183 | * Check if empty state is shown 184 | * 185 | * @return boolean 186 | */ 187 | public boolean isEmpty() { 188 | return state == State.EMPTY; 189 | } 190 | 191 | /** 192 | * Check if error state is shown 193 | * 194 | * @return boolean 195 | */ 196 | public boolean isError() { 197 | return state == State.ERROR; 198 | } 199 | 200 | private void switchState(State state, OnClickListener onClickListener) { 201 | this.state = state; 202 | 203 | switch (state) { 204 | case CONTENT: 205 | hideLoadingView(); 206 | hideEmptyView(); 207 | hideErrorView(); 208 | 209 | break; 210 | case LOADING: 211 | hideEmptyView(); 212 | hideErrorView(); 213 | setLoadingView(); 214 | break; 215 | case LOADING_TEXT: 216 | 217 | hideEmptyView(); 218 | hideErrorView(); 219 | setLoadingView(loadingText); 220 | break; 221 | case EMPTY: 222 | hideLoadingView(); 223 | hideErrorView(); 224 | 225 | setEmptyView(); 226 | 227 | break; 228 | case ERROR: 229 | hideLoadingView(); 230 | hideEmptyView(); 231 | 232 | setErrorView(onClickListener); 233 | 234 | break; 235 | case ERROR_SMALL: 236 | hideLoadingView(); 237 | hideEmptyView(); 238 | 239 | setErrorView4SmallLayout(onClickListener); 240 | break; 241 | 242 | } 243 | } 244 | 245 | private void setLoadingView() { 246 | if (loadingStateRelativeLayout == null) { 247 | view = inflater.inflate(R.layout.progress_loading_view, null); 248 | loadingStateRelativeLayout = (RelativeLayout) view.findViewById(R.id.loadingStateRelativeLayout); 249 | 250 | loadingStateProgressBar = (MetaballView) view.findViewById(R.id.loadingStateProgressBar); 251 | 252 | layoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 253 | ViewGroup.LayoutParams.MATCH_PARENT); 254 | // layoutParams.addRule(CENTER_IN_PARENT); 255 | 256 | if (cornerResId != -1) { 257 | loadingStateRelativeLayout.setBackgroundResource(cornerResId); 258 | } 259 | addView(loadingStateRelativeLayout, layoutParams); 260 | } else { 261 | loadingStateRelativeLayout.setVisibility(VISIBLE); 262 | } 263 | } 264 | 265 | private void setLoadingView(String loadtext) { 266 | if (loadingStateRelativeLayout == null) { 267 | view = inflater.inflate(R.layout.progress_loading_view, null); 268 | loadingStateRelativeLayout = (RelativeLayout) view.findViewById(R.id.loadingStateRelativeLayout); 269 | 270 | loadingStateProgressBar = (MetaballView) view.findViewById(R.id.loadingStateProgressBar); 271 | TextView text = (TextView) view.findViewById(R.id.loading_text); 272 | text.setText(loadtext); 273 | layoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 274 | ViewGroup.LayoutParams.MATCH_PARENT); 275 | // layoutParams.addRule(CENTER_IN_PARENT); 276 | 277 | if (cornerResId != -1) { 278 | loadingStateRelativeLayout.setBackgroundResource(cornerResId); 279 | } 280 | 281 | addView(loadingStateRelativeLayout, layoutParams); 282 | } else { 283 | loadingStateRelativeLayout.setVisibility(VISIBLE); 284 | } 285 | } 286 | 287 | private void setEmptyView() { 288 | if (emptyStateRelativeLayout == null) { 289 | ViewGroup contentContainer = (ViewGroup) findViewById(R.id.fl_content_container); 290 | 291 | view = inflater.inflate(R.layout.progress_empty_view, null); 292 | emptyStateRelativeLayout = (RelativeLayout) view.findViewById(R.id.emptyStateRelativeLayout); 293 | emptyStateImageView = (ImageView) view.findViewById(R.id.emptyStateImageView); 294 | 295 | Drawable emptyDrawable = new IconDrawable(getContext(), Iconify.IconValue.zmdi_shopping_basket) 296 | .colorRes(android.R.color.white); 297 | 298 | emptyStateImageView.setImageDrawable(emptyDrawable); 299 | 300 | //Set background color if not TRANSPARENT 301 | if (emptyStateBackgroundColor != Color.TRANSPARENT) { 302 | emptyStateRelativeLayout.setBackgroundColor(emptyStateBackgroundColor); 303 | } 304 | 305 | layoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 306 | ViewGroup.LayoutParams.MATCH_PARENT); 307 | layoutParams.addRule(CENTER_IN_PARENT); 308 | 309 | if (cornerResId != -1) { 310 | emptyStateRelativeLayout.setBackgroundResource(cornerResId); 311 | } 312 | 313 | contentContainer.addView(emptyStateRelativeLayout, layoutParams); 314 | } else { 315 | emptyStateRelativeLayout.setVisibility(VISIBLE); 316 | } 317 | } 318 | 319 | /** 320 | * custom 定制化展示 321 | * 设置空数据展示页面 322 | */ 323 | public void setEmptyView(String showText) { 324 | ViewGroup contentContainer = (ViewGroup) findViewById(R.id.fl_content_container); 325 | this.state = State.EMPTY; 326 | hideLoadingView(); 327 | hideErrorView(); 328 | view = inflater.inflate(R.layout.progress_empty_custom_view, null); 329 | emptyStateRelativeLayout = (RelativeLayout) view.findViewById(R.id.emptyStateRelativeLayout); 330 | TextView textView = (TextView) view.findViewById(R.id.empty_textview); 331 | if (!TextUtils.isEmpty(showText)) { 332 | textView.setText(showText); 333 | } 334 | 335 | layoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 336 | ViewGroup.LayoutParams.MATCH_PARENT); 337 | layoutParams.addRule(CENTER_IN_PARENT); 338 | 339 | if (cornerResId != -1) { 340 | emptyStateRelativeLayout.setBackgroundResource(cornerResId); 341 | } 342 | 343 | contentContainer.addView(view, layoutParams); 344 | } 345 | 346 | private View emptyView; 347 | 348 | /** 349 | * custom 定制化展示 350 | * 设置空数据展示页面 351 | */ 352 | public void setEmptyView(View view) { 353 | if (emptyView == null) { 354 | ViewGroup contentContainer = (ViewGroup) findViewById(R.id.fl_content_container); 355 | this.state = State.EMPTY; 356 | hideLoadingView(); 357 | hideErrorView(); 358 | layoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 359 | ViewGroup.LayoutParams.MATCH_PARENT); 360 | layoutParams.addRule(CENTER_IN_PARENT); 361 | 362 | emptyView = view; 363 | contentContainer.addView(emptyView, layoutParams); 364 | } else { 365 | emptyView.setVisibility(VISIBLE); 366 | } 367 | } 368 | 369 | private void setErrorView(OnClickListener onClickListener) { 370 | if (errorStateRelativeLayout == null) { 371 | ViewGroup contentContainer = (ViewGroup) findViewById(R.id.fl_content_container); 372 | view = inflater.inflate(R.layout.progress_error_view, null); 373 | errorStateRelativeLayout = (RelativeLayout) view.findViewById(R.id.errorStateRelativeLayout); 374 | 375 | errorStateImageView = (ImageView) view.findViewById(R.id.errorStateImageView); 376 | errorStateButton = (Button) view.findViewById(R.id.errorStateButton); 377 | 378 | Drawable errorDrawable = new IconDrawable(getContext(), Iconify.IconValue.zmdi_wifi_off) 379 | .colorRes(R.color.mc); 380 | 381 | errorStateImageView.setImageDrawable(errorDrawable); 382 | 383 | if (onClickListener != null) { 384 | errorStateButton.setOnClickListener(onClickListener); 385 | } 386 | 387 | layoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 388 | ViewGroup.LayoutParams.MATCH_PARENT); 389 | layoutParams.addRule(CENTER_IN_PARENT); 390 | 391 | if (cornerResId != -1) { 392 | errorStateRelativeLayout.setBackgroundResource(cornerResId); 393 | } 394 | 395 | contentContainer.addView(errorStateRelativeLayout, layoutParams); 396 | } else { 397 | errorStateRelativeLayout.setVisibility(VISIBLE); 398 | } 399 | } 400 | 401 | private void setErrorView4SmallLayout(OnClickListener onClickListener) { 402 | if (errorStateRelativeLayout == null) { 403 | ViewGroup contentContainer = (ViewGroup) findViewById(R.id.fl_content_container); 404 | view = inflater.inflate(R.layout.progress_error_view_small, null); 405 | errorStateRelativeLayout = (RelativeLayout) view.findViewById(R.id.errorStateRelativeLayout); 406 | TextView errorStateContentTextView = (TextView) view.findViewById(R.id.errorStateContentTextView); 407 | errorStateImageView = (ImageView) view.findViewById(R.id.errorStateImageView); 408 | errorStateButton = (Button) view.findViewById(R.id.errorStateButton); 409 | 410 | if (errorButton != null) { 411 | errorStateButton.setText(errorButton); 412 | } 413 | if (errorMessage != null) { 414 | errorStateContentTextView.setText(errorMessage); 415 | } 416 | Drawable errorDrawable = new IconDrawable(getContext(), Iconify.IconValue.zmdi_wifi_off) 417 | .colorRes(R.color.mc); 418 | 419 | errorStateImageView.setImageDrawable(errorDrawable); 420 | 421 | if (onClickListener != null) { 422 | errorStateButton.setOnClickListener(onClickListener); 423 | } 424 | 425 | layoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 426 | ViewGroup.LayoutParams.MATCH_PARENT); 427 | layoutParams.addRule(CENTER_IN_PARENT); 428 | 429 | if (cornerResId != -1) { 430 | errorStateRelativeLayout.setBackgroundResource(cornerResId); 431 | } 432 | 433 | contentContainer.addView(errorStateRelativeLayout, layoutParams); 434 | } else { 435 | errorStateRelativeLayout.setVisibility(VISIBLE); 436 | } 437 | } 438 | 439 | 440 | private void hideLoadingView() { 441 | if (loadingStateRelativeLayout != null) { 442 | loadingStateRelativeLayout.setVisibility(GONE); 443 | } 444 | } 445 | 446 | private void hideEmptyView() { 447 | if (emptyStateRelativeLayout != null) { 448 | emptyStateRelativeLayout.setVisibility(GONE); 449 | } 450 | } 451 | 452 | private void hideErrorView() { 453 | if (errorStateRelativeLayout != null) { 454 | errorStateRelativeLayout.setVisibility(GONE); 455 | } 456 | } 457 | 458 | public static enum State { 459 | CONTENT, LOADING, EMPTY, ERROR, ERROR_SMALL, LOADING_TEXT 460 | } 461 | 462 | public void setCornerResId(int cornerResId) { 463 | this.cornerResId = cornerResId; 464 | } 465 | 466 | 467 | private int mStartX, mStartY; 468 | 469 | @Override 470 | public boolean onInterceptTouchEvent(MotionEvent ev) { 471 | boolean isIntercept = false; 472 | if (isUseSlideBack) { 473 | int x = (int) ev.getX(); 474 | int y = (int) ev.getY(); 475 | 476 | mVelocityTracker.addMovement(ev); 477 | 478 | switch (ev.getAction()) { 479 | case MotionEvent.ACTION_DOWN: 480 | isIntercept = false; 481 | break; 482 | case MotionEvent.ACTION_MOVE: 483 | int distanceX = x - mStartX; 484 | int distanceY = y - mStartY; 485 | mVelocityTracker.computeCurrentVelocity(1000); 486 | float xVelocity = mVelocityTracker.getXVelocity(); 487 | // Log.i(tag, "xVelocity:" + xVelocity); 488 | if (distanceX > 0 && Math.abs(distanceX) > Math.abs(distanceY) && Math.abs(xVelocity) >= 1000) { 489 | isIntercept = true; 490 | } else { 491 | isIntercept = false; 492 | } 493 | break; 494 | case MotionEvent.ACTION_UP: 495 | isIntercept = false; 496 | break; 497 | } 498 | // Log.i(tag, "isIntercept:" + isIntercept); 499 | mStartX = x; 500 | mStartY = y; 501 | } 502 | 503 | return isIntercept; 504 | } 505 | 506 | @Override 507 | protected void onDetachedFromWindow() { 508 | if (mVelocityTracker != null) { 509 | mVelocityTracker.clear(); 510 | } 511 | super.onDetachedFromWindow(); 512 | } 513 | 514 | @Override 515 | public boolean onTouchEvent(MotionEvent event) { 516 | if (gestureDetector != null) { 517 | return gestureDetector.onTouchEvent(event); 518 | } 519 | return false; 520 | } 521 | 522 | GestureDetector.OnGestureListener onGestureListener = new GestureDetector.SimpleOnGestureListener() { 523 | 524 | @Override 525 | public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { 526 | // Log.i(tag, "velocityX:" + velocityX + "\t velocityY:" + velocityY); 527 | if (velocityX > 1000 && Math.abs(velocityY) < 800) { 528 | if (attachActivity != null) { 529 | attachActivity.onBackPressed(); 530 | } 531 | return true; 532 | } 533 | return false; 534 | } 535 | }; 536 | } -------------------------------------------------------------------------------- /adlibrary/src/main/res/drawable/image_disable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yipianfengye/android-adDialog/02ff5d56946ecf7b34011c712ebf43b4dabe664a/adlibrary/src/main/res/drawable/image_disable.png -------------------------------------------------------------------------------- /adlibrary/src/main/res/layout/ad_dialog_content_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 13 | 14 | 23 | 24 | 37 | 38 | -------------------------------------------------------------------------------- /adlibrary/src/main/res/layout/anim_dialog_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 19 | 20 | 24 | 25 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /adlibrary/src/main/res/layout/progress_empty_custom_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 15 | 16 | 20 | 21 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /adlibrary/src/main/res/layout/progress_empty_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 20 | 21 | 34 | 35 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /adlibrary/src/main/res/layout/progress_error_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 14 | 15 | 20 | 21 | 22 | 36 | 37 |