├── .gitignore
├── .idea
├── .name
├── compiler.xml
├── copyright
│ └── profiles_settings.xml
├── gradle.xml
├── inspectionProfiles
│ ├── Project_Default.xml
│ └── profiles_settings.xml
├── libraries
│ ├── animated_vector_drawable_23_3_0.xml
│ ├── appcompat_v7_23_3_0.xml
│ ├── design_23_3_0.xml
│ ├── recyclerview_v7_23_3_0.xml
│ ├── support_annotations_23_3_0.xml
│ ├── support_v4_23_3_0.xml
│ └── support_vector_drawable_23_3_0.xml
├── misc.xml
├── modules.xml
├── runConfigurations.xml
├── vcs.xml
└── workspace.xml
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── cn
│ │ └── ittiger
│ │ └── ApplicationTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── cn
│ │ │ └── ittiger
│ │ │ └── ucpage
│ │ │ ├── DemoActivity.java
│ │ │ └── view
│ │ │ ├── ContentHeadView.java
│ │ │ ├── ContentView.java
│ │ │ ├── MoveView.java
│ │ │ ├── PageHeadView.java
│ │ │ ├── PageNavigationView.java
│ │ │ ├── TouchMoveView.java
│ │ │ └── UCIndexView.java
│ └── res
│ │ ├── layout
│ │ ├── activity_uc_index_view.xml
│ │ ├── content_head_view_layout.xml
│ │ ├── content_view_layout.xml
│ │ ├── page_head_view_layout.xml
│ │ └── page_navigation_view_layout.xml
│ │ ├── menu
│ │ └── menu_main.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-v21
│ │ └── styles.xml
│ │ ├── values-w820dp
│ │ └── dimens.xml
│ │ └── values
│ │ ├── attrs.xml
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── cn
│ └── ittiger
│ └── ExampleUnitTest.java
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── local.properties
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | .DS_Store
4 | local.properties
5 | gradle.properties
6 | /.idea
7 | /build
8 | /captures
9 |
--------------------------------------------------------------------------------
/.idea/.name:
--------------------------------------------------------------------------------
1 | UCIndexAnimation
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
23 |
24 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.idea/libraries/animated_vector_drawable_23_3_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/libraries/appcompat_v7_23_3_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/.idea/libraries/design_23_3_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/.idea/libraries/recyclerview_v7_23_3_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/.idea/libraries/support_annotations_23_3_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.idea/libraries/support_v4_23_3_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/.idea/libraries/support_vector_drawable_23_3_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # UC浏览器首页滑动动画实现
2 |
3 | #### 现在已采用Behavior实现此效果,代码在这里 [https://github.com/huyongli/UCMainViewForBehavior](https://github.com/huyongli/UCMainViewForBehavior)
4 |
5 |
6 | 库的相关讲解见我的博客[ittiger.cn](http://ittiger.cn/2016/05/26/UC%E6%B5%8F%E8%A7%88%E5%99%A8%E9%A6%96%E9%A1%B5%E6%BB%91%E5%8A%A8%E5%8A%A8%E7%94%BB%E5%AE%9E%E7%8E%B0/)
7 |
8 |
9 | 个人微信公众号,欢迎扫码关注交流:
10 | 
11 |
12 |
13 | 效果图如下:
14 | 
15 | 
16 | 
17 | 
18 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 23
5 | buildToolsVersion "23.0.3"
6 |
7 | defaultConfig {
8 | applicationId "cn.ittiger"
9 | minSdkVersion 14
10 | targetSdkVersion 23
11 | versionCode 1
12 | versionName "1.0"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile fileTree(dir: 'libs', include: ['*.jar'])
24 | testCompile 'junit:junit:4.12'
25 | compile 'com.android.support:appcompat-v7:23.3.0'
26 | compile 'com.android.support:design:23.3.0'
27 | }
28 |
--------------------------------------------------------------------------------
/app/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 /home/baina/ylhu/program/android-sdk-linux/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 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/cn/ittiger/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package cn.ittiger;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
10 |
11 |
16 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/ittiger/ucpage/DemoActivity.java:
--------------------------------------------------------------------------------
1 | package cn.ittiger.ucpage;
2 |
3 | import cn.ittiger.ucpage.view.UCIndexView;
4 |
5 | import android.app.Activity;
6 | import android.os.Bundle;
7 |
8 | public class DemoActivity extends Activity {
9 | UCIndexView mUCIndexView;
10 | boolean flag = false;
11 |
12 | @Override
13 | protected void onCreate(Bundle savedInstanceState) {
14 |
15 | super.onCreate(savedInstanceState);
16 | setContentView(R.layout.activity_uc_index_view);
17 | mUCIndexView = (UCIndexView) findViewById(R.id.ucindexview);
18 | }
19 |
20 | @Override
21 | public void onBackPressed() {
22 |
23 | if(flag == false && !mUCIndexView.isPullRestoreEnable()) {
24 | mUCIndexView.onBackRestore();
25 | flag = true;
26 | } else {
27 | super.onBackPressed();
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/ittiger/ucpage/view/ContentHeadView.java:
--------------------------------------------------------------------------------
1 | package cn.ittiger.ucpage.view;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 |
6 | /**
7 | * 内容视图的头部(对应UC首页新闻视图完全展示后的新闻类型导航头部部分,初始时隐藏)
8 | *
9 | * @author laohu
10 | * @link http://ittiger.cn
11 | */
12 | public class ContentHeadView extends MoveView {
13 |
14 | public ContentHeadView(Context context) {
15 | super(context);
16 | }
17 |
18 | public ContentHeadView(Context context, AttributeSet attrs) {
19 | super(context, attrs);
20 | }
21 |
22 | public ContentHeadView(Context context, AttributeSet attrs, int defStyleAttr) {
23 | super(context, attrs, defStyleAttr);
24 | }
25 |
26 | public synchronized void onShowAnimation(float step) {
27 |
28 | if(isShowFinish()) {
29 | return;
30 | }
31 | updateMarginTop(-getShowMoveStep(step));
32 | }
33 |
34 | public synchronized void onHideAnimation(float step) {
35 |
36 | if(isHideFinish()) {
37 | return;
38 | }
39 | updateMarginTop(getHideMoveStep(step));
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/ittiger/ucpage/view/ContentView.java:
--------------------------------------------------------------------------------
1 | package cn.ittiger.ucpage.view;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 |
6 | /**
7 | * @author laohu
8 | * @link http://ittiger.cn
9 | *
10 | * 内容视图(对应UC首页中展示新闻内容的视图),主要滑动操作在此视图上
11 | */
12 | public class ContentView extends TouchMoveView {
13 |
14 | public ContentView(Context context) {
15 | super(context);
16 | }
17 |
18 | public ContentView(Context context, AttributeSet attrs) {
19 | super(context, attrs);
20 | }
21 |
22 | public ContentView(Context context, AttributeSet attrs, int defStyleAttr) {
23 | super(context, attrs, defStyleAttr);
24 | }
25 |
26 | public synchronized void onShowAnimation(float step) {
27 |
28 | if(isShowFinish()) {
29 | return;
30 | }
31 | updateMarginTop(-getShowMoveStep(step));
32 | }
33 |
34 | public synchronized void onHideAnimation(float step) {
35 |
36 | if(isHideFinish()) {
37 | return;
38 | }
39 | updateMarginTop(getHideMoveStep(step));
40 | }
41 |
42 | /**
43 | * 获取当前视图在展示过程中已经滑离初始化位置的距离
44 | * @return
45 | */
46 | public int getShowOffset() {
47 |
48 | return mHideStopMarginTop - getMarginTop();
49 | }
50 |
51 | /**
52 | * 获取当前视图在恢复过程中已经滑离展示停止位置的距离
53 | * @return
54 | */
55 | public int getHideOffset() {
56 |
57 | return getMarginTop() - mShowStopMarginTop;
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/ittiger/ucpage/view/MoveView.java:
--------------------------------------------------------------------------------
1 | package cn.ittiger.ucpage.view;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.widget.FrameLayout;
6 |
7 | /**
8 | * @author laohu
9 | * @link http://ittiger.cn
10 | *
11 | */
12 | public class MoveView extends FrameLayout {
13 |
14 | /**
15 | * 需要滑动的高度
16 | */
17 | protected int mNeedMoveHeight = -1;
18 | /**
19 | * Show展示时的停止值,此处我设置向上滑动为Show的状态,也可称为展示状态
20 | */
21 | protected int mShowStopMarginTop;
22 | /**
23 | * Hide时的停止值,此处我设置向下滑动为Hide状态,也可称为恢复初始化状态
24 | */
25 | protected int mHideStopMarginTop;
26 |
27 | public MoveView(Context context, AttributeSet attrs, int defStyleAttr) {
28 |
29 | super(context, attrs, defStyleAttr);
30 | }
31 |
32 | public MoveView(Context context, AttributeSet attrs) {
33 |
34 | super(context, attrs);
35 | }
36 |
37 | public MoveView(Context context) {
38 |
39 | super(context);
40 | }
41 |
42 | /**
43 | * 当前View是否可以出发TouchEvent事件
44 | * @return 默认不允许
45 | */
46 | public boolean isTouchEventEnable() {
47 |
48 | return false;
49 | }
50 |
51 | /**
52 | * 获取此视图需要滑动的高度
53 | * @return
54 | */
55 | protected int getNeedMoveHeight() {
56 |
57 | return mNeedMoveHeight;
58 | }
59 |
60 | /**
61 | * 设置此视图需要滑动的高度
62 | * @param needMoveHeight
63 | */
64 | protected void setNeedMoveHeight(int needMoveHeight) {
65 |
66 | mNeedMoveHeight = needMoveHeight;
67 | }
68 |
69 | /**
70 | * 设置此视图向上滑动时,滑动停止时的marginTop值
71 | * @param showStopMarginTop
72 | */
73 | protected void setShowStopMarginTop(int showStopMarginTop) {
74 |
75 | mShowStopMarginTop = showStopMarginTop;
76 | }
77 |
78 | /**
79 | * 设置此视图向下滑动时,滑动停止时的marginTop值
80 | * @param hideStopMarginTop
81 | */
82 | protected void setHideStopMarginTop(int hideStopMarginTop) {
83 |
84 | mHideStopMarginTop = hideStopMarginTop;
85 | }
86 |
87 | /**
88 | * 或取此视图当前的marginTop值
89 | * @return
90 | */
91 | protected int getMarginTop() {
92 |
93 | return ((MarginLayoutParams)getLayoutParams()).topMargin;
94 | }
95 |
96 | /**
97 | * 根据指定的step更新此视图的MarginTop值
98 | * @param step 此处的step值分正负,如果向marginTop减小,则step为负数
99 | */
100 | protected void updateMarginTop(float step) {
101 |
102 | //将step转换为整数
103 | int intStep = step > 0 ? ((int)(step + 0.5f)) : -((int)(Math.abs(step) + 0.5f));
104 |
105 | MarginLayoutParams layoutParams = (MarginLayoutParams)getLayoutParams();
106 | layoutParams.topMargin = layoutParams.topMargin + intStep;
107 | setLayoutParams(layoutParams);
108 | invalidate();
109 | }
110 |
111 | /**
112 | * 是否恢复完成
113 | * @return
114 | */
115 | protected synchronized boolean isHideFinish() {
116 |
117 | if(mHideStopMarginTop < 0) {
118 | return getMarginTop() <= mHideStopMarginTop ? true : false;
119 | } else {
120 | return getMarginTop() >= mHideStopMarginTop ? true : false;
121 | }
122 | }
123 |
124 | /**
125 | * 是否展示完成
126 | * @return
127 | */
128 | protected synchronized boolean isShowFinish() {
129 |
130 | if(mShowStopMarginTop > 0) {
131 | return getMarginTop() <= mShowStopMarginTop ? true : false;
132 | } else {
133 | return getMarginTop() >= mShowStopMarginTop ? true : false;
134 | }
135 | }
136 |
137 |
138 | /**
139 | * 获取当前实际可滑动的距离
140 | * @param step 可滑动距离,此距离值会与最大可滑动距离进行比较,取最小值
141 | * @return
142 | */
143 | protected float getShowMoveStep(float step) {
144 |
145 | int maxStep = Math.abs(Math.abs(getMarginTop()) - Math.abs(mShowStopMarginTop));//此次滑动所允许滑动的最大step
146 | if(step > maxStep) {//可用滑动的marginTop小于step值,则用最大可滑动值替代
147 | step = maxStep;
148 | }
149 | return step;
150 | }
151 |
152 | /**
153 | * 获取当前实际可滑动的距离
154 | * @param step 可滑动距离,此距离值会与最大可滑动距离进行比较,取最小值
155 | * @return
156 | */
157 | protected float getHideMoveStep(float step) {
158 |
159 | int maxStep = Math.abs(Math.abs(mHideStopMarginTop) - Math.abs(getMarginTop()));//此次滑动所允许滑动的最大step
160 | if(step > maxStep) {//可用滑动的marginTop小于step值,则用最大可滑动值替代
161 | step = maxStep;
162 | }
163 | return step;
164 | }
165 | }
166 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/ittiger/ucpage/view/PageHeadView.java:
--------------------------------------------------------------------------------
1 | package cn.ittiger.ucpage.view;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 |
6 | /**
7 | * 页面头部View(对应UC首页新闻视图向上滑动完成后页面的头部View,UC中最开始隐藏)
8 | * @author laohu
9 | * @link http://ittiger.cn
10 | *
11 | */
12 | public class PageHeadView extends MoveView {
13 |
14 | public PageHeadView(Context context) {
15 |
16 | super(context);
17 | }
18 |
19 | public PageHeadView(Context context, AttributeSet attrs) {
20 |
21 | super(context, attrs);
22 | }
23 |
24 | public PageHeadView(Context context, AttributeSet attrs, int defStyleAttr) {
25 |
26 | super(context, attrs, defStyleAttr);
27 | }
28 |
29 | public synchronized void onShowAnimation(float step) {
30 |
31 | if(isShowFinish()) {
32 | return;
33 | }
34 | updateMarginTop(getShowMoveStep(step));
35 | }
36 |
37 | public synchronized void onHideAnimation(float step) {
38 |
39 | if(isHideFinish()) {
40 | return;
41 | }
42 | updateMarginTop(-getHideMoveStep(step));
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/ittiger/ucpage/view/PageNavigationView.java:
--------------------------------------------------------------------------------
1 | package cn.ittiger.ucpage.view;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 |
6 | /**
7 | * UC首页的网址导航视图
8 | *
9 | * @author laohu
10 | * @link http://ittiger.cn
11 | */
12 | public class PageNavigationView extends TouchMoveView {
13 |
14 | public PageNavigationView(Context context) {
15 |
16 | super(context);
17 | }
18 |
19 | public PageNavigationView(Context context, AttributeSet attrs) {
20 |
21 | super(context, attrs);
22 | }
23 |
24 | public PageNavigationView(Context context, AttributeSet attrs,
25 | int defStyleAttr) {
26 |
27 | super(context, attrs, defStyleAttr);
28 | }
29 |
30 | public synchronized void onShowAnimation(float step) {
31 |
32 | if(isShowFinish()) {
33 | return;
34 | }
35 | updateMarginTop(-getShowMoveStep(step));
36 | }
37 |
38 | public synchronized void onHideAnimation(float step) {
39 |
40 | if(isHideFinish()) {
41 | return;
42 | }
43 | updateMarginTop(getHideMoveStep(step));
44 | }
45 |
46 | @Override
47 | public synchronized boolean isShowFinish() {
48 |
49 | return getMarginTop() <= mShowStopMarginTop ? true : false;
50 | }
51 |
52 | @Override
53 | public synchronized boolean isHideFinish() {
54 |
55 | return getMarginTop() >= mHideStopMarginTop ? true : false;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/ittiger/ucpage/view/TouchMoveView.java:
--------------------------------------------------------------------------------
1 | package cn.ittiger.ucpage.view;
2 |
3 | import android.content.Context;
4 | import android.text.method.Touch;
5 | import android.util.AttributeSet;
6 | import android.view.MotionEvent;
7 |
8 | public class TouchMoveView extends MoveView {
9 |
10 | private TouchMoveListener mTouchMoveListener;
11 |
12 | public TouchMoveView(Context context, AttributeSet attrs, int defStyleAttr) {
13 | super(context, attrs, defStyleAttr);
14 | }
15 |
16 | public TouchMoveView(Context context, AttributeSet attrs) {
17 | super(context, attrs);
18 | }
19 |
20 | public TouchMoveView(Context context) {
21 | super(context);
22 | }
23 |
24 | @Override
25 | public boolean isTouchEventEnable() {
26 | return true;
27 | }
28 |
29 | @Override
30 | public boolean onTouchEvent(MotionEvent event) {
31 |
32 | if(isTouchEventEnable()) {
33 | if(mTouchMoveListener != null) {
34 | mTouchMoveListener.onTouchMoveEvent(event);
35 | }
36 | }
37 | return isTouchEventEnable() || super.onTouchEvent(event);
38 | }
39 |
40 |
41 | public interface TouchMoveListener {
42 |
43 | void onTouchMoveEvent(MotionEvent event);
44 | }
45 |
46 | public void setTouchMoveListener(TouchMoveListener touchMoveListener) {
47 |
48 | this.mTouchMoveListener = touchMoveListener;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/ittiger/ucpage/view/UCIndexView.java:
--------------------------------------------------------------------------------
1 | package cn.ittiger.ucpage.view;
2 |
3 | import cn.ittiger.ucpage.R;
4 |
5 | import android.content.Context;
6 | import android.content.res.TypedArray;
7 | import android.util.AttributeSet;
8 | import android.util.Log;
9 | import android.view.MotionEvent;
10 | import android.widget.FrameLayout;
11 |
12 | /**
13 | * 包含UC首页动画的自定义View
14 | * @author laohu
15 | */
16 | public class UCIndexView extends FrameLayout implements TouchMoveView.TouchMoveListener {
17 |
18 | /**
19 | * 上下文
20 | */
21 | private Context mContext;
22 | /**
23 | * 页面头部视图(对应UC首页新闻视图向上滑动完成后页面的头部View,UC中最开始隐藏)
24 | */
25 | private PageHeadView mPageHeadView;
26 | /**
27 | * 页面内容导航视图(对应UC首页的网址导航视图)
28 | */
29 | private PageNavigationView mPageNavigationView;
30 | /**
31 | * 内容视图的头部视图(对应UC首页新闻视图完全展示后的新闻类型导航头部部分,初始时隐藏)
32 | */
33 | private ContentHeadView mContentHeadView;
34 | /**
35 | * 内容视图(对应UC首页中的新闻部分)
36 | */
37 | private ContentView mContentView;
38 |
39 |
40 | /**
41 | * 页面头部视图是否固定(默认不固定),此属性为true的话PageHeadView则会固定在界面顶部不会滑动,此属性为false的话PageHeadView会首先隐藏再慢慢滑出
42 | */
43 | private boolean mIsPageHeadViewFixed = false;
44 | /**
45 | * 内容视图的头部视图是否启用,默认启用
46 | */
47 | private boolean mIsContentHeadViewEnable = true;
48 | /**
49 | * 是否允许下拉时恢复初始化状态,默认不允许
50 | */
51 | private boolean mIsPullRestoreEnable = false;
52 | /**
53 | * 页面头部的高度
54 | */
55 | private int mPageHeadViewHeight = 0;
56 | /**
57 | * 页面内容视图的头部视图的高度,当内容视图的头部视图不启用时,此值为0
58 | */
59 | private int mContentHeadViewHeight = 0;
60 | /**
61 | * 手指放开后,视图自动滑动时的每次滑动距离间隔,默认每次滑动20px
62 | */
63 | private int mAutoSlipStep = 20;
64 | /**
65 | * 手指放开后,视图自动滑动时的时间间隔,默认每间隔5毫秒滑动一次
66 | */
67 | private int mAutoSlipTimeStep = 5;
68 |
69 | public UCIndexView(Context context) {
70 |
71 | super(context);
72 | this.init(context, null);
73 | }
74 |
75 | public UCIndexView(Context context, AttributeSet attrs) {
76 |
77 | super(context, attrs);
78 | this.init(context, attrs);
79 | }
80 |
81 | public UCIndexView(Context context, AttributeSet attrs, int defStyleAttr) {
82 |
83 | super(context, attrs, defStyleAttr);
84 | this.init(context, attrs);
85 | }
86 |
87 | private void init(Context context, AttributeSet attributeSet) {
88 |
89 | this.mContext = context;
90 | TypedArray typeArray = context.obtainStyledAttributes(attributeSet, R.styleable.UCIndexView);
91 |
92 | //页面头部的高度(对应UC首页新闻视图向上滑动完成后页面的头部View,UC中最开始隐藏)
93 | float pageHeadViewHeight = typeArray.getDimension(R.styleable.UCIndexView_pageHeadViewHeight, 0);
94 | mPageHeadViewHeight = (int)(pageHeadViewHeight + 0.5f);
95 |
96 | //页面头部是否固定,默认不固定(即默认隐藏,随着滑动而展示出来),如果固定的话则一直在头部展示不会随着滑动和动
97 | mIsPageHeadViewFixed = typeArray.getBoolean(R.styleable.UCIndexView_isPageHeadViewFixed, false);
98 |
99 | //页面头部的内容布局资源ID
100 | int pageHeadViewLayoutId = typeArray.getResourceId(R.styleable.UCIndexView_pageHeadViewLayoutId, 0);
101 |
102 | //页面内容导航的高度(对应UC首页的网址导航视图)
103 | float pageNavigationViewHeight = typeArray.getDimension(R.styleable.UCIndexView_pageNavigationViewHeight, 0);
104 |
105 | //页面内容导航的布局资源ID
106 | int pageNavigationViewLayoutId = typeArray.getResourceId(R.styleable.UCIndexView_pageNavigationViewLayoutId, 0);
107 |
108 | //内容视图的头部(对应UC首页新闻视图完全展示后的新闻类型导航头部部分,初始时隐藏)
109 | float contentHeadViewHeight = typeArray.getDimension(R.styleable.UCIndexView_contentHeadViewHeight, 0);
110 | mContentHeadViewHeight = (int)(contentHeadViewHeight + 0.5f);
111 |
112 | //内容视图的头部是否启用,默认启用
113 | mIsContentHeadViewEnable = typeArray.getBoolean(R.styleable.UCIndexView_isContentHeadViewEnable, true);
114 |
115 | //内容视图头部的布局资源ID
116 | int contentHeadViewLayoutId = typeArray.getResourceId(R.styleable.UCIndexView_contentHeadViewLayoutId, 0);
117 |
118 | //内容视图的布局资源ID
119 | int contentViewLayoutId = typeArray.getResourceId(R.styleable.UCIndexView_contentViewLayoutId, 0);
120 |
121 | mAutoSlipStep = (int)(typeArray.getDimension(R.styleable.UCIndexView_autoSlipDistanceStep, mAutoSlipStep) + 0.5f);
122 | mAutoSlipTimeStep = typeArray.getInt(R.styleable.UCIndexView_autoSlipTimeStep, mAutoSlipTimeStep);
123 |
124 | mIsPullRestoreEnable = typeArray.getBoolean(R.styleable.UCIndexView_isPullRestoreEnable, false);
125 |
126 | typeArray.recycle();
127 |
128 | //下面四个视图的添加顺序不能更改,否则无法达到效果,此处视图的遮盖采用的是FrameLayout布局的特性
129 | addPageNavigationView(pageNavigationViewLayoutId, pageNavigationViewHeight);
130 | addPageHeadView(pageHeadViewLayoutId, pageHeadViewHeight);
131 | addContentHeadView(contentHeadViewLayoutId, contentHeadViewHeight, pageNavigationViewHeight);
132 | addContentView(contentViewLayoutId, pageNavigationViewHeight);
133 | }
134 |
135 | /**
136 | * 添加页面头部视图
137 | * @param resId 页面头部视图中的元素布局资源文件ID
138 | * @param pageHeadViewHeight 页面头部视图的高度
139 | */
140 | private void addPageHeadView(int resId, float pageHeadViewHeight) {
141 |
142 | if(resId == 0) {
143 | throw new IllegalArgumentException("please set attribution pageHeadViewLayoutId int UCIndexView");
144 | }
145 |
146 | mPageHeadView = new PageHeadView(mContext);
147 | LayoutParams layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, (int)(pageHeadViewHeight + 0.5f));
148 | if(!mIsPageHeadViewFixed) {//不固定头部,头部会进行隐藏
149 | layoutParams.topMargin = -(int)(pageHeadViewHeight + 0.5f);
150 | }
151 | mPageHeadView.setLayoutParams(layoutParams);
152 |
153 | mPageHeadView.setShowStopMarginTop(0);//向上滑时PageHeadView的滑动停止的位置,该位置应该是PageHeadView刚好展示在页面顶部的位置,此时marginTop为0
154 | mPageHeadView.setHideStopMarginTop(layoutParams.topMargin);//向下滑时PageHeadView的滑动停止的位置,此时该位置为PageHeadView的初始化位置
155 | mPageHeadView.setNeedMoveHeight(mPageHeadViewHeight);//设置ContentHeadView相对ContentView需要滑动的高度,即为其本身的高度
156 |
157 | inflate(mContext, resId, mPageHeadView);
158 | addView(mPageHeadView);
159 | }
160 |
161 | /**
162 | * 添加页面内容导航视图
163 | * @param resId 页面内容导航视图的元素布局资源文件ID
164 | * @param pageNavigationViewHeight 页面内容导航视图的高度
165 | */
166 | private void addPageNavigationView(int resId, float pageNavigationViewHeight) {
167 |
168 | if(resId == 0) {
169 | throw new IllegalArgumentException("please set attribution pageNavigationViewLayoutId int UCIndexView");
170 | }
171 | mPageNavigationView = new PageNavigationView(mContext);
172 | if(mIsPageHeadViewFixed) {//页面头部固定时,将PageNavigationView的PadingTop设置为PageHeadView的高度,防止PageHeadView将PageNavigationView的部分内容遮住
173 | mPageNavigationView.setPadding(0, mPageHeadViewHeight, 0, 0);
174 | }
175 | LayoutParams layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, (int)(pageNavigationViewHeight + 0.5f));
176 | mPageNavigationView.setLayoutParams(layoutParams);
177 | mPageNavigationView.setTouchMoveListener(this);
178 |
179 | //向上滑动时PageNavigationView的停止位置设置为PageHeadView高度的一半
180 | mPageNavigationView.setShowStopMarginTop(-mPageHeadViewHeight / 2);
181 | //PageNavigationView的滑动距离为PageHeadView高度的一半
182 | mPageNavigationView.setNeedMoveHeight(mPageHeadViewHeight / 2);
183 | mPageNavigationView.setHideStopMarginTop(layoutParams.topMargin);
184 |
185 | inflate(mContext, resId, mPageNavigationView);
186 | addView(mPageNavigationView);
187 | }
188 |
189 | /**
190 | * 添加内容视图的头部视图
191 | * @param resId 页面内容视图中的头部视图的元素布局资源文件ID
192 | * @param contentHeadViewHeight 页面内容视图中的头部视图的高度
193 | * @param marginTop 页面内容视图中的头部视图的marginTop
194 | */
195 | private void addContentHeadView(int resId, float contentHeadViewHeight, float marginTop) {
196 |
197 | if(!mIsContentHeadViewEnable) {//内容头部视图不启用
198 | mContentHeadViewHeight = 0;
199 | return;
200 | }
201 | if(resId == 0) {
202 | throw new IllegalArgumentException("please set attribution contentHeadViewLayoutId int UCIndexView");
203 | }
204 | mContentHeadView = new ContentHeadView(mContext);
205 | LayoutParams layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, (int)(contentHeadViewHeight + 0.5f));
206 | layoutParams.topMargin = (int)(marginTop + 0.5f);
207 | mContentHeadView.setLayoutParams(layoutParams);
208 |
209 | mContentHeadView.setShowStopMarginTop(mPageHeadViewHeight);//向上滑时ContentHeadView的滑动停止的位置,该位置应该是刚好距离一个PageHeadView的高度
210 | mContentHeadView.setHideStopMarginTop(layoutParams.topMargin);//向下滑时ContentHeadView的滑动停止的位置,此时该位置为ContentHeadView的初始化位置
211 | mContentHeadView.setNeedMoveHeight((int)(contentHeadViewHeight + 0.5f));//设置ContentHeadView相对ContentView需要滑动的高度,即为其本身的高度
212 |
213 | inflate(mContext, resId, mContentHeadView);
214 | addView(mContentHeadView);
215 | }
216 |
217 | /**
218 | * 添加内容视图
219 | * @param resId 页面内容视图的元素布局资源文件ID
220 | * @param marginTop 页面内容视图的marginTop
221 | */
222 | private void addContentView(int resId, float marginTop) {
223 |
224 | if(resId == 0) {
225 | throw new IllegalArgumentException("please set attribution contentViewLayoutId int UCIndexView");
226 | }
227 |
228 | mContentView = new ContentView(mContext);
229 | LayoutParams layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
230 | layoutParams.topMargin = (int)(marginTop + 0.5f);
231 | mContentView.setLayoutParams(layoutParams);
232 | mContentView.setTouchMoveListener(this);
233 |
234 | //向上滑时ContentView的滑动停止的位置,该位置应该是PageHeadView和ContentHeadView刚好展示在页面顶部的位置,此时marginTop为PageHeadView和ContentHeadView两者的高度之和
235 | mContentView.setShowStopMarginTop(mContentHeadViewHeight + mPageHeadViewHeight);
236 | mContentView.setHideStopMarginTop(layoutParams.topMargin);//向下滑时ContentView的滑动停止的位置,此时该位置为ContentView的初始化位置
237 | //ContentView需要移动的距离为其本身到顶部的MarginTop值减去ContentHeadView和PageHeadView两者的高度
238 | mContentView.setNeedMoveHeight(Math.abs(layoutParams.topMargin - mContentHeadViewHeight - mPageHeadViewHeight));
239 |
240 | inflate(mContext, resId, mContentView);
241 | addView(mContentView);
242 | }
243 |
244 | /**
245 | * 上一次的触摸点Y坐标
246 | */
247 | private float mLastTouchY = 0;
248 | /**
249 | * 两次触摸点之间的距离
250 | */
251 | private float mDelY = 0;
252 |
253 | @Override
254 | public void onTouchMoveEvent(MotionEvent event) {
255 |
256 | switch (event.getAction()) {
257 | case MotionEvent.ACTION_DOWN:
258 | mLastTouchY = event.getRawY();
259 | break;
260 | case MotionEvent.ACTION_MOVE:
261 | mDelY = event.getRawY() - mLastTouchY;
262 | viewMove(mDelY, mIsPullRestoreEnable);
263 | mLastTouchY = event.getRawY();
264 | break;
265 | case MotionEvent.ACTION_UP:
266 | int offset = 0;
267 | if(mDelY > 0) {//hide,下拉
268 | if(!mIsPullRestoreEnable) {//当前不允许下拉恢复
269 | return;
270 | }
271 | offset = mContentView.getHideOffset();
272 | } else {//show, 上拉
273 | offset = mContentView.getShowOffset();
274 | }
275 | if(offset <= mPageHeadView.getNeedMoveHeight() / 2) {//没有滑过二分之一高度
276 | slip(-mDelY, mIsPullRestoreEnable);
277 | } else {
278 | slip(mDelY, mIsPullRestoreEnable);
279 | }
280 | break;
281 | }
282 | }
283 |
284 | /**
285 | * 手指松开屏幕后,视图自动滑动
286 | * 每隔 mAutoSlipTimeStep 长时间滑动 mAutoSlipStep 距离
287 | * @param delY 当前的滑动距离
288 | * @param isPullRestoreEnable 是否允许下拉恢复
289 | */
290 | private void slip(float delY, final boolean isPullRestoreEnable) {
291 |
292 | if(delY > 0) {//当前滑动为向下滑动,即处于恢复状态
293 | if(isHideFinish()) {//已经恢复结束
294 | return;
295 | }
296 | postDelayed(new Runnable() {
297 | @Override
298 | public void run() {
299 |
300 | viewMove(mAutoSlipStep, isPullRestoreEnable);
301 | slip(mAutoSlipStep, isPullRestoreEnable);//准备下一次滑动
302 | }
303 | }, mAutoSlipTimeStep);
304 | } else {//当前滑动为向上滑动,即处于展示状态
305 | if(isShowFinish()) {//已经展示结束
306 | return;
307 | }
308 | postDelayed(new Runnable() {
309 | @Override
310 | public void run() {
311 |
312 | viewMove(-mAutoSlipStep, isPullRestoreEnable);
313 | slip(-mAutoSlipStep, isPullRestoreEnable);//准备下一次滑动
314 | }
315 | }, mAutoSlipTimeStep);
316 | }
317 | }
318 |
319 | /**
320 | * 对所有视图进行滑动操作
321 | * @param delY 当前的滑动步长
322 | * @param isPullRestoreEnable 是否允许下拉恢复
323 | */
324 | private void viewMove(float delY, boolean isPullRestoreEnable) {
325 |
326 | float step = Math.abs(delY);
327 | //根据滑动距离的比例计算PageHeadView的滑动步长
328 | float pageHeadViewStep = step * mPageHeadView.getNeedMoveHeight() / mContentView.getNeedMoveHeight();
329 | //手指滑动距离作为ContentView的滑动步长
330 | float contentViewStep = step;
331 | //ContentHeadView初始不固定显示时,其实际滑动步长为ContentView的滑动步长加上其相对ContentView的滑动步长
332 | float contentHeadViewStep = mIsContentHeadViewEnable ? step + step * mContentHeadView.getNeedMoveHeight() / mContentView.getNeedMoveHeight() : 0;
333 | float pageNavigationViewStep = step * mPageNavigationView.getNeedMoveHeight() / mContentView.getNeedMoveHeight();
334 |
335 | if(delY > 0) {//下滑
336 | if(!isPullRestoreEnable) {//当前不允许下拉恢复
337 | return;
338 | }
339 | if(!isHideFinish()) {//恢复状态是否已完成
340 | if(mIsPageHeadViewFixed == false) {
341 | mPageHeadView.onHideAnimation(pageHeadViewStep);
342 | }
343 | mContentView.onHideAnimation(contentViewStep);
344 | if(mIsContentHeadViewEnable) {
345 | mContentHeadView.onHideAnimation(contentHeadViewStep);
346 | }
347 | mPageNavigationView.onHideAnimation(pageNavigationViewStep);
348 | }
349 | } else {//上滑
350 | if(!isShowFinish()) {//展示状态是否已完成
351 | if(mIsPageHeadViewFixed == false) {//PageHeadView没有被固定时才进行滑动
352 | mPageHeadView.onShowAnimation(pageHeadViewStep);
353 | }
354 | mContentView.onShowAnimation(contentViewStep);
355 | if(mIsContentHeadViewEnable) {//ContentHeadView启用时才进行滑动
356 | mContentHeadView.onShowAnimation(contentHeadViewStep);
357 | }
358 | mPageNavigationView.onShowAnimation(pageNavigationViewStep);
359 | }
360 | }
361 | }
362 |
363 | /**
364 | * 判断所有视图是否全部恢复结束
365 | * @return
366 | */
367 | private boolean isHideFinish() {
368 |
369 | //当PageHeadView固定的时候,默认为恢复结束
370 | boolean pageHeadViewHideFinish = mIsPageHeadViewFixed ? true : mPageHeadView.isHideFinish();
371 | //当ContentHeadView不启用的时候,默认为恢复结束
372 | boolean contentHeadViewHideFinish = mIsContentHeadViewEnable ? mContentHeadView.isHideFinish() : true;
373 |
374 | return pageHeadViewHideFinish && mPageNavigationView.isHideFinish() &&
375 | contentHeadViewHideFinish && mContentView.isHideFinish();
376 | }
377 |
378 | /**
379 | * 判断所有视图是否全部展示结束
380 | * @return
381 | */
382 | private boolean isShowFinish() {
383 |
384 | //当PageHeadView固定的时候,默认为展示结束
385 | boolean pageHeadViewShowFinish = mIsPageHeadViewFixed ? true : mPageHeadView.isShowFinish();
386 | //当ContentHeadView不启用的时候,默认为展示结束
387 | boolean contentHeadViewShowFinish = mIsContentHeadViewEnable ? mContentHeadView.isShowFinish() : true;
388 |
389 | return pageHeadViewShowFinish && mPageNavigationView.isShowFinish() &&
390 | contentHeadViewShowFinish && mContentView.isShowFinish();
391 | }
392 |
393 | /**
394 | * 恢复初始化状态
395 | */
396 | public void onBackRestore() {
397 | slip(1, true);
398 | }
399 |
400 | public boolean isPullRestoreEnable() {
401 |
402 | return mIsPullRestoreEnable;
403 | }
404 |
405 | public void setPullRestoreEnable(boolean isPullRestoreEnable) {
406 |
407 | mIsPullRestoreEnable = isPullRestoreEnable;
408 | }
409 | }
410 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_uc_index_view.xml:
--------------------------------------------------------------------------------
1 |
2 |
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/content_head_view_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/content_view_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/page_head_view_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/page_navigation_view_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_main.xml:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/huyongli/UCIndexAnimation/a0713c25b897bff9184c260ede4a0708a35051e8/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/huyongli/UCIndexAnimation/a0713c25b897bff9184c260ede4a0708a35051e8/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/huyongli/UCIndexAnimation/a0713c25b897bff9184c260ede4a0708a35051e8/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/huyongli/UCIndexAnimation/a0713c25b897bff9184c260ede4a0708a35051e8/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/huyongli/UCIndexAnimation/a0713c25b897bff9184c260ede4a0708a35051e8/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/values-v21/styles.xml:
--------------------------------------------------------------------------------
1 | >
2 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 10dp
6 | 40dp
7 | -40dp
8 | 200dp
9 | 16dp
10 | 16dp
11 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | UCPageDemo
5 | UC头条
6 | NaviContent_网址导航区
7 | 新闻头部导航
8 | 新闻内容区
9 | StartActivity
10 | Hello world!
11 | Settings
12 | DemoActivity
13 |
14 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/app/src/test/java/cn/ittiger/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package cn.ittiger;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * To work on unit tests, switch the Test Artifact in the Build Variants view.
9 | */
10 | public class ExampleUnitTest {
11 | @Test
12 | public void addition_isCorrect() throws Exception {
13 | assertEquals(4, 2 + 2);
14 | }
15 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | // jcenter()
6 | // jcenter{"http://jcenter.bintray.com/"};
7 | mavenLocal()
8 | maven {
9 | name "jcenter"
10 | url "http://jcenter.bintray.com/"
11 | }
12 | }
13 | dependencies {
14 | classpath 'com.android.tools.build:gradle:1.+'
15 |
16 | // NOTE: Do not place your application dependencies here; they belong
17 | // in the individual module build.gradle files
18 | }
19 | }
20 |
21 | allprojects {
22 | repositories {
23 | // jcenter()
24 | // jcenter{"http://jcenter.bintray.com/"};
25 | mavenLocal()
26 | maven {
27 | name "jcenter"
28 | url "http://jcenter.bintray.com/"
29 | }
30 | }
31 | }
32 |
33 | task clean(type: Delete) {
34 | delete rootProject.buildDir
35 | }
36 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | ## Project-wide Gradle settings.
2 | #
3 | # For more details on how to configure your build environment visit
4 | # http://www.gradle.org/docs/current/userguide/build_environment.html
5 | #
6 | # Specifies the JVM arguments used for the daemon process.
7 | # The setting is particularly useful for tweaking memory settings.
8 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
9 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
10 | #
11 | # When configured, Gradle will run in incubating parallel mode.
12 | # This option should only be used with decoupled projects. More details, visit
13 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
14 | # org.gradle.parallel=true
15 | #Fri Apr 22 10:02:14 CST 2016
16 | #systemProp.http.proxyHost=172.17.100.131
17 | #systemProp.http.proxyPort=8888
18 | #systemProp.https.proxyHost=172.17.100.131
19 | #systemProp.https.proxyPort=8888
20 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/huyongli/UCIndexAnimation/a0713c25b897bff9184c260ede4a0708a35051e8/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Oct 21 11:34:03 PDT 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/local.properties:
--------------------------------------------------------------------------------
1 | ## This file is automatically generated by Android Studio.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file should *NOT* be checked into Version Control Systems,
5 | # as it contains information specific to your local configuration.
6 | #
7 | # Location of the SDK. This is only used by Gradle.
8 | # For customization when using a Version Control System, please read the
9 | # header note.
10 | sdk.dir=H\:\\AndroidEclipse\\sdk
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------