├── .gitignore
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── gaoneng
│ │ └── autoscrollbacklayout
│ │ ├── GridViewDemoActivity.java
│ │ ├── ListViewDemoActivity.java
│ │ ├── MainActivity.java
│ │ └── RecyclerViewDemoActivity.java
│ └── res
│ ├── drawable
│ └── bg_btn_shape.xml
│ ├── layout
│ ├── activity_grid_view_demo.xml
│ ├── activity_listview_layout.xml
│ ├── activity_recycler_view_demo.xml
│ └── main_layout.xml
│ ├── mipmap-hdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-mdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xxhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xxxhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ └── values
│ ├── colors.xml
│ ├── strings.xml
│ └── styles.xml
├── autoscrollbacklayout
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── gaoneng
│ │ └── library
│ │ ├── AutoScrollBackLayout.java
│ │ ├── DensityUtils.java
│ │ └── ScrollUtil.java
│ └── res
│ ├── anim
│ ├── fab_scale_down.xml
│ └── fab_scale_up.xml
│ ├── drawable-hdpi
│ └── go_top.png
│ ├── drawable-xhdpi
│ └── go_top.png
│ ├── drawable-xxhdpi
│ └── go_top.png
│ ├── drawable-xxxhdpi
│ └── go_top.png
│ └── values
│ ├── attrs.xml
│ └── strings.xml
├── build.gradle
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── preview.gif
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea
5 | .DS_Store
6 | /build
7 | gradlew
8 | gradlew.bat
9 | gradle.properties
10 | /captures
11 | .externalNativeBuild
12 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # AutoScrollBackLayout
2 | 在ListView,GridView,RecyclerView列表滚动向底部一段距离,就自动显示一个返回顶部的按钮
3 |
4 | ## 效果
5 | 
6 |
7 | ## 使用
8 | 1、添加依赖:
9 | ```
10 | compile ('com.gaoneng.library:autoscrollbacklayout:1.1.1'){
11 | exclude group: 'com.android.support', module: 'recyclerview-v7'
12 | }
13 | ```
14 | 2、通过xml文件添加如下:
15 | ```
16 |
17 |
26 |
27 |
33 |
34 | ```
35 | 3、调用bindScrollBack():
36 | ```
37 | AutoScrollBackLayout autoScrollBackLayout = (AutoScrollBackLayout) findViewById(R.id.scroll_layout);
38 | ListView listView = (ListView) findViewById(android.R.id.list);
39 | List list = new ArrayList<>();
40 | for (int i = 0; i < 20; i++) {
41 | list.add("this is a test! in " + i);
42 | }
43 | listView.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, list));
44 | autoScrollBackLayout.bindScrollBack();
45 | ```
46 | ## 原理
47 | - 针对ListView和GridView,通过反射和动态代理的方式监听OnScrollListener,这样就不会影响已有的OnScrollListener的正常运行。
48 | **但是这里需要注意的是,如果已经使用`AbsListView.setOnScrollListener()`设置过监听,
49 | 一定要在其后面调用`autoScrollBackLayout.bindScrollBack()`**
50 | ```
51 | private void hookScrollListenerForListview() {
52 | try {
53 | //通过反射获取mOnScrollListener对象
54 | Field scrollListenerField = AbsListView.class.getDeclaredField("mOnScrollListener");
55 | scrollListenerField.setAccessible(true);
56 | Object object = scrollListenerField.get(wrapView);
57 | //需要被代理的目前对象
58 | AbsListView.OnScrollListener target;
59 | if (object == null) {
60 | //如果mOnScrollListener没有设置过,就设置一个空的用来hook
61 | target = new FakeScrollLitener();
62 | } else {
63 | target = (AbsListView.OnScrollListener) object;
64 | }
65 | //InvocationHandler对象,用于添加额外的控制处理
66 | ScrollListenerInvocationHandler listenerInvocationHandler = new ScrollListenerInvocationHandler(target);
67 | //Proxy.newProxyInstance生成动态代理对象
68 | AbsListView.OnScrollListener proxy = listenerInvocationHandler.getProxy();
69 | if (DEBUG) {
70 | Log.i(TAG, "target=" + target.getClass().getName() + " ,proxy=" + proxy.getClass().getName() + ", proxied interfaces=" + Arrays.toString(proxy.getClass().getInterfaces()));
71 | }
72 | //将代理对象proxy设置到被反射的mOnScrollListener的字段中
73 | scrollListenerField.set(wrapView, proxy);
74 | } catch (Exception e) {
75 | Log.e(TAG, e.toString());
76 | }
77 | }
78 | ```
79 | - 针对RecyclerView,因为其内部的监听已经是`List`形式,所以直接`addOnScrollListener()`方式添加即可;
80 | ```
81 | private void addScrollListenerForRecyclerView() {
82 | ((RecyclerView) wrapView).addOnScrollListener(new RecyclerView.OnScrollListener() {
83 | @Override
84 | public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
85 | if (myScrollLitener != null)
86 | myScrollLitener.onScrollStateChanged(recyclerView, newState);
87 | }
88 |
89 | @Override
90 | public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
91 | if (myScrollLitener != null) myScrollLitener.onScroll(recyclerView, dy, 0, 0);
92 | }
93 | });
94 | }
95 | ```
96 |
97 | ## 其他属性
98 | attrs | value
99 | ------------ | -------------
100 | app:show_scroll | true/false 是否自动显示返回按钮,默认true
101 | app:scroll_distance | dp 触发显示返回按钮的滚动距离,默认100dp
102 | app:show_animation | anim 按钮出现动画,默认 R.anim.fab_scale_up
103 | app:hide_animation | anim 按钮出现动画,默认 R.anim.fab_scale_down
104 | app:auto_arrow_icon | drawable 按钮图标,默认 R.drawable.go_top
105 | app:scroll_gravity | Gravity 按钮的位置,默认 Gravity.BOTTOM and Gravity.CENTER_HORIZONTAL
106 |
107 |
108 |
109 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 25
5 | buildToolsVersion "25.0.0"
6 | defaultConfig {
7 | applicationId "com.gaoneng.autoscrollbacklayout"
8 | minSdkVersion 15
9 | targetSdkVersion 25
10 | versionCode 1
11 | versionName "1.0"
12 | }
13 | buildTypes {
14 | release {
15 | minifyEnabled false
16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
17 | }
18 | }
19 | }
20 |
21 | dependencies {
22 | compile fileTree(dir: 'libs', include: ['*.jar'])
23 | compile project(':autoscrollbacklayout')
24 | compile 'com.android.support:appcompat-v7:25.3.1'
25 | }
26 |
--------------------------------------------------------------------------------
/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/gaoneng/Android/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 |
19 | # Uncomment this to preserve the line number information for
20 | # debugging stack traces.
21 | #-keepattributes SourceFile,LineNumberTable
22 |
23 | # If you keep the line number information, uncomment this to
24 | # hide the original source file name.
25 | #-renamesourcefileattribute SourceFile
26 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
22 |
25 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/app/src/main/java/com/gaoneng/autoscrollbacklayout/GridViewDemoActivity.java:
--------------------------------------------------------------------------------
1 | package com.gaoneng.autoscrollbacklayout;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.os.Bundle;
6 | import android.support.v7.app.AppCompatActivity;
7 | import android.widget.ArrayAdapter;
8 | import android.widget.GridView;
9 |
10 | import com.gaoneng.library.AutoScrollBackLayout;
11 |
12 | import java.util.ArrayList;
13 | import java.util.List;
14 |
15 | public class GridViewDemoActivity extends AppCompatActivity {
16 |
17 | @Override
18 | protected void onCreate(Bundle savedInstanceState) {
19 | super.onCreate(savedInstanceState);
20 | setContentView(R.layout.activity_grid_view_demo);
21 | AutoScrollBackLayout autoScrollBackLayout = (AutoScrollBackLayout) findViewById(R.id.scroll_layout);
22 | GridView gridView = (GridView) findViewById(R.id.gridview);
23 | List list = new ArrayList<>();
24 | for (int i = 0; i < 100; i++) {
25 | list.add("this is a test! in " + i);
26 | }
27 | gridView.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, list));
28 | autoScrollBackLayout.bindScrollBack();
29 | }
30 |
31 | public static void start(Context context) {
32 | Intent starter = new Intent(context, GridViewDemoActivity.class);
33 | context.startActivity(starter);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/app/src/main/java/com/gaoneng/autoscrollbacklayout/ListViewDemoActivity.java:
--------------------------------------------------------------------------------
1 | package com.gaoneng.autoscrollbacklayout;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.os.Bundle;
6 | import android.support.v7.app.AppCompatActivity;
7 | import android.widget.ArrayAdapter;
8 | import android.widget.ListView;
9 |
10 | import com.gaoneng.library.AutoScrollBackLayout;
11 |
12 | import java.util.ArrayList;
13 | import java.util.List;
14 |
15 | public class ListViewDemoActivity extends AppCompatActivity {
16 |
17 | @Override
18 | protected void onCreate(Bundle savedInstanceState) {
19 | super.onCreate(savedInstanceState);
20 | setContentView(R.layout.activity_listview_layout);
21 | AutoScrollBackLayout autoScrollBackLayout = (AutoScrollBackLayout) findViewById(R.id.scroll_layout);
22 | ListView listView = (ListView) findViewById(android.R.id.list);
23 | List list = new ArrayList<>();
24 | for (int i = 0; i < 20; i++) {
25 | list.add("this is a test! in " + i);
26 | }
27 | listView.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, list));
28 | autoScrollBackLayout.bindScrollBack();
29 | }
30 |
31 | public static void start(Context context) {
32 | Intent starter = new Intent(context, ListViewDemoActivity.class);
33 | context.startActivity(starter);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/app/src/main/java/com/gaoneng/autoscrollbacklayout/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.gaoneng.autoscrollbacklayout;
2 |
3 | import android.os.Bundle;
4 | import android.support.v7.app.AppCompatActivity;
5 | import android.view.View;
6 |
7 | public class MainActivity extends AppCompatActivity {
8 |
9 | @Override
10 | protected void onCreate(Bundle savedInstanceState) {
11 | super.onCreate(savedInstanceState);
12 | setContentView(R.layout.main_layout);
13 | findViewById(R.id.btn_1).setOnClickListener(new View.OnClickListener() {
14 | @Override
15 | public void onClick(View v) {
16 | ListViewDemoActivity.start(MainActivity.this);
17 | }
18 | });
19 | findViewById(R.id.btn_2).setOnClickListener(new View.OnClickListener() {
20 | @Override
21 | public void onClick(View v) {
22 | GridViewDemoActivity.start(MainActivity.this);
23 | }
24 | });
25 | findViewById(R.id.btn_3).setOnClickListener(new View.OnClickListener() {
26 | @Override
27 | public void onClick(View v) {
28 | RecyclerViewDemoActivity.start(MainActivity.this);
29 | }
30 | });
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/app/src/main/java/com/gaoneng/autoscrollbacklayout/RecyclerViewDemoActivity.java:
--------------------------------------------------------------------------------
1 | package com.gaoneng.autoscrollbacklayout;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.os.Bundle;
6 | import android.support.v7.app.AppCompatActivity;
7 | import android.support.v7.widget.DividerItemDecoration;
8 | import android.support.v7.widget.LinearLayoutManager;
9 | import android.support.v7.widget.RecyclerView;
10 | import android.view.LayoutInflater;
11 | import android.view.View;
12 | import android.view.ViewGroup;
13 | import android.widget.TextView;
14 |
15 | import com.gaoneng.library.AutoScrollBackLayout;
16 |
17 | import java.util.ArrayList;
18 | import java.util.List;
19 |
20 | public class RecyclerViewDemoActivity extends AppCompatActivity {
21 |
22 | @Override
23 | protected void onCreate(Bundle savedInstanceState) {
24 | super.onCreate(savedInstanceState);
25 | setContentView(R.layout.activity_recycler_view_demo);
26 | AutoScrollBackLayout autoScrollBackLayout = (AutoScrollBackLayout) findViewById(R.id.scroll_layout);
27 | RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recylcerview);
28 | recyclerView.setLayoutManager(new LinearLayoutManager(this));
29 | recyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
30 | List list = new ArrayList<>();
31 | for (int i = 0; i < 20; i++) {
32 | list.add("this is a test! in " + i);
33 | }
34 | autoScrollBackLayout.bindScrollBack();
35 | recyclerView.setAdapter(new MyAdapter(this, list));
36 | }
37 |
38 | public static void start(Context context) {
39 | Intent starter = new Intent(context, RecyclerViewDemoActivity.class);
40 | context.startActivity(starter);
41 | }
42 |
43 | private class MyAdapter extends RecyclerView.Adapter {
44 | private Context context;
45 | private List list;
46 |
47 | public MyAdapter(Context context, List list) {
48 | this.context = context;
49 | this.list = list;
50 | }
51 |
52 | @Override
53 | public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
54 | return new ViewHolder(LayoutInflater.from(RecyclerViewDemoActivity.this).inflate(android.R.layout.simple_list_item_1, null));
55 | }
56 |
57 | @Override
58 | public void onBindViewHolder(ViewHolder holder, int position) {
59 | holder.bind(list.get(position));
60 | }
61 |
62 | @Override
63 | public int getItemCount() {
64 | return list.size();
65 | }
66 | }
67 |
68 | private class ViewHolder extends RecyclerView.ViewHolder {
69 | TextView textView;
70 |
71 | public ViewHolder(View itemView) {
72 | super(itemView);
73 | textView = (TextView) itemView.findViewById(android.R.id.text1);
74 | }
75 |
76 | public void bind(String s) {
77 | textView.setText(s);
78 | }
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_btn_shape.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
6 |
7 |
8 |
9 | -
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_grid_view_demo.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_listview_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_recycler_view_demo.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/main_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
18 |
19 |
28 |
29 |
38 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gaoneng102/AutoScrollBackLayout/381221d2decae9a30495a8c07424d00f5eed4b70/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gaoneng102/AutoScrollBackLayout/381221d2decae9a30495a8c07424d00f5eed4b70/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gaoneng102/AutoScrollBackLayout/381221d2decae9a30495a8c07424d00f5eed4b70/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gaoneng102/AutoScrollBackLayout/381221d2decae9a30495a8c07424d00f5eed4b70/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gaoneng102/AutoScrollBackLayout/381221d2decae9a30495a8c07424d00f5eed4b70/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gaoneng102/AutoScrollBackLayout/381221d2decae9a30495a8c07424d00f5eed4b70/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gaoneng102/AutoScrollBackLayout/381221d2decae9a30495a8c07424d00f5eed4b70/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gaoneng102/AutoScrollBackLayout/381221d2decae9a30495a8c07424d00f5eed4b70/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gaoneng102/AutoScrollBackLayout/381221d2decae9a30495a8c07424d00f5eed4b70/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gaoneng102/AutoScrollBackLayout/381221d2decae9a30495a8c07424d00f5eed4b70/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | AutoScrollBackLayout
3 | Listview
4 | Gridview
5 | Recyclerview
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/autoscrollbacklayout/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/autoscrollbacklayout/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'com.github.dcendents.android-maven'
3 | apply plugin: 'com.jfrog.bintray'
4 |
5 | // 这个version是区分library版本的,因此当我们需要更新library时记得修改这个version
6 | version = "1.1.1"
7 |
8 | android {
9 | compileSdkVersion 25
10 | buildToolsVersion "25.0.0"
11 | defaultConfig {
12 | minSdkVersion 15
13 | targetSdkVersion 25
14 | versionCode 1
15 | versionName "1.0"
16 |
17 | }
18 | buildTypes {
19 | release {
20 | minifyEnabled false
21 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
22 | }
23 | }
24 | }
25 |
26 | dependencies {
27 | compile fileTree(dir: 'libs', include: ['*.jar'])
28 | compile 'com.android.support:recyclerview-v7:25.3.1'
29 | }
30 | def siteUrl = 'https://github.com/gaoneng102/AutoScrollBackLayout' // 项目的主页
31 | def gitUrl = 'https://github.com/gaoneng102/AutoScrollBackLayout.git' // Git仓库的url
32 |
33 | group = "com.gaoneng.library" // Maven Group ID for the artifact,一般填你唯一的包名
34 |
35 | install {
36 | repositories.mavenInstaller {
37 | // This generates POM.xml with proper parameters
38 | pom {
39 | project {
40 | packaging 'aar'
41 | // Add your description here
42 | name 'Android auto scroll to top in listview or recyclerview library for app' //项目描述
43 | url siteUrl
44 | // Set your license
45 | licenses {
46 | license {
47 | name 'The Apache Software License, Version 2.0'
48 | url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
49 | }
50 | }
51 | developers {
52 | developer {
53 | id 'gaoneng102' //填写开发者基本信息
54 | name 'gaoneng'
55 | email 'gaoneng1850@gmail.com'
56 | }
57 | }
58 | scm {
59 | connection gitUrl
60 | developerConnection gitUrl
61 | url siteUrl
62 | }
63 | }
64 | }
65 | }
66 | }
67 | task sourcesJar(type: Jar) {
68 | from android.sourceSets.main.java.srcDirs
69 | classifier = 'sources'
70 | }
71 | task javadoc(type: Javadoc) {
72 | source = android.sourceSets.main.java.srcDirs
73 | classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
74 | }
75 | task javadocJar(type: Jar, dependsOn: javadoc) {
76 | classifier = 'javadoc'
77 | from javadoc.destinationDir
78 | }
79 | artifacts {
80 | archives javadocJar
81 | archives sourcesJar
82 | }
83 | Properties properties = new Properties()
84 | properties.load(project.rootProject.file('local.properties').newDataInputStream())
85 | bintray {
86 | user = properties.getProperty("bintray.user")
87 | key = properties.getProperty("bintray.apikey")
88 | configurations = ['archives']
89 | pkg {
90 | repo = "maven" //发布到Bintray的那个仓库里,默认账户有四个库,我们这里上传到maven库
91 | name = "autoscrollbacklayout" //发布到Bintray上的项目名字
92 | websiteUrl = siteUrl
93 | vcsUrl = gitUrl
94 | licenses = ["Apache-2.0"]
95 | publish = true
96 | }
97 | }
--------------------------------------------------------------------------------
/autoscrollbacklayout/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/gaoneng/Android/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 |
19 | # Uncomment this to preserve the line number information for
20 | # debugging stack traces.
21 | #-keepattributes SourceFile,LineNumberTable
22 |
23 | # If you keep the line number information, uncomment this to
24 | # hide the original source file name.
25 | #-renamesourcefileattribute SourceFile
26 |
--------------------------------------------------------------------------------
/autoscrollbacklayout/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/autoscrollbacklayout/src/main/java/com/gaoneng/library/AutoScrollBackLayout.java:
--------------------------------------------------------------------------------
1 | package com.gaoneng.library;
2 |
3 | import android.content.Context;
4 | import android.content.res.TypedArray;
5 | import android.support.annotation.AttrRes;
6 | import android.support.annotation.NonNull;
7 | import android.support.annotation.Nullable;
8 | import android.support.v7.widget.LinearLayoutManager;
9 | import android.support.v7.widget.RecyclerView;
10 | import android.util.AttributeSet;
11 | import android.util.Log;
12 | import android.view.Gravity;
13 | import android.view.View;
14 | import android.view.ViewGroup;
15 | import android.view.animation.Animation;
16 | import android.view.animation.AnimationUtils;
17 | import android.widget.AbsListView;
18 | import android.widget.FrameLayout;
19 | import android.widget.ImageView;
20 |
21 | import java.lang.reflect.Field;
22 | import java.lang.reflect.InvocationHandler;
23 | import java.lang.reflect.Method;
24 | import java.lang.reflect.Proxy;
25 | import java.util.Arrays;
26 |
27 | /**
28 | * 列表显示自动返回顶部的包装类
29 | * Created by gaoneng on 17-6-6.
30 | */
31 | public class AutoScrollBackLayout extends FrameLayout {
32 | public static final String TAG = "AutoScrollBackLayout";
33 | private static final int DELAYMILLIS = 1500;
34 | public boolean DEBUG = false;
35 | private View wrapView;
36 | private ImageView scrollBackView;
37 | private boolean mShowScroll;
38 | private Animation mShowAnimation;
39 | private Animation mHideAnimation;
40 | private int scroll_gravity;
41 | private MyScrollLitener myScrollLitener;
42 | private DismissRunable dismissRunable;
43 | private int showScrollDistance;
44 | private int arrowIcon;
45 |
46 | public AutoScrollBackLayout(@NonNull Context context) {
47 | super(context);
48 | init(context, null, 0);
49 | }
50 |
51 | public AutoScrollBackLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
52 | super(context, attrs);
53 | init(context, attrs, 0);
54 | }
55 |
56 | public AutoScrollBackLayout(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {
57 | super(context, attrs, defStyleAttr);
58 | init(context, attrs, defStyleAttr);
59 | }
60 |
61 | private void init(Context context, AttributeSet attrs, int defStyleAttr) {
62 | if (isInEditMode()) return;
63 | TypedArray attr = context.obtainStyledAttributes(attrs, R.styleable.AutoScrollBackLayout, defStyleAttr, 0);
64 | mShowScroll = attr.getBoolean(R.styleable.AutoScrollBackLayout_show_scroll, true);
65 | int showAnimResourceId = attr.getResourceId(R.styleable.AutoScrollBackLayout_show_animation, R.anim.fab_scale_up);
66 | mShowAnimation = AnimationUtils.loadAnimation(getContext(), showAnimResourceId);
67 | int hideAnimResourceId = attr.getResourceId(R.styleable.AutoScrollBackLayout_hide_animation, R.anim.fab_scale_down);
68 | mHideAnimation = AnimationUtils.loadAnimation(getContext(), hideAnimResourceId);
69 | scroll_gravity = attr.getInt(R.styleable.AutoScrollBackLayout_scroll_gravity, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL);
70 | showScrollDistance = attr.getDimensionPixelSize(R.styleable.AutoScrollBackLayout_scroll_distance, 100);
71 | arrowIcon = attr.getResourceId(R.styleable.AutoScrollBackLayout_auto_arrow_icon, R.drawable.go_top);
72 | attr.recycle();
73 | myScrollLitener = new MyScrollLitener();
74 | dismissRunable = new DismissRunable();
75 | }
76 |
77 | @Override
78 | protected void onFinishInflate() {
79 | super.onFinishInflate();
80 | attachAbsListView();
81 | attachScrollBackView();
82 | }
83 |
84 | private void attachAbsListView() {
85 | if (getChildCount() > 0) {
86 | wrapView = findTargetScrollView(this);
87 | if (DEBUG) {
88 | Log.i(TAG, "find wrapView=" + (wrapView == null ? null : wrapView.getClass().getName()));
89 | }
90 | }
91 | }
92 |
93 | private View findTargetScrollView(View view) {
94 | if (view != null) {
95 | if (view instanceof AbsListView || view instanceof RecyclerView) return view;
96 | if (view instanceof ViewGroup) {
97 | View target = null;
98 | ViewGroup viewGroup = (ViewGroup) view;
99 | for (int i = 0; i < viewGroup.getChildCount(); i++) {
100 | target = findTargetScrollView(viewGroup.getChildAt(i));
101 | }
102 | return target;
103 | }
104 | }
105 | return null;
106 | }
107 |
108 | private void attachScrollBackView() {
109 | scrollBackView = new ImageView(getContext());
110 | scrollBackView.setImageResource(arrowIcon);
111 | if (mShowScroll) {
112 | scrollBackView.setVisibility(INVISIBLE);
113 | FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
114 | params.gravity = scroll_gravity;
115 | params.bottomMargin = DensityUtils.dp2px(getContext(), 16f);
116 | scrollBackView.setOnClickListener(new PendingScrollBackListener());
117 | addView(scrollBackView, params);
118 | }
119 | }
120 |
121 | /**
122 | * 如果已经使用AbsListView.setOnScrollListener()
设置过监听,一定要在其后面调用;
123 | * 如果没有使用AbsListView.setOnScrollListener()
,就在onCreate()或者onActivityCreated()中调用即可;
124 | */
125 | public void bindScrollBack() {
126 | if (wrapView != null && scrollBackView != null && mShowScroll) {
127 | if (wrapView instanceof AbsListView) {
128 | hookScrollListenerForAbsListview();
129 | } else if (wrapView instanceof RecyclerView) {
130 | addScrollListenerForRecyclerView();
131 | }
132 | }
133 | }
134 |
135 | private void hookScrollListenerForAbsListview() {
136 | try {
137 | //通过反射获取mOnScrollListener对象
138 | Field scrollListenerField = AbsListView.class.getDeclaredField("mOnScrollListener");
139 | scrollListenerField.setAccessible(true);
140 | Object object = scrollListenerField.get(wrapView);
141 | //需要被代理的目前对象
142 | AbsListView.OnScrollListener target;
143 | if (object == null) {
144 | //如果mOnScrollListener没有设置过,就设置一个空的用来hook
145 | target = new FakeScrollLitener();
146 | } else {
147 | target = (AbsListView.OnScrollListener) object;
148 | }
149 | //InvocationHandler对象,用于添加额外的控制处理
150 | ScrollListenerInvocationHandler listenerInvocationHandler = new ScrollListenerInvocationHandler(target);
151 | //Proxy.newProxyInstance生成动态代理对象
152 | AbsListView.OnScrollListener proxy = listenerInvocationHandler.getProxy();
153 | if (DEBUG) {
154 | Log.i(TAG, "target=" + target.getClass().getName() + " ,proxy=" + proxy.getClass().getName() + ", proxied interfaces=" + Arrays.toString(proxy.getClass().getInterfaces()));
155 | }
156 | //将代理对象proxy设置到被反射的mOnScrollListener的字段中
157 | scrollListenerField.set(wrapView, proxy);
158 | } catch (Exception e) {
159 | Log.e(TAG, e.toString());
160 | }
161 | }
162 |
163 | private void addScrollListenerForRecyclerView() {
164 | ((RecyclerView) wrapView).addOnScrollListener(new RecyclerView.OnScrollListener() {
165 | @Override
166 | public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
167 | if (myScrollLitener != null)
168 | myScrollLitener.onScrollStateChanged(recyclerView, newState);
169 | }
170 |
171 | @Override
172 | public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
173 | if (myScrollLitener != null) myScrollLitener.onScroll(recyclerView, dy, 0, 0);
174 | }
175 | });
176 | }
177 |
178 | /**
179 | * 都是采取获取当前第一个可见视图的位置,来计算该视图到顶部的距离,这样计算的滚动距离都是假定每个行高是固定的情况;
180 | *
181 | * @param dy RecyclerView中onscroll()回传的dy,但是在移除或者添加数据后就不准确,这里还是作为一个备选值
182 | */
183 | private int getScrollDistance(int dy) {
184 | if (wrapView == null) return 0;
185 | if (wrapView instanceof AbsListView) {
186 | AbsListView listView = (AbsListView) wrapView;
187 | View topChild = listView.getChildAt(0);
188 | return topChild == null ? 0 : listView.getFirstVisiblePosition() * topChild.getHeight() - topChild.getTop();
189 | } else if (wrapView instanceof RecyclerView) {
190 | RecyclerView recyclerView = (RecyclerView) this.wrapView;
191 | RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
192 | if (layoutManager instanceof LinearLayoutManager) {
193 | LinearLayoutManager linearLayoutManager = (LinearLayoutManager) layoutManager;
194 | View fristChild = recyclerView.getChildAt(0);
195 | if (fristChild == null) return 0;
196 | int top = fristChild.getTop();
197 | int firstVisibleItemPosition = linearLayoutManager.findFirstVisibleItemPosition();
198 | return -top + firstVisibleItemPosition * fristChild.getHeight();
199 | }
200 | return dy;
201 | }
202 | return 0;
203 | }
204 |
205 | private void playShowAnimation() {
206 | mHideAnimation.cancel();
207 | if (scrollBackView != null) {
208 | scrollBackView.startAnimation(mShowAnimation);
209 | }
210 | }
211 |
212 | private void playHideAnimation() {
213 | mShowAnimation.cancel();
214 | if (scrollBackView != null) {
215 | scrollBackView.startAnimation(mHideAnimation);
216 | }
217 | }
218 |
219 | public boolean isHidden() {
220 | return scrollBackView != null && scrollBackView.getVisibility() == INVISIBLE;
221 | }
222 |
223 | public void show(boolean animate) {
224 | if (isHidden()) {
225 | if (animate) {
226 | playShowAnimation();
227 | }
228 | if (scrollBackView != null) {
229 | scrollBackView.setVisibility(VISIBLE);
230 | }
231 | }
232 | }
233 |
234 | public void hide(boolean animate) {
235 | if (!isHidden()) {
236 | if (animate) {
237 | playHideAnimation();
238 | }
239 | if (scrollBackView != null) {
240 | scrollBackView.setVisibility(INVISIBLE);
241 | }
242 | }
243 | }
244 |
245 | public void toggle(boolean animate) {
246 | if (isHidden()) {
247 | show(animate);
248 | } else {
249 | hide(animate);
250 | }
251 | }
252 |
253 | @Override
254 | protected void onDetachedFromWindow() {
255 | super.onDetachedFromWindow();
256 | if (dismissRunable != null) {
257 | removeCallbacks(dismissRunable);
258 | }
259 | if (scrollBackView != null) {
260 | scrollBackView.clearAnimation();
261 | }
262 | }
263 |
264 | private class PendingScrollBackListener implements OnClickListener {
265 |
266 | @Override
267 | public void onClick(final View v) {
268 | //点击返回到顶部列表,悬停3秒后消失
269 | ScrollUtil.smoothScrollListViewToTop(wrapView, new ScrollUtil.ScrollToTopListener() {
270 | @Override
271 | public void scrollComplete() {
272 | v.post(dismissRunable);
273 | }
274 | });
275 | }
276 | }
277 |
278 | private class DismissRunable implements Runnable {
279 | @Override
280 | public void run() {
281 | hide(true);
282 | }
283 | }
284 |
285 | private class MyScrollLitener {
286 | private int scrollState;
287 | private int scrollDistance;
288 |
289 | /**
290 | * RecyclerView.SCROLL_STATE_IDLE=0
291 | * AbsListView.OnScrollListener.SCROLL_STATE_IDLE=0
292 | * scrollState=0即为停止滚动
293 | */
294 | void onScrollStateChanged(View scrollview, int scrollState) {
295 | //列表滚动停止时,此时根据滚动距离判断是否需要延迟隐藏返回按钮
296 | this.scrollState = scrollState;
297 | String logTarget = scrollview.getClass().getSimpleName() + "@" + Integer.toHexString(System.identityHashCode(scrollview));
298 | if (DEBUG) {
299 | Log.d(TAG, logTarget + " scrollState=" + scrollState + ",scrollDistance=" + scrollDistance + ",showScrollDistance=" + showScrollDistance);
300 | }
301 | if (scrollState == 0) {
302 | if (DEBUG) {
303 | Log.d(TAG, logTarget + " hide()!!! scrollState=" + 0 + ",scrollDistance=" + scrollDistance + ",showScrollDistance=" + showScrollDistance);
304 | }
305 | if (dismissRunable != null) {
306 | removeCallbacks(dismissRunable);
307 | postDelayed(dismissRunable, scrollDistance >= showScrollDistance ? DELAYMILLIS : 0);
308 | }
309 | }
310 | }
311 |
312 | void onScroll(View scrollview, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
313 | if (scrollState == 0) return;
314 | scrollDistance = getScrollDistance(firstVisibleItem);
315 | String logTarget = scrollview.getClass().getSimpleName() + "@" + Integer.toHexString(System.identityHashCode(scrollview));
316 | if (scrollDistance >= showScrollDistance) {
317 | if (DEBUG) {
318 | Log.d(TAG, logTarget + " show()!!! scrollState=" + scrollState + ",scrollDistance=" + scrollDistance + ",firstVisibleItem=" + firstVisibleItem);
319 | }
320 | if (dismissRunable != null) {
321 | removeCallbacks(dismissRunable);
322 | postDelayed(dismissRunable, DELAYMILLIS);
323 | }
324 | show(true);
325 | }
326 | }
327 | }
328 |
329 | private class ScrollListenerInvocationHandler implements InvocationHandler {
330 | private AbsListView.OnScrollListener target;
331 |
332 | ScrollListenerInvocationHandler(AbsListView.OnScrollListener target) {
333 | this.target = target;
334 | }
335 |
336 | public AbsListView.OnScrollListener getProxy() {
337 | // Proxy.newProxyInstance() 第二个参数一定不能使用 target.getClass().getInterfaces()获得被代理的接口
338 | // 因为上面获得的是当前实现类本身实现的接口,不包含父类实现的接口;
339 | // 这里采取固定AbsListView.OnScrollListener接口的方式即可;
340 | return (AbsListView.OnScrollListener) Proxy.newProxyInstance(target.getClass().getClassLoader(), new Class[]{AbsListView.OnScrollListener.class}, this);
341 | }
342 |
343 | @Override
344 | public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
345 | if (DEBUG) {
346 | Log.i(TAG, "动态代理拦截 method=" + method.getName());
347 | }
348 | if (myScrollLitener != null) {
349 | if (method.getName().equals("onScroll")) {
350 | myScrollLitener.onScroll((View) args[0], (int) args[1], (int) args[2], (int) args[3]);
351 | } else if (method.getName().equals("onScrollStateChanged")) {
352 | myScrollLitener.onScrollStateChanged((View) args[0], (int) args[1]);
353 | }
354 | }
355 | return method.invoke(target, args);
356 | }
357 | }
358 |
359 | private class FakeScrollLitener implements AbsListView.OnScrollListener {
360 | @Override
361 | public void onScrollStateChanged(AbsListView view, int scrollState) {
362 |
363 | }
364 |
365 | @Override
366 | public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
367 |
368 | }
369 | }
370 | }
371 |
--------------------------------------------------------------------------------
/autoscrollbacklayout/src/main/java/com/gaoneng/library/DensityUtils.java:
--------------------------------------------------------------------------------
1 | package com.gaoneng.library;
2 |
3 | import android.content.Context;
4 | import android.util.TypedValue;
5 |
6 | /**
7 | * 常用单位转换的辅助类,涉及到单位转换的方法都在这里.
8 | */
9 | public class DensityUtils {
10 |
11 | private DensityUtils() {
12 | /* cannot be instantiated */
13 | throw new UnsupportedOperationException("cannot be instantiated");
14 | }
15 |
16 | /**
17 | * dp转px
18 | */
19 | public static int dp2px(Context context, float dpVal) {
20 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
21 | dpVal, context.getResources().getDisplayMetrics());
22 | }
23 |
24 | /**
25 | * sp转px
26 | */
27 | public static int sp2px(Context context, float spVal) {
28 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
29 | spVal, context.getResources().getDisplayMetrics());
30 | }
31 |
32 | /**
33 | * px转dp
34 | */
35 | public static float px2dp(Context context, float pxVal) {
36 | final float scale = context.getResources().getDisplayMetrics().density;
37 | return (pxVal / scale);
38 | }
39 |
40 | /**
41 | * px转sp
42 | */
43 | public static float px2sp(Context context, float pxVal) {
44 | return (pxVal / context.getResources().getDisplayMetrics().scaledDensity);
45 | }
46 |
47 | }
--------------------------------------------------------------------------------
/autoscrollbacklayout/src/main/java/com/gaoneng/library/ScrollUtil.java:
--------------------------------------------------------------------------------
1 |
2 | package com.gaoneng.library;
3 |
4 | import android.support.v7.widget.RecyclerView;
5 | import android.view.View;
6 | import android.widget.AbsListView;
7 |
8 |
9 | public class ScrollUtil {
10 |
11 |
12 | public static void smoothScrollListViewToTop(final View scrollView, ScrollToTopListener listener) {
13 | if (scrollView == null) {
14 | return;
15 | }
16 | if (scrollView instanceof AbsListView) {
17 | smoothScrollListViewToTop((AbsListView) scrollView, listener);
18 | } else if (scrollView instanceof RecyclerView) {
19 | smoothScrollListViewToTop((RecyclerView) scrollView, listener);
20 | }
21 | }
22 |
23 | public static void smoothScrollListViewToTop(final AbsListView listView, final ScrollToTopListener listener) {
24 | if (listView == null) {
25 | return;
26 | }
27 | listView.smoothScrollToPositionFromTop(0, 0);
28 | listView.postDelayed(new Runnable() {
29 | @Override
30 | public void run() {
31 | listView.setSelection(0);
32 | if (listener != null) {
33 | listener.scrollComplete();
34 | }
35 | }
36 | }, 300);
37 | }
38 |
39 | public static void smoothScrollListViewToTop(final RecyclerView recyclerView, final ScrollToTopListener listener) {
40 | if (recyclerView == null) {
41 | return;
42 | }
43 | recyclerView.smoothScrollToPosition(0);
44 | recyclerView.postDelayed(new Runnable() {
45 | @Override
46 | public void run() {
47 | if (listener != null) {
48 | listener.scrollComplete();
49 | }
50 | }
51 | }, 300);
52 | }
53 |
54 | public interface ScrollToTopListener {
55 | void scrollComplete();
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/autoscrollbacklayout/src/main/res/anim/fab_scale_down.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/autoscrollbacklayout/src/main/res/anim/fab_scale_up.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/autoscrollbacklayout/src/main/res/drawable-hdpi/go_top.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gaoneng102/AutoScrollBackLayout/381221d2decae9a30495a8c07424d00f5eed4b70/autoscrollbacklayout/src/main/res/drawable-hdpi/go_top.png
--------------------------------------------------------------------------------
/autoscrollbacklayout/src/main/res/drawable-xhdpi/go_top.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gaoneng102/AutoScrollBackLayout/381221d2decae9a30495a8c07424d00f5eed4b70/autoscrollbacklayout/src/main/res/drawable-xhdpi/go_top.png
--------------------------------------------------------------------------------
/autoscrollbacklayout/src/main/res/drawable-xxhdpi/go_top.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gaoneng102/AutoScrollBackLayout/381221d2decae9a30495a8c07424d00f5eed4b70/autoscrollbacklayout/src/main/res/drawable-xxhdpi/go_top.png
--------------------------------------------------------------------------------
/autoscrollbacklayout/src/main/res/drawable-xxxhdpi/go_top.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gaoneng102/AutoScrollBackLayout/381221d2decae9a30495a8c07424d00f5eed4b70/autoscrollbacklayout/src/main/res/drawable-xxxhdpi/go_top.png
--------------------------------------------------------------------------------
/autoscrollbacklayout/src/main/res/values/attrs.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 |
35 |
36 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/autoscrollbacklayout/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Library
3 |
4 |
--------------------------------------------------------------------------------
/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 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:2.3.3'
9 | classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.6'
10 | classpath 'com.github.dcendents:android-maven-gradle-plugin:1.4.1'
11 | // NOTE: Do not place your application dependencies here; they belong
12 | // in the individual module build.gradle files
13 | }
14 | }
15 |
16 | allprojects {
17 | repositories {
18 | jcenter()
19 | }
20 | }
21 |
22 | task clean(type: Delete) {
23 | delete rootProject.buildDir
24 | }
25 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gaoneng102/AutoScrollBackLayout/381221d2decae9a30495a8c07424d00f5eed4b70/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Thu Jun 22 11:20:06 CST 2017
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-3.3-all.zip
7 |
--------------------------------------------------------------------------------
/preview.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gaoneng102/AutoScrollBackLayout/381221d2decae9a30495a8c07424d00f5eed4b70/preview.gif
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':autoscrollbacklayout'
2 |
--------------------------------------------------------------------------------