├── .gitignore
├── 01github上的项目展示.gif
├── 02实际项目展示.gif
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── tandygong
│ │ └── gzx
│ │ └── nestscroll
│ │ └── ApplicationTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── tandygong
│ │ │ └── gzx
│ │ │ └── nestscroll
│ │ │ ├── activitys
│ │ │ ├── MainActivity.java
│ │ │ └── NestScrollWithScrollViewActivity.java
│ │ │ ├── adapters
│ │ │ ├── SchoolDeatilAdapter.java
│ │ │ └── SubTitleMenuListAdapter.java
│ │ │ ├── enums
│ │ │ ├── AnimStyle.java
│ │ │ └── Page.java
│ │ │ ├── fragments
│ │ │ ├── ContainerSchoolInfoFragment.java
│ │ │ ├── TabProjectInfoFragment.java
│ │ │ └── TabSchoolInfoFragment.java
│ │ │ ├── utils
│ │ │ ├── ActivityUtils.java
│ │ │ └── Constants.java
│ │ │ └── views
│ │ │ ├── AppWebView.java
│ │ │ ├── AppWebViewClient.java
│ │ │ ├── CustomDrawerLayout.java
│ │ │ ├── CustomerNestedScrollView.java
│ │ │ ├── ProgressBarWebView.java
│ │ │ ├── PullToRefreshLayout.java
│ │ │ └── Pullable.java
│ └── res
│ │ ├── anim
│ │ ├── reverse_anim.xml
│ │ ├── rotating.xml
│ │ ├── slide_in_from_bottom.xml
│ │ ├── slide_in_from_top.xml
│ │ ├── slide_out_to_bottom.xml
│ │ └── slide_out_to_top.xml
│ │ ├── drawable
│ │ ├── bg_black_radius_5.xml
│ │ └── progressbar.xml
│ │ ├── layout
│ │ ├── activity_main.xml
│ │ ├── activity_nest_scroll_with_scroll_view.xml
│ │ ├── fragment_project_info.xml
│ │ ├── fragment_tab_school_info.xml
│ │ ├── item_tips_titles.xml
│ │ ├── layout_fragment_container_school_info.xml
│ │ ├── load_more.xml
│ │ └── refresh_head.xml
│ │ ├── mipmap-hdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-mdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xhdpi
│ │ ├── guanliqi_back.png
│ │ ├── guanliqi_xuanxiao.png
│ │ ├── ic_launcher.png
│ │ ├── load_failed.png
│ │ ├── load_succeed.png
│ │ ├── loading.png
│ │ ├── pull_icon_big.png
│ │ ├── pullup_icon_big.png
│ │ ├── refresh_failed.png
│ │ ├── refresh_succeed.png
│ │ ├── refreshing.png
│ │ ├── school_location.png
│ │ ├── school_ranking.png
│ │ ├── school_statistics.png
│ │ ├── school_weather.png
│ │ └── strategy_list.png
│ │ ├── mipmap-xxhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxxhdpi
│ │ └── ic_launcher.png
│ │ ├── values-w820dp
│ │ └── dimens.xml
│ │ └── values
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── refs.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── tandygong
│ └── gzx
│ └── nestscroll
│ └── ExampleUnitTest.java
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | #idea
2 | .idea/
3 | *.iml
4 |
5 | # Built application files
6 | *.apk
7 | *.ap_
8 |
9 | # Files for the Dalvik VM
10 | *.dex
11 |
12 | # Java class files
13 | *.class
14 |
15 | # Generated files
16 | bin/
17 | gen/
18 |
19 | # Gradle files
20 | .gradle/
21 | build/
22 | */build/
23 |
24 | # Local configuration file (sdk path, etc)
25 | local.properties
26 |
27 | # Proguard folder generated by Eclipse
28 | proguard/
29 |
30 | # Log Files
31 | *.log
32 |
33 | /captures
34 |
--------------------------------------------------------------------------------
/01github上的项目展示.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tandygong/NestScroll/c28e8fd7a5700a896f7c8c7a9ff746ee418259d4/01github上的项目展示.gif
--------------------------------------------------------------------------------
/02实际项目展示.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tandygong/NestScroll/c28e8fd7a5700a896f7c8c7a9ff746ee418259d4/02实际项目展示.gif
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | #NestScroll
2 | ##这是从我做过的一个项目里面的一个页面
3 |
4 | ###使用了NestScrollView,PullToRefreshLayout,WebView多层嵌套
5 | #### 如有建议和问题请发送邮件至531493235@qq.com
6 |
7 |
8 | ####原项目效果
9 | 
10 |
11 | ####gitHub效果展示
12 | 
13 |
14 |
15 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 23
5 | buildToolsVersion "23.0.1"
6 |
7 | defaultConfig {
8 | applicationId "com.tandygong.gzx.nestscroll"
9 | minSdkVersion 16
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(include: ['*.jar'], dir: 'libs')
24 | testCompile 'junit:junit:4.12'
25 | compile 'com.android.support:appcompat-v7:23.1.1'
26 | compile 'com.android.support:design:23.1.1'
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 D:\java\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 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/tandygong/gzx/nestscroll/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.tandygong.gzx.nestscroll;
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 |
4 |
5 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tandygong/gzx/nestscroll/activitys/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.tandygong.gzx.nestscroll.activitys;
2 |
3 | import android.os.Bundle;
4 | import android.support.v7.app.AppCompatActivity;
5 | import android.view.View;
6 | import android.widget.Button;
7 | import android.widget.Toast;
8 |
9 | import com.tandygong.gzx.nestscroll.R;
10 | import com.tandygong.gzx.nestscroll.utils.ActivityUtils;
11 |
12 | /**
13 | * Created by usb on 2016/4/13.
14 | */
15 | public class MainActivity extends AppCompatActivity implements View.OnClickListener {
16 |
17 | private Button btnScrollView;
18 | private Button btnRecycleView;
19 |
20 | @Override
21 | protected void onCreate(Bundle savedInstanceState) {
22 | super.onCreate(savedInstanceState);
23 | setContentView(R.layout.activity_main);
24 | findIds();
25 | initData();
26 | setListeners();
27 | }
28 |
29 |
30 | private void findIds() {
31 | btnScrollView = (Button) findViewById(R.id.btn_use_scrollview);
32 | btnRecycleView = (Button) findViewById(R.id.btn_use_recycle_view);
33 | }
34 |
35 | private void initData() {
36 |
37 | }
38 |
39 | private void setListeners() {
40 | btnScrollView.setOnClickListener(this);
41 | btnRecycleView.setOnClickListener(this);
42 | }
43 |
44 | @Override
45 | public void onClick(View v) {
46 | switch (v.getId()) {
47 | case R.id.btn_use_scrollview:
48 | String url = "http://p3.qhimg.com/t01d0b5e6e40b60df20.png";
49 | ActivityUtils.toSchoolDetailActivityForResult(this, true, "北京大学", "BeijingUniversity", url, 100, 1, true);
50 | break;
51 | case R.id.btn_use_recycle_view:
52 | Toast.makeText(this, "正在开发", Toast.LENGTH_SHORT).show();
53 | break;
54 | }
55 |
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tandygong/gzx/nestscroll/activitys/NestScrollWithScrollViewActivity.java:
--------------------------------------------------------------------------------
1 | package com.tandygong.gzx.nestscroll.activitys;
2 |
3 | import android.os.Bundle;
4 | import android.support.design.widget.TabLayout;
5 | import android.support.v4.view.ViewPager;
6 | import android.support.v4.widget.DrawerLayout;
7 | import android.support.v7.app.AppCompatActivity;
8 | import android.view.View;
9 | import android.widget.ImageView;
10 | import android.widget.LinearLayout;
11 | import android.widget.ListView;
12 | import android.widget.RelativeLayout;
13 | import android.widget.TextView;
14 |
15 | import com.tandygong.gzx.nestscroll.R;
16 | import com.tandygong.gzx.nestscroll.adapters.SchoolDeatilAdapter;
17 |
18 |
19 | public class NestScrollWithScrollViewActivity extends AppCompatActivity implements View.OnClickListener, ViewPager.OnPageChangeListener {
20 | private TabLayout mTabLayout;
21 | private ViewPager mViewPager;
22 | private boolean isApply;
23 | private String englishName;
24 | private String chineseName;
25 | private String imgUrl;
26 | private int schoolId;
27 | private RelativeLayout rlShowSlideMenu;
28 | private ListView lvMenu;
29 | private DrawerLayout drawerLayout;
30 | private TextView tvContentNum;
31 | private LinearLayout llSearchSchool;
32 | private View applyBtn;
33 | private TextView tSchool;
34 | private View backBtn;
35 |
36 | @Override
37 | protected void onCreate(Bundle savedInstanceState) {
38 | super.onCreate(savedInstanceState);
39 | getExtraData();
40 | setContentView(R.layout.activity_nest_scroll_with_scroll_view);
41 | findViews();
42 | setData();
43 | setListeners();
44 | }
45 |
46 | public void getExtraData() {
47 | Bundle extras = getIntent().getExtras();
48 | if (extras == null) {
49 | return;
50 | }
51 | isApply = extras.getBoolean("isApply", false);
52 | englishName = extras.getString("englishName");
53 | chineseName = extras.getString("chineseName");
54 | imgUrl = extras.getString("imgUrl");
55 | schoolId = extras.getInt("schoolId");
56 | }
57 |
58 | private void findViews() {
59 | mTabLayout = (TabLayout) findViewById(R.id.tabs);
60 | mViewPager = (ViewPager) findViewById(R.id.vp_main);
61 | ImageView tvToolBarBg = (ImageView) findViewById(R.id.toobar_bg);
62 | TextView tvNameEn = (TextView) findViewById(R.id.tv_name_english);
63 | TextView tvNameCn = (TextView) findViewById(R.id.tv_name_chinese);
64 | backBtn = findViewById(R.id.toobar_back);
65 | applyBtn = findViewById(R.id.toobar_apply);
66 |
67 | rlShowSlideMenu = (RelativeLayout) findViewById(R.id.rl_show_slide_menu);
68 | lvMenu = (ListView) findViewById(R.id.lv_menuList);
69 | tvContentNum = (TextView) findViewById(R.id.tv_contentNum);
70 | drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
71 |
72 |
73 | //ImageLoader.getInstance().displayImage(imgUrl, tvToolBarBg);
74 | tvNameCn.setText(chineseName);
75 | tvNameEn.setText(englishName);
76 |
77 |
78 | }
79 |
80 | private void setData() {
81 | mViewPager.setAdapter(new SchoolDeatilAdapter(getSupportFragmentManager(), schoolId));
82 | drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
83 | rlShowSlideMenu.setVisibility(View.INVISIBLE);
84 | mTabLayout.setupWithViewPager(mViewPager);
85 | }
86 |
87 | private void setListeners() {
88 | mViewPager.addOnPageChangeListener(this);
89 | backBtn.setOnClickListener(this);
90 | applyBtn.setOnClickListener(this);
91 | }
92 |
93 | public ListView getLvMenu() {
94 | return lvMenu;
95 | }
96 |
97 | public DrawerLayout getDrawerLayout() {
98 | return drawerLayout;
99 | }
100 |
101 | public TextView getTvContentNum() {
102 | return tvContentNum;
103 | }
104 |
105 | public RelativeLayout getRlShowSlideMenu() {
106 | return rlShowSlideMenu;
107 | }
108 |
109 |
110 | @Override
111 | public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
112 |
113 | }
114 |
115 | @Override
116 | public void onPageSelected(int position) {//当切换tab时设置悬浮按钮显示/隐藏,DrawLayout锁定/解锁
117 | if (position == 0) {
118 | rlShowSlideMenu.setVisibility(View.INVISIBLE);
119 | drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
120 | } else {
121 | rlShowSlideMenu.setVisibility(View.VISIBLE);
122 | drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
123 | }
124 | }
125 |
126 | @Override
127 | public void onPageScrollStateChanged(int state) {
128 |
129 | }
130 |
131 | @Override
132 | public void onClick(View v) {
133 | switch (v.getId()) {
134 | case R.id.toobar_back:
135 | finish();
136 | break;
137 | case R.id.toobar_apply:
138 | break;
139 | }
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tandygong/gzx/nestscroll/adapters/SchoolDeatilAdapter.java:
--------------------------------------------------------------------------------
1 | package com.tandygong.gzx.nestscroll.adapters;
2 |
3 | import android.os.Bundle;
4 | import android.support.v4.app.Fragment;
5 | import android.support.v4.app.FragmentManager;
6 | import android.support.v4.app.FragmentPagerAdapter;
7 |
8 | import com.tandygong.gzx.nestscroll.fragments.TabProjectInfoFragment;
9 | import com.tandygong.gzx.nestscroll.fragments.TabSchoolInfoFragment;
10 |
11 | /**
12 | * viewPager的adapter,含有两个fragment
13 | */
14 | public class SchoolDeatilAdapter extends FragmentPagerAdapter {
15 | private int schoolId;
16 |
17 | public SchoolDeatilAdapter(FragmentManager fm, int schoolId) {
18 | super(fm);
19 | this.schoolId = schoolId;
20 | }
21 |
22 |
23 | @Override
24 | public Fragment getItem(int position) {
25 | if (position == 1) {
26 | TabSchoolInfoFragment tabSchoolInfoFragment = new TabSchoolInfoFragment();//右侧的学校信息fragment
27 | Bundle bundle = new Bundle();
28 | bundle.putInt("schoolId", schoolId);
29 | tabSchoolInfoFragment.setArguments(bundle);
30 | return tabSchoolInfoFragment;
31 | } else {
32 | TabProjectInfoFragment tabProjectInfoFragment = new TabProjectInfoFragment();//左侧的项目信息fragment
33 | return tabProjectInfoFragment;
34 | }
35 | }
36 |
37 | @Override
38 | public int getCount() {
39 | return 2;
40 | }
41 |
42 | @Override
43 | public CharSequence getPageTitle(int position) {
44 | return position == 0 ? "项目信息" : "学校信息";
45 | }
46 |
47 | /* @Override
48 | public long getItemId(int position) {
49 | int hashCode = dataList.get(position).hashCode();
50 | return hashCode;
51 | }*/
52 | }
53 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tandygong/gzx/nestscroll/adapters/SubTitleMenuListAdapter.java:
--------------------------------------------------------------------------------
1 | package com.tandygong.gzx.nestscroll.adapters;
2 |
3 | import android.content.Context;
4 | import android.graphics.Color;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 | import android.widget.BaseAdapter;
8 | import android.widget.TextView;
9 |
10 |
11 | import com.tandygong.gzx.nestscroll.R;
12 |
13 | import java.util.ArrayList;
14 |
15 | /**
16 | * Created by gzx on 2016/3/11 at 20:42.
17 | */
18 | public class SubTitleMenuListAdapter extends BaseAdapter {
19 | private int selectPos;
20 | private ArrayList dataList;
21 | private Context context;
22 |
23 | public SubTitleMenuListAdapter(Context context, ArrayList dataList) {
24 | this.context = context;
25 | this.dataList = dataList;
26 | }
27 |
28 | public int getSelectPos() {
29 | return selectPos;
30 | }
31 |
32 | public void setSelectPos(int selectPos) {
33 | this.selectPos = selectPos;
34 | notifyDataSetChanged();
35 | }
36 |
37 | @Override
38 | public int getCount() {
39 | return dataList == null ? 0 : dataList.size();
40 | }
41 |
42 | @Override
43 | public Object getItem(int position) {
44 | return dataList.get(position);
45 | }
46 |
47 | @Override
48 | public long getItemId(int position) {
49 | return position;
50 | }
51 |
52 | @Override
53 | public View getView(int position, View convertView, ViewGroup parent) {
54 | ViewHolder holder;
55 | if (convertView == null) {
56 | holder = new ViewHolder();
57 | convertView = View.inflate(context, R.layout.item_tips_titles, null);
58 | holder.tvTitle = (TextView) convertView.findViewById(R.id.tv_title);
59 | convertView.setTag(holder);
60 | } else {
61 | holder = (ViewHolder) convertView.getTag();
62 | }
63 | holder.tvTitle.setText(dataList.get(position));
64 | if (position == selectPos) {
65 | holder.tvTitle.setTextColor(Color.parseColor("#ff8570"));
66 | holder.tvTitle.setBackgroundColor(Color.parseColor("#f6f6f6"));
67 | } else {
68 | holder.tvTitle.setTextColor(Color.parseColor("#222222"));
69 | holder.tvTitle.setBackgroundColor(Color.parseColor("#ffffff"));
70 | }
71 |
72 | return convertView;
73 | }
74 |
75 | class ViewHolder {
76 | TextView tvTitle;
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tandygong/gzx/nestscroll/enums/AnimStyle.java:
--------------------------------------------------------------------------------
1 | package com.tandygong.gzx.nestscroll.enums;
2 |
3 | import java.io.Serializable;
4 |
5 | /**
6 | * 切换内容时的动画
7 | * Created by gzx on 2016/3/17 at 15:01.
8 | */
9 | public enum AnimStyle implements Serializable {
10 | /**
11 | * 从上往下移动
12 | */
13 | TOP_TO_BOTTOM,
14 | /**
15 | * 从底部往上滑动
16 | */
17 | BOTTOM_TO_TOP,
18 | /**
19 | * 默认加载,无动画
20 | */
21 | DEFAULT_NO_ANIM
22 | }
23 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tandygong/gzx/nestscroll/enums/Page.java:
--------------------------------------------------------------------------------
1 | package com.tandygong.gzx.nestscroll.enums;
2 |
3 | /**
4 | * Created by gzx on 2016/3/17 at 14:56.
5 | */
6 | public enum Page {
7 | /**
8 | * 第一页
9 | */FirstPage,
10 | /**
11 | * 最后一页
12 | */LastPage,
13 | /**
14 | * 中间页
15 | */CenterPage
16 | }
17 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tandygong/gzx/nestscroll/fragments/ContainerSchoolInfoFragment.java:
--------------------------------------------------------------------------------
1 | package com.tandygong.gzx.nestscroll.fragments;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.os.Bundle;
6 | import android.support.annotation.Nullable;
7 | import android.support.v4.app.Fragment;
8 | import android.support.v4.widget.NestedScrollView;
9 | import android.util.Log;
10 | import android.view.LayoutInflater;
11 | import android.view.MotionEvent;
12 | import android.view.View;
13 | import android.view.ViewGroup;
14 | import android.widget.LinearLayout;
15 | import android.widget.TextView;
16 |
17 | import com.tandygong.gzx.nestscroll.R;
18 | import com.tandygong.gzx.nestscroll.enums.AnimStyle;
19 | import com.tandygong.gzx.nestscroll.enums.Page;
20 | import com.tandygong.gzx.nestscroll.utils.Constants;
21 | import com.tandygong.gzx.nestscroll.views.CustomerNestedScrollView;
22 | import com.tandygong.gzx.nestscroll.views.ProgressBarWebView;
23 | import com.tandygong.gzx.nestscroll.views.PullToRefreshLayout;
24 |
25 |
26 | /**
27 | * 学校信息
28 | * Created by gzx on 2016/3/25 at 11:05.
29 | */
30 | public class ContainerSchoolInfoFragment extends Fragment implements View.OnTouchListener, NestedScrollView.OnScrollChangeListener, PullToRefreshLayout.OnRefreshListener, View.OnLayoutChangeListener {
31 | private CustomerNestedScrollView mScrollView;
32 | private ProgressBarWebView webView;
33 | private String pageUrl;
34 | private int pageId;
35 | private Page currPage;//当前页的标识 第一页/最后一页/中间页
36 | private PullToRefreshLayout pulltoRefresh;
37 | private Intent receiverIntent;
38 | private TextView tvRealTitle;
39 | private TextView tvFakeTitle;
40 | private int[] locationReal = new int[2];//记录真标题栏在窗口位置的数组
41 | private int[] locationFake = new int[2];//记录假标题栏在窗口位置的数组
42 | private String subTitle;
43 | private LinearLayout llItemWhole;
44 |
45 | @Nullable
46 | @Override
47 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
48 | receiverIntent = new Intent();
49 | receiverIntent.setAction(Constants.ACTION_REPLACE_FRAGMENT_SCHOOL_INFO);
50 |
51 | View view = inflater.inflate(R.layout.layout_fragment_container_school_info, null);
52 | getBundleData();
53 | findViewIds(view);
54 | setListeners();
55 | initData();
56 | return view;
57 | }
58 |
59 | private void getBundleData() {
60 | Bundle extras = getArguments();
61 | if (extras != null) {//从TabSchoolInfoFragment获取数据
62 | pageUrl = extras.getString("PageUrl");
63 | subTitle = extras.getString("subTitle");
64 | int totalCount = extras.getInt("TotalCount");
65 | pageId = extras.getInt("PageId");
66 |
67 |
68 | //如果页码(pageid 从0开始)等于0,当前页标识=FirstPage
69 | //如果页码和(总页数-1)相等,当前页标识=LastPage
70 | //其它值 ,当前页标识=CenterPage
71 | currPage = pageId == 0 ? Page.FirstPage : pageId == totalCount - 1 ? Page.LastPage : Page.CenterPage;
72 |
73 | Log.e("pageUrl", pageUrl);
74 | }
75 |
76 |
77 | }
78 |
79 | private void findViewIds(View view) {
80 | pulltoRefresh = (PullToRefreshLayout) view.findViewById(R.id.ptf_detail);
81 | mScrollView = (CustomerNestedScrollView) view.findViewById(R.id.nestScrollView);//实现PullAble接扣得NestScrollView
82 | webView = (ProgressBarWebView) view.findViewById(R.id.webView);//包含在PUllToRefreshLayout的webView
83 | tvRealTitle = (TextView) view.findViewById(R.id.tv_real_title);//真标题栏
84 | tvFakeTitle = (TextView) view.findViewById(R.id.tv_fake_title);//浮在CoordinatorLayout下面的假标题栏
85 | View llHead = view.findViewById(R.id.ll_head);
86 |
87 | //这个线性布局包裹整个内容,因为在PullToRefreshLayout中,若子view(除了include的头尾布局)
88 | // 的高度小于PullToRefreshLayout的高度时,就会出现不能上拉的情况,所以需要在后面设置最小高度
89 | llItemWhole = (LinearLayout) view.findViewById(R.id.ll_item_whole);
90 |
91 |
92 | switch (currPage) {//根据Page标志设置可上拉/下拉
93 | case FirstPage:
94 | mScrollView.setCanRefresh(false);
95 | llHead.setVisibility(View.VISIBLE);
96 | break;
97 | case CenterPage:
98 | break;
99 | case LastPage:
100 | mScrollView.setCanLoadMore(false);
101 | break;
102 | }
103 |
104 | }
105 |
106 |
107 | private void setListeners() {
108 | pulltoRefresh.setOnRefreshListener(this);
109 | mScrollView.setOnScrollChangeListener(this);
110 | mScrollView.setOnTouchListener(this);
111 | mScrollView.addOnLayoutChangeListener(this);
112 | }
113 |
114 | /**
115 | * 计算真假标题滑动时在窗口位置,当他们相遇时分别做隐藏和显示动作
116 | */
117 | private void onTitleMeet() {
118 | tvRealTitle.getLocationOnScreen(locationReal);
119 | tvFakeTitle.getLocationOnScreen(locationFake);
120 | if (locationReal[1] <= locationFake[1]) {
121 | if (tvFakeTitle.getVisibility() != View.VISIBLE)
122 | tvFakeTitle.setVisibility(View.VISIBLE);
123 | } else {
124 | if (tvFakeTitle.getVisibility() == View.VISIBLE)
125 | tvFakeTitle.setVisibility(View.INVISIBLE);
126 | }
127 | }
128 |
129 | private void initData() {
130 | Context applicationContext = getContext().getApplicationContext();
131 | llItemWhole.setMinimumHeight(applicationContext.getResources().getDisplayMetrics().heightPixels);
132 | setRefreshLabel();
133 | tvFakeTitle.setText(subTitle);
134 | tvRealTitle.setText(subTitle);
135 | webView.setWebViewMargin(0);
136 | webView.loadUrl(pageUrl);
137 |
138 | }
139 |
140 | /**
141 | * 设置上拉下拉提示语
142 | */
143 | private void setRefreshLabel() {
144 | String loadMoreStr = "加载下一章内容";
145 | String refreshStr = "加载上一章内容";
146 |
147 | pulltoRefresh.setLoadMoreWord(loadMoreStr, loadMoreStr, loadMoreStr, loadMoreStr, "加载失败");
148 | pulltoRefresh.setRefreshWords(refreshStr, refreshStr, refreshStr, refreshStr, "加载失败");
149 | }
150 |
151 | @Override
152 | public void onScrollChange(NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
153 | onTitleMeet();
154 | }
155 |
156 | @Override
157 | public boolean onTouch(View v, MotionEvent event) {
158 | onTitleMeet();
159 | return false;
160 | }
161 |
162 |
163 | @Override
164 | public void onRefresh(PullToRefreshLayout pullToRefreshLayout) {//下拉PUllToRefreshLayout布局的操作
165 | pulltoRefresh.refreshFinish(PullToRefreshLayout.SUCCEED);
166 | receiverIntent.putExtra("animStyle", AnimStyle.TOP_TO_BOTTOM);
167 | getActivity().sendBroadcast(receiverIntent);//发送广播,通知TabSchoolFragment切换内容
168 | }
169 |
170 | @Override
171 | public void onLoadMore(PullToRefreshLayout pullToRefreshLayout) {
172 | pulltoRefresh.loadmoreFinish(PullToRefreshLayout.SUCCEED);
173 | receiverIntent.putExtra("animStyle", AnimStyle.BOTTOM_TO_TOP);
174 | getActivity().sendBroadcast(receiverIntent);
175 | }
176 |
177 | @Override
178 | public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
179 | onTitleMeet();
180 | }
181 |
182 |
183 | }
184 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tandygong/gzx/nestscroll/fragments/TabProjectInfoFragment.java:
--------------------------------------------------------------------------------
1 | package com.tandygong.gzx.nestscroll.fragments;
2 |
3 | import android.os.Bundle;
4 | import android.support.annotation.Nullable;
5 | import android.support.v4.app.Fragment;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 |
10 | import com.tandygong.gzx.nestscroll.R;
11 |
12 |
13 | /**
14 | * Created by gengxin on 2015/12/16.
15 | */
16 | public class TabProjectInfoFragment extends Fragment {
17 |
18 | @Nullable
19 | @Override
20 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
21 | View view = inflater.inflate(R.layout.fragment_project_info, null);
22 | return view;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tandygong/gzx/nestscroll/fragments/TabSchoolInfoFragment.java:
--------------------------------------------------------------------------------
1 | package com.tandygong.gzx.nestscroll.fragments;
2 |
3 | import android.content.BroadcastReceiver;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.content.IntentFilter;
7 | import android.os.Bundle;
8 | import android.support.annotation.NonNull;
9 | import android.support.annotation.Nullable;
10 | import android.support.v4.app.Fragment;
11 | import android.support.v4.app.FragmentTransaction;
12 | import android.support.v4.widget.DrawerLayout;
13 | import android.util.Log;
14 | import android.view.Gravity;
15 | import android.view.LayoutInflater;
16 | import android.view.View;
17 | import android.view.ViewGroup;
18 | import android.widget.AdapterView;
19 | import android.widget.ListView;
20 | import android.widget.RelativeLayout;
21 | import android.widget.TextView;
22 |
23 | import com.tandygong.gzx.nestscroll.R;
24 | import com.tandygong.gzx.nestscroll.activitys.NestScrollWithScrollViewActivity;
25 | import com.tandygong.gzx.nestscroll.adapters.SubTitleMenuListAdapter;
26 | import com.tandygong.gzx.nestscroll.enums.AnimStyle;
27 | import com.tandygong.gzx.nestscroll.utils.Constants;
28 |
29 | import java.util.ArrayList;
30 |
31 | /**
32 | * Created by gzx on 2016/2/14.
33 | */
34 | public class TabSchoolInfoFragment extends Fragment implements View.OnClickListener, AdapterView.OnItemClickListener, DrawerLayout.DrawerListener {
35 |
36 |
37 | private ArrayList subTitles;
38 | private ArrayList subUrls;
39 | private int destPageId;
40 | private AnimStyle animStyle;
41 | private int schoolId;
42 | private ListView lvContent;
43 | private DrawerLayout drawerLayout;
44 | private RelativeLayout rlShowSlideMenu;
45 | private TextView tvContentNum;
46 | private BroadcastReceiver receiver;
47 |
48 | @Nullable
49 | @Override
50 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
51 | View view = inflater.inflate(R.layout.fragment_tab_school_info, null);
52 | getExtraData();
53 | findViewIds(view);
54 | setListeners();
55 | initData();
56 | return view;
57 | }
58 |
59 | private void getExtraData() {
60 | Bundle arguments = getArguments();
61 | if (arguments != null) {
62 | schoolId = arguments.getInt("schoolId");
63 | }
64 | }
65 |
66 |
67 | private void findViewIds(View view) {
68 |
69 | }
70 |
71 | private void setListeners() {
72 | //注册广播接收者,当收到广播时的操作
73 | receiver = new BroadcastReceiver() {
74 | @Override
75 | public void onReceive(Context context, Intent intent) {
76 | Bundle extras = intent.getExtras();
77 | if (extras != null) {
78 | animStyle = (AnimStyle) extras.getSerializable("animStyle");
79 | destPageId += animStyle == AnimStyle.TOP_TO_BOTTOM ? -1 : 1;
80 | }
81 | switchFragment(destPageId, animStyle);//切换内容
82 | }
83 | };
84 | getContext().registerReceiver(receiver, new IntentFilter(Constants.ACTION_REPLACE_FRAGMENT_SCHOOL_INFO));
85 | }
86 |
87 | private void initData() {
88 | subTitles = new ArrayList<>();
89 | subUrls = new ArrayList<>();
90 | getViewFromActivity();
91 | setTestData();//设置测试数据
92 | initSlideMenu();
93 | switchFragment(destPageId, AnimStyle.DEFAULT_NO_ANIM);//首次加载没有切换动画
94 | }
95 |
96 | private void getViewFromActivity() {
97 | NestScrollWithScrollViewActivity activity = (NestScrollWithScrollViewActivity) getActivity();
98 | lvContent = activity.getLvMenu();
99 | drawerLayout = activity.getDrawerLayout();
100 | rlShowSlideMenu = activity.getRlShowSlideMenu();
101 | tvContentNum = activity.getTvContentNum();
102 |
103 | drawerLayout.setDrawerListener(this);
104 | rlShowSlideMenu.setOnClickListener(this);
105 | }
106 |
107 |
108 | /**
109 | * 设置DrawerLayout右侧的菜单
110 | */
111 | private void initSlideMenu() {
112 | lvContent.setAdapter(new SubTitleMenuListAdapter(getActivity(), subTitles));
113 | lvContent.setOnItemClickListener(this);
114 | }
115 |
116 |
117 | /**
118 | * 根据广播接收的"要求"来定制要显示的fragment
119 | *
120 | * @param destPageId 将要切换内容的页码
121 | * @param animStyle 切换动画效果
122 | */
123 | private void switchFragment(int destPageId, AnimStyle animStyle) {
124 | if (destPageId >= subUrls.size() || destPageId < 0) {
125 | return;
126 | }
127 | ContainerSchoolInfoFragment fragment = getSchoolInfoContainerFragment(destPageId);
128 | FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
129 |
130 | switch (animStyle) {
131 | case TOP_TO_BOTTOM:
132 | ft.setCustomAnimations(R.anim.slide_in_from_top, R.anim.slide_out_to_bottom);
133 | break;
134 | case BOTTOM_TO_TOP:
135 | ft.setCustomAnimations(R.anim.slide_in_from_bottom, R.anim.slide_out_to_top);
136 | break;
137 | case DEFAULT_NO_ANIM:
138 | break;
139 | }
140 | try {
141 | ft.replace(R.id.fl_container, fragment);
142 | ft.commitAllowingStateLoss();
143 | tvContentNum.setText(destPageId + 1 + "/" + subUrls.size());
144 | } catch (Exception e) {
145 | Log.e("exception", e.getMessage());//捕捉页面还没加载就退出activity引起的异常
146 | }
147 | }
148 |
149 | @NonNull
150 | private ContainerSchoolInfoFragment getSchoolInfoContainerFragment(int destPageId) {
151 | ContainerSchoolInfoFragment fragment = new ContainerSchoolInfoFragment();
152 | Bundle bundle = new Bundle();
153 | bundle.putString("PageUrl", subUrls.get(destPageId));
154 | bundle.putInt("TotalCount", subUrls.size());
155 | bundle.putString("subTitle", subTitles.get(destPageId));
156 | bundle.putInt("PageId", destPageId);
157 | fragment.setArguments(bundle);
158 | return fragment;
159 | }
160 |
161 | @Override
162 | public void onDestroy() {
163 | getContext().unregisterReceiver(receiver);
164 | super.onDestroy();
165 | }
166 |
167 | @Override
168 | public void onClick(View v) {
169 | switch (v.getId()) {
170 | case R.id.rl_show_slide_menu:
171 | drawerLayout.openDrawer(Gravity.RIGHT);
172 | break;
173 | }
174 | }
175 |
176 | @Override
177 | public void onItemClick(AdapterView> parent, View view, int position, long id) {
178 | SubTitleMenuListAdapter adapter = (SubTitleMenuListAdapter) lvContent.getAdapter();
179 | if (position != adapter.getSelectPos()) {
180 | adapter.setSelectPos(position);
181 | drawerLayout.closeDrawer(Gravity.RIGHT);
182 | destPageId = position;
183 | switchFragment(destPageId, AnimStyle.DEFAULT_NO_ANIM);
184 | }
185 | }
186 |
187 | @Override
188 | public void onDrawerSlide(View drawerView, float slideOffset) {
189 | rlShowSlideMenu.setAlpha(1f - slideOffset);
190 | }
191 |
192 | @Override
193 | public void onDrawerOpened(View drawerView) {
194 | SubTitleMenuListAdapter adapter = (SubTitleMenuListAdapter) lvContent.getAdapter();
195 | if (adapter == null) {
196 | return;
197 | }
198 | adapter.setSelectPos(destPageId);
199 | lvContent.smoothScrollToPosition(destPageId);
200 |
201 | }
202 |
203 | @Override
204 | public void onDrawerClosed(View drawerView) {
205 | }
206 |
207 | @Override
208 | public void onDrawerStateChanged(int newState) {
209 |
210 | }
211 |
212 |
213 | private void setTestData() {
214 | subTitles.add("01.概况");
215 | subTitles.add("02.成都之必体验");
216 | subTitles.add("04.景点");
217 | subTitles.add("05.住宿");
218 | subTitles.add("06.餐饮");
219 | subTitles.add("07.购物");
220 | subTitles.add("08.娱乐");
221 |
222 | subUrls.add("http://m.mafengwo.cn/gl/catalog/index?id=29&catalog_id=100");
223 | subUrls.add("http://m.mafengwo.cn/gl/catalog/index?id=29&catalog_id=101");
224 | subUrls.add("http://m.mafengwo.cn/gl/catalog/index?id=29&catalog_id=102");
225 | subUrls.add("http://m.mafengwo.cn/gl/catalog/index?id=29&catalog_id=1868");
226 | subUrls.add("http://m.mafengwo.cn/gl/catalog/index?id=29&catalog_id=103");
227 | subUrls.add("http://m.mafengwo.cn/gl/catalog/index?id=29&catalog_id=104");
228 | subUrls.add("http://m.mafengwo.cn/gl/catalog/index?id=29&catalog_id=105");
229 | }
230 | }
231 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tandygong/gzx/nestscroll/utils/ActivityUtils.java:
--------------------------------------------------------------------------------
1 | package com.tandygong.gzx.nestscroll.utils;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.content.Intent;
6 |
7 | import com.tandygong.gzx.nestscroll.activitys.NestScrollWithScrollViewActivity;
8 |
9 | /**
10 | * Created by usb on 2016/4/13.
11 | */
12 | public class ActivityUtils {
13 | public static void toSchoolDetailActivityForResult(Context context, boolean isApply, String chineseName, String englishName, String imgUrl, int schoolId, int programId, boolean checked) {
14 | Intent intent = new Intent(context, NestScrollWithScrollViewActivity.class);
15 | intent.putExtra("isApply", isApply);
16 | intent.putExtra("chineseName", chineseName);
17 | intent.putExtra("englishName", englishName);
18 | intent.putExtra("imgUrl", imgUrl);
19 | intent.putExtra("schoolId", schoolId);
20 | intent.putExtra("programId", programId);
21 | intent.putExtra("checked", checked);
22 | context.startActivity(intent);
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tandygong/gzx/nestscroll/utils/Constants.java:
--------------------------------------------------------------------------------
1 | package com.tandygong.gzx.nestscroll.utils;
2 |
3 | /**
4 | * Created by usb on 2016/4/13.
5 | */
6 | public class Constants {
7 | public static final String ACTION_REPLACE_FRAGMENT_SCHOOL_INFO = "action_replace_fragment_school_info";
8 | //WebViewCacheDir
9 | public static final String APP_WEB_CACAHE_DIRNAME = "/webcache";
10 | }
11 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tandygong/gzx/nestscroll/views/AppWebView.java:
--------------------------------------------------------------------------------
1 | package com.tandygong.gzx.nestscroll.views;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.webkit.WebSettings;
6 | import android.webkit.WebView;
7 |
8 | import com.tandygong.gzx.nestscroll.utils.Constants;
9 |
10 |
11 | /**
12 | * Created by gzx on 2016/3/11 at 15:42.
13 | */
14 | public class AppWebView extends WebView {
15 |
16 | private String cacheDirPath;
17 |
18 | public AppWebView(Context context) {
19 | super(context);
20 | cacheDirPath = context.getFilesDir().getAbsolutePath() + Constants.APP_WEB_CACAHE_DIRNAME;
21 | initSetting();
22 | }
23 |
24 | public AppWebView(Context context, AttributeSet attrs) {
25 | super(context, attrs);
26 | cacheDirPath = context.getFilesDir().getAbsolutePath() + Constants.APP_WEB_CACAHE_DIRNAME;
27 | initSetting();
28 | }
29 |
30 | public AppWebView(Context context, AttributeSet attrs, int defStyleAttr) {
31 | super(context, attrs, defStyleAttr);
32 | cacheDirPath = context.getFilesDir().getAbsolutePath() + Constants.APP_WEB_CACAHE_DIRNAME;
33 | initSetting();
34 | }
35 |
36 | public void initSetting() {
37 | getSettings().setJavaScriptEnabled(true);
38 | getSettings().setRenderPriority(WebSettings.RenderPriority.HIGH);
39 | getSettings().setCacheMode(WebSettings.LOAD_DEFAULT); // 设置
40 | // 缓存模式
41 | // 开启 DOM storage API 功能
42 | getSettings().setDomStorageEnabled(true);
43 | // 开启 database storage API 功能
44 | getSettings().setDatabaseEnabled(true);
45 | // 设置数据库缓存路径
46 | getSettings().setDatabasePath(cacheDirPath);
47 | // 设置 Application Caches 缓存目录
48 | getSettings().setAppCachePath(cacheDirPath);
49 | // 开启 Application Caches 功能
50 | getSettings().setAppCacheEnabled(true);
51 | }
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tandygong/gzx/nestscroll/views/AppWebViewClient.java:
--------------------------------------------------------------------------------
1 | package com.tandygong.gzx.nestscroll.views;
2 |
3 | import android.graphics.Bitmap;
4 | import android.webkit.WebView;
5 | import android.webkit.WebViewClient;
6 |
7 | /**
8 | * Created by gzx on 2016/3/11 at 15:36.
9 | */
10 | public class AppWebViewClient extends WebViewClient {
11 |
12 | @Override
13 | public boolean shouldOverrideUrlLoading(WebView view, String url) {
14 | return super.shouldOverrideUrlLoading(view, url);
15 | }
16 |
17 | @Override
18 | public void onPageStarted(WebView view, String url, Bitmap favicon) {
19 | super.onPageStarted(view, url, favicon);
20 | }
21 |
22 | @Override
23 | public void onPageFinished(WebView view, String url) {
24 | super.onPageFinished(view, url);
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tandygong/gzx/nestscroll/views/CustomDrawerLayout.java:
--------------------------------------------------------------------------------
1 | package com.tandygong.gzx.nestscroll.views;
2 |
3 | import android.content.Context;
4 | import android.support.v4.widget.DrawerLayout;
5 | import android.util.AttributeSet;
6 |
7 | /**
8 | * Created by gzx on 2016/3/12 at 17:37.
9 | */
10 | public class CustomDrawerLayout extends DrawerLayout {
11 |
12 | public CustomDrawerLayout(Context context) {
13 | super(context);
14 | }
15 |
16 | public CustomDrawerLayout(Context context, AttributeSet attrs) {
17 | super(context, attrs);
18 | }
19 |
20 | public CustomDrawerLayout(Context context, AttributeSet attrs, int defStyle) {
21 | super(context, attrs, defStyle);
22 | }
23 |
24 |
25 | @Override
26 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
27 | widthMeasureSpec = MeasureSpec.makeMeasureSpec(
28 | MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY);
29 | heightMeasureSpec = MeasureSpec.makeMeasureSpec(
30 | MeasureSpec.getSize(heightMeasureSpec), MeasureSpec.EXACTLY);
31 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
32 | }
33 |
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tandygong/gzx/nestscroll/views/CustomerNestedScrollView.java:
--------------------------------------------------------------------------------
1 | package com.tandygong.gzx.nestscroll.views;
2 |
3 | import android.content.Context;
4 | import android.support.v4.widget.NestedScrollView;
5 | import android.util.AttributeSet;
6 | import android.view.MotionEvent;
7 |
8 | /**
9 | * Created by gzx on 2016/3/24 at 20:20.
10 | */
11 | public class CustomerNestedScrollView extends NestedScrollView implements Pullable {
12 |
13 | private boolean isScrollToBottom;
14 | private boolean canLoadMore = true;
15 | private boolean canRefresh = true;
16 |
17 |
18 | public CustomerNestedScrollView(Context context) {
19 | super(context);
20 | }
21 |
22 | public CustomerNestedScrollView(Context context, AttributeSet attrs) {
23 | super(context, attrs);
24 | }
25 |
26 | public CustomerNestedScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
27 | super(context, attrs, defStyleAttr);
28 | }
29 |
30 |
31 | public boolean isCanLoadMore() {
32 | return canLoadMore;
33 | }
34 |
35 | public void setCanLoadMore(boolean canLoadMore) {
36 | this.canLoadMore = canLoadMore;
37 | }
38 |
39 | public boolean isCanRefresh() {
40 | return canRefresh;
41 | }
42 |
43 | public void setCanRefresh(boolean canRefresh) {
44 | this.canRefresh = canRefresh;
45 | }
46 |
47 |
48 | @Override
49 | public boolean canPullDown() {
50 | return getScrollY() == 0 && canRefresh;
51 | }
52 |
53 |
54 | @Override
55 | protected void onScrollChanged(int l, int t, int oldl, int oldt) {
56 | int scrollY = getScrollY();
57 | super.onScrollChanged(l, t, oldl, oldt);
58 | }
59 |
60 |
61 | @Override
62 | public boolean canPullUp() {
63 | return isScrollToBottom && canLoadMore;
64 | }
65 |
66 |
67 | @Override
68 | public boolean onTouchEvent(MotionEvent ev) {
69 | switch (ev.getAction()) {
70 | case MotionEvent.ACTION_DOWN:
71 | break;
72 | case MotionEvent.ACTION_MOVE:
73 | int scrollY = getScrollY();
74 | int height = getHeight();
75 | int scrollViewMeasuredHeight = getChildAt(0).getMeasuredHeight();
76 | if (scrollY == 0) {
77 | }
78 | if ((scrollY + height) == scrollViewMeasuredHeight) {
79 | isScrollToBottom = true;
80 | } else {
81 | isScrollToBottom = false;
82 | }
83 | break;
84 |
85 | default:
86 | break;
87 | }
88 | return super.onTouchEvent(ev);
89 | }
90 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/tandygong/gzx/nestscroll/views/ProgressBarWebView.java:
--------------------------------------------------------------------------------
1 | package com.tandygong.gzx.nestscroll.views;
2 |
3 | import android.content.Context;
4 | import android.graphics.Bitmap;
5 | import android.os.Handler;
6 | import android.os.Message;
7 | import android.support.v4.content.ContextCompat;
8 | import android.util.AttributeSet;
9 | import android.webkit.WebView;
10 | import android.widget.AbsoluteLayout;
11 | import android.widget.LinearLayout;
12 | import android.widget.ProgressBar;
13 |
14 | import com.tandygong.gzx.nestscroll.R;
15 |
16 |
17 | public class ProgressBarWebView extends AppWebView {
18 | private int webViewMargin = 114;
19 | private ProgressBar progressbar;
20 | private OnLoadCompleteListener onLoadCompleteListener;
21 | Handler handler = new Handler(new Handler.Callback() {
22 | @Override
23 | public boolean handleMessage(Message msg) {
24 | switch (msg.what) {
25 | case 2:
26 | if (getProgress() == 100) {
27 | progressbar.setVisibility(INVISIBLE);
28 | LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(-1, -1);
29 | params.topMargin = webViewMargin;
30 | setLayoutParams(params);
31 | if (onLoadCompleteListener != null) {
32 | onLoadCompleteListener.onComplete();
33 | }
34 | } else {
35 | if (progressbar.getVisibility() == INVISIBLE)
36 | progressbar.setVisibility(VISIBLE);
37 | progressbar.setProgress(getProgress());
38 | handler.sendEmptyMessageDelayed(2, 10);
39 | }
40 | break;
41 | default:
42 | break;
43 | }
44 |
45 | return false;
46 | }
47 | }
48 | );
49 |
50 | public ProgressBarWebView(Context context) {
51 | this(context, null, 0);
52 |
53 | }
54 |
55 | public void setWebViewMargin(int margin) {
56 | webViewMargin = margin;
57 | }
58 |
59 | public ProgressBarWebView(Context context, AttributeSet attrs) {
60 | this(context, attrs, 0);
61 | }
62 |
63 | public ProgressBarWebView(Context context, AttributeSet attrs, int defStyle) {
64 | super(context, attrs, defStyle);
65 | progressbar = new ProgressBar(context, null, android.R.attr.progressBarStyleHorizontal);
66 | progressbar.setProgressDrawable(ContextCompat.getDrawable(getContext(), R.drawable.progressbar));
67 | progressbar.setMax(100);
68 | LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(AbsoluteLayout.LayoutParams.FILL_PARENT, 5);
69 | layoutParams.bottomMargin = 25;
70 | progressbar.setLayoutParams(layoutParams);
71 | addView(progressbar);
72 | setWebViewClient(new WebClient());
73 | }
74 |
75 | public OnLoadCompleteListener getOnLoadCompleteListener() {
76 | return onLoadCompleteListener;
77 | }
78 |
79 | public void setOnLoadCompleteListener(OnLoadCompleteListener onLoadCompleteListener) {
80 | this.onLoadCompleteListener = onLoadCompleteListener;
81 | }
82 |
83 |
84 | public class WebClient extends AppWebViewClient {
85 | @Override
86 | public void onPageFinished(WebView view, String url) {
87 | super.onPageFinished(view, url);
88 | }
89 |
90 | @Override
91 | public void onPageStarted(WebView view, String url, Bitmap favicon) {
92 | handler.sendEmptyMessage(2);
93 | super.onPageStarted(view, url, favicon);
94 | }
95 |
96 | }
97 |
98 |
99 | @Override
100 | protected void onScrollChanged(int l, int t, int oldl, int oldt) {
101 | AbsoluteLayout.LayoutParams lp = (AbsoluteLayout.LayoutParams) progressbar.getLayoutParams();
102 | lp.x = l;
103 | lp.y = t;
104 | progressbar.setLayoutParams(lp);
105 | super.onScrollChanged(l, t, oldl, oldt);
106 | }
107 |
108 |
109 | public interface OnLoadCompleteListener {
110 | void onComplete();
111 | }
112 |
113 | }
114 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tandygong/gzx/nestscroll/views/PullToRefreshLayout.java:
--------------------------------------------------------------------------------
1 | package com.tandygong.gzx.nestscroll.views;
2 |
3 | import android.content.Context;
4 | import android.os.AsyncTask;
5 | import android.os.Handler;
6 | import android.os.Message;
7 | import android.util.AttributeSet;
8 | import android.view.MotionEvent;
9 | import android.view.View;
10 | import android.view.ViewGroup;
11 | import android.view.animation.AnimationUtils;
12 | import android.view.animation.LinearInterpolator;
13 | import android.view.animation.RotateAnimation;
14 | import android.widget.RelativeLayout;
15 | import android.widget.TextView;
16 |
17 |
18 | import com.tandygong.gzx.nestscroll.R;
19 |
20 | import java.util.Timer;
21 | import java.util.TimerTask;
22 |
23 | public class PullToRefreshLayout extends RelativeLayout {
24 | private String mStrRefreshing = "刷新中";
25 | private String mStrPullToRefresh = "继续下拉以刷新";
26 | private String mStrReleaseToRefresh = "释放刷新";
27 | private String mStrRefreshSuccess = "刷新成功";
28 | private String mStrRefreshFail="刷新失败";
29 |
30 | private String mStrLoading = "加载中";
31 | private String mStrPullToLoadMore = "继续上拉加载更多";
32 | private String mStrReleaseToLoadMore = "释放加载更多";
33 | private String mStrLoadSuccess = "加载成功";
34 | private String mStrLoadFail="加载失败";
35 |
36 | // 初始状态
37 | public static final int INIT = 0;
38 | // 释放刷新
39 | public static final int RELEASE_TO_REFRESH = 1;
40 | // 正在刷新
41 | public static final int REFRESHING = 2;
42 | // 释放加载
43 | public static final int RELEASE_TO_LOAD = 3;
44 | // 正在加载
45 | public static final int LOADING = 4;
46 | // 操作完毕
47 | public static final int DONE = 5;
48 | // 当前状态
49 | private int state = INIT;
50 | // 刷新回调接口
51 | private OnRefreshListener mListener;
52 | // 刷新成功
53 | public static final int SUCCEED = 0;
54 | // 刷新失败
55 | public static final int FAIL = 1;
56 | // 按下Y坐标,上一个事件点Y坐标
57 | private float downY, lastY;
58 |
59 | // 下拉的距离。注意:pullDownY和pullUpY不可能同时不为0
60 | public float pullDownY = 0;
61 | // 上拉的距离
62 | private float pullUpY = 0;
63 |
64 | // 释放刷新的距离
65 | private float refreshDist = 200;
66 | // 释放加载的距离
67 | private float loadmoreDist = 200;
68 |
69 | private MyTimer timer;
70 | // 回滚速度
71 | public float MOVE_SPEED = 8;
72 | // 第一次执行布局
73 | private boolean isLayout = false;
74 | // 在刷新过程中滑动操作
75 | private boolean isTouch = false;
76 | // 手指滑动距离与下拉头的滑动距离比,中间会随正切函数变化
77 | private float radio = 2;
78 |
79 | // 下拉箭头的转180°动画
80 | private RotateAnimation rotateAnimation;
81 | // 均匀旋转动画
82 | private RotateAnimation refreshingAnimation;
83 |
84 | // 下拉头
85 | private View refreshView;
86 | // 下拉的箭头
87 | private View pullView;
88 | // 正在刷新的图标
89 | private View refreshingView;
90 | // 刷新结果图标
91 | private View refreshStateImageView;
92 | // 刷新结果:成功或失败
93 | private TextView refreshStateTextView;
94 |
95 | // 上拉头
96 | private View loadmoreView;
97 | // 上拉的箭头
98 | private View pullUpView;
99 | // 正在加载的图标
100 | private View loadingView;
101 | // 加载结果图标
102 | private View loadStateImageView;
103 | // 加载结果:成功或失败
104 | private TextView loadStateTextView;
105 |
106 | // 实现了Pullable接口的View
107 | private View pullableView;
108 | // 过滤多点触碰
109 | private int mEvents;
110 |
111 | // 这两个变量用来控制pull的方向,如果不加控制,当情况满足可上拉又可下拉时没法下拉
112 | private boolean canPullDown = true;
113 | private boolean canPullUp = true;
114 |
115 | private Context mContext;
116 |
117 | Handler updateHandler = new Handler() {
118 |
119 | @Override
120 | public void handleMessage(Message msg) {
121 | // 回弹速度随下拉距离moveDeltaY增大而增大
122 | MOVE_SPEED = (float) (8 + 5 * Math.tan(Math.PI / 2
123 | / getMeasuredHeight() * (pullDownY + Math.abs(pullUpY))));
124 | if (!isTouch) {
125 | // 正在刷新,且没有往上推的话则悬停,显示"正在刷新..."
126 | if (state == REFRESHING && pullDownY <= refreshDist) {
127 | pullDownY = refreshDist;
128 | timer.cancel();
129 | } else if (state == LOADING && -pullUpY <= loadmoreDist) {
130 | pullUpY = -loadmoreDist;
131 | timer.cancel();
132 | }
133 |
134 | }
135 | if (pullDownY > 0)
136 | pullDownY -= MOVE_SPEED;
137 | else if (pullUpY < 0)
138 | pullUpY += MOVE_SPEED;
139 | if (pullDownY < 0) {
140 | // 已完成回弹
141 | pullDownY = 0;
142 | pullView.clearAnimation();
143 | // 隐藏下拉头时有可能还在刷新,只有当前状态不是正在刷新时才改变状态
144 | if (state != REFRESHING && state != LOADING)
145 | changeState(INIT);
146 | timer.cancel();
147 | requestLayout();
148 | }
149 | if (pullUpY > 0) {
150 | // 已完成回弹
151 | pullUpY = 0;
152 | pullUpView.clearAnimation();
153 | // 隐藏上拉头时有可能还在刷新,只有当前状态不是正在刷新时才改变状态
154 | if (state != REFRESHING && state != LOADING)
155 | changeState(INIT);
156 | timer.cancel();
157 | requestLayout();
158 | }
159 | // Log.d("handle", "handle");
160 | // 刷新布局,会自动调用onLayout
161 | requestLayout();
162 | // 没有拖拉或者回弹完成
163 | if (pullDownY + Math.abs(pullUpY) == 0)
164 | timer.cancel();
165 | }
166 |
167 | };
168 |
169 | public void setmStrRefreshing(String mStrRefreshing) {
170 | this.mStrRefreshing = mStrRefreshing;
171 | }
172 |
173 | public void setmStrPullToRefresh(String mStrPullToRefresh) {
174 | this.mStrPullToRefresh = mStrPullToRefresh;
175 | }
176 |
177 | public void setmStrReleaseToRefresh(String mStrReleaseToRefresh) {
178 | this.mStrReleaseToRefresh = mStrReleaseToRefresh;
179 | }
180 |
181 | public void setmStrRefreshSuccess(String mStrRefreshSuccess) {
182 | this.mStrRefreshSuccess = mStrRefreshSuccess;
183 | }
184 |
185 | public void setmStrRefreshFail(String mStrRefreshFail) {
186 | this.mStrRefreshFail = mStrRefreshFail;
187 | }
188 |
189 | public void setmStrLoading(String mStrLoading) {
190 | this.mStrLoading = mStrLoading;
191 | }
192 |
193 | public void setmStrPullToLoadMore(String mStrPullToLoadMore) {
194 | this.mStrPullToLoadMore = mStrPullToLoadMore;
195 | }
196 |
197 | public void setmStrReleaseToLoadMore(String mStrReleaseToLoadMore) {
198 | this.mStrReleaseToLoadMore = mStrReleaseToLoadMore;
199 | }
200 |
201 | public void setmStrLoadSuccess(String mStrLoadSuccess) {
202 | this.mStrLoadSuccess = mStrLoadSuccess;
203 | }
204 |
205 | public void setmStrLoadFail(String mStrLoadFail) {
206 | this.mStrLoadFail = mStrLoadFail;
207 | }
208 | public void setRefreshWords(String refreshingStr, String pulltoRefreshStr, String releasetoRefreshStr, String refreshSuccessStr,String refreshFailStr) {
209 | this.mStrRefreshing = refreshingStr;
210 | this.mStrPullToRefresh = pulltoRefreshStr;
211 | this.mStrReleaseToRefresh = releasetoRefreshStr;
212 | this.mStrRefreshSuccess = refreshSuccessStr;
213 | this.mStrRefreshFail=refreshFailStr;
214 | }
215 |
216 | public void setLoadMoreWord(String loadingStr, String pulltoLoadmoreStr, String releaseToLoadmoreStr, String loadSuccessStr,String loadFailStr) {
217 | this.mStrLoading = loadingStr;
218 | this.mStrPullToLoadMore = pulltoLoadmoreStr;
219 | this.mStrReleaseToLoadMore = releaseToLoadmoreStr;
220 | this.mStrLoadSuccess = loadSuccessStr;
221 | this.mStrLoadFail=loadFailStr;
222 | }
223 |
224 | public void setOnRefreshListener(OnRefreshListener listener) {
225 | mListener = listener;
226 | }
227 |
228 | public PullToRefreshLayout(Context context) {
229 | super(context);
230 | initView(context);
231 | }
232 |
233 | public PullToRefreshLayout(Context context, AttributeSet attrs) {
234 | super(context, attrs);
235 | initView(context);
236 | }
237 |
238 | public PullToRefreshLayout(Context context, AttributeSet attrs, int defStyle) {
239 | super(context, attrs, defStyle);
240 | initView(context);
241 | }
242 |
243 | private void initView(Context context) {
244 | mContext = context;
245 | timer = new MyTimer(updateHandler);
246 | rotateAnimation = (RotateAnimation) AnimationUtils.loadAnimation(
247 | context, R.anim.reverse_anim);
248 | refreshingAnimation = (RotateAnimation) AnimationUtils.loadAnimation(
249 | context, R.anim.rotating);
250 | // 添加匀速转动动画
251 | LinearInterpolator lir = new LinearInterpolator();
252 | rotateAnimation.setInterpolator(lir);
253 | refreshingAnimation.setInterpolator(lir);
254 | }
255 |
256 | private void hide() {
257 | timer.schedule(5);
258 | }
259 |
260 |
261 | public void refreshFinish(int refreshResult) {
262 | refreshingView.clearAnimation();
263 | refreshingView.setVisibility(View.GONE);
264 | switch (refreshResult) {
265 | case SUCCEED:
266 | // 刷新成功
267 | refreshStateImageView.setVisibility(View.VISIBLE);
268 | refreshStateTextView.setText(mStrRefreshSuccess);
269 | refreshStateImageView
270 | .setBackgroundResource(R.mipmap.refresh_succeed);
271 | break;
272 | case FAIL:
273 | default:
274 | // 刷新失败
275 | refreshStateImageView.setVisibility(View.VISIBLE);
276 | refreshStateTextView.setText(mStrRefreshFail);
277 | refreshStateImageView
278 | .setBackgroundResource(R.mipmap.refresh_failed);
279 | break;
280 | }
281 | if (pullDownY > 0) {
282 | // 刷新结果停留1秒
283 | new Handler() {
284 | @Override
285 | public void handleMessage(Message msg) {
286 | changeState(DONE);
287 | hide();
288 | }
289 | }.sendEmptyMessageDelayed(0, 1000);
290 | } else {
291 | changeState(DONE);
292 | hide();
293 | }
294 | }
295 |
296 |
297 | public void loadmoreFinish(int refreshResult) {
298 | loadingView.clearAnimation();
299 | loadingView.setVisibility(View.GONE);
300 | switch (refreshResult) {
301 | case SUCCEED:
302 | // 加载成功
303 | loadStateImageView.setVisibility(View.VISIBLE);
304 | loadStateTextView.setText(mStrLoadSuccess);
305 | loadStateImageView.setBackgroundResource(R.mipmap.load_succeed);
306 | break;
307 | case FAIL:
308 | default:
309 | // 加载失败
310 | loadStateImageView.setVisibility(View.VISIBLE);
311 | loadStateTextView.setText(mStrLoadFail);
312 | loadStateImageView.setBackgroundResource(R.mipmap.load_failed);
313 | break;
314 | }
315 | if (pullUpY < 0) {
316 | // 刷新结果停留1秒
317 | new Handler() {
318 | @Override
319 | public void handleMessage(Message msg) {
320 | changeState(DONE);
321 | hide();
322 | }
323 | }.sendEmptyMessageDelayed(0, 1000);
324 | } else {
325 | changeState(DONE);
326 | hide();
327 | }
328 | }
329 |
330 | private void changeState(int to) {
331 | state = to;
332 | switch (state) {
333 | case INIT:
334 | // 下拉布局初始状态
335 | refreshStateImageView.setVisibility(View.GONE);
336 | refreshStateTextView.setText(mStrPullToRefresh);
337 | pullView.clearAnimation();
338 | pullView.setVisibility(View.VISIBLE);
339 | // 上拉布局初始状态
340 | loadStateImageView.setVisibility(View.GONE);
341 | loadStateTextView.setText(mStrPullToLoadMore);
342 | pullUpView.clearAnimation();
343 | pullUpView.setVisibility(View.VISIBLE);
344 | break;
345 | case RELEASE_TO_REFRESH:
346 | // 释放刷新状态
347 | refreshStateTextView.setText(mStrReleaseToRefresh);
348 | pullView.startAnimation(rotateAnimation);
349 | break;
350 | case REFRESHING:
351 | // 正在刷新状态
352 | pullView.clearAnimation();
353 | refreshingView.setVisibility(View.VISIBLE);
354 | pullView.setVisibility(View.INVISIBLE);
355 | refreshingView.startAnimation(refreshingAnimation);
356 | refreshStateTextView.setText(mStrRefreshing);
357 | break;
358 | case RELEASE_TO_LOAD:
359 | // 释放加载状态
360 | loadStateTextView.setText(mStrReleaseToLoadMore);
361 | pullUpView.startAnimation(rotateAnimation);
362 | break;
363 | case LOADING:
364 | // 正在加载状态
365 | pullUpView.clearAnimation();
366 | loadingView.setVisibility(View.VISIBLE);
367 | pullUpView.setVisibility(View.INVISIBLE);
368 | loadingView.startAnimation(refreshingAnimation);
369 | loadStateTextView.setText(mStrLoading);
370 | break;
371 | case DONE:
372 | // 刷新或加载完毕,啥都不做
373 | break;
374 | }
375 | }
376 |
377 | private void releasePull() {
378 | canPullDown = true;
379 | canPullUp = true;
380 | }
381 |
382 |
383 | @Override
384 | public boolean dispatchTouchEvent(MotionEvent ev) {
385 | switch (ev.getActionMasked()) {
386 | case MotionEvent.ACTION_DOWN:
387 | downY = ev.getY();
388 | lastY = downY;
389 | timer.cancel();
390 | mEvents = 0;
391 | releasePull();
392 | break;
393 | case MotionEvent.ACTION_POINTER_DOWN:
394 | case MotionEvent.ACTION_POINTER_UP:
395 | // 过滤多点触碰
396 | mEvents = -1;
397 | break;
398 | case MotionEvent.ACTION_MOVE:
399 | if (mEvents == 0) {
400 | if (pullDownY > 0
401 | || (((Pullable) pullableView).canPullDown()
402 | && canPullDown && state != LOADING)) {
403 | // 可以下拉,正在加载时不能下拉
404 | // 对实际滑动距离做缩小,造成用力拉的感觉
405 | pullDownY = pullDownY + (ev.getY() - lastY) / radio;
406 | if (pullDownY < 0) {
407 | pullDownY = 0;
408 | canPullDown = false;
409 | canPullUp = true;
410 | }
411 | if (pullDownY > getMeasuredHeight())
412 | pullDownY = getMeasuredHeight();
413 | if (state == REFRESHING) {
414 | // 正在刷新的时候触摸移动
415 | isTouch = true;
416 | }
417 | } else if (pullUpY < 0
418 | || (((Pullable) pullableView).canPullUp() && canPullUp && state != REFRESHING)) {
419 | // 可以上拉,正在刷新时不能上拉
420 | pullUpY = pullUpY + (ev.getY() - lastY) / radio;
421 | if (pullUpY > 0) {
422 | pullUpY = 0;
423 | canPullDown = true;
424 | canPullUp = false;
425 | }
426 | if (pullUpY < -getMeasuredHeight())
427 | pullUpY = -getMeasuredHeight();
428 | if (state == LOADING) {
429 | // 正在加载的时候触摸移动
430 | isTouch = true;
431 | }
432 | } else
433 | releasePull();
434 | } else
435 | mEvents = 0;
436 | lastY = ev.getY();
437 | // 根据下拉距离改变比例
438 | radio = (float) (2 + 2 * Math.tan(Math.PI / 2 / getMeasuredHeight()
439 | * (pullDownY + Math.abs(pullUpY))));
440 | if (pullDownY > 0 || pullUpY < 0)
441 | requestLayout();
442 | if (pullDownY > 0) {
443 | if (pullDownY <= refreshDist
444 | && (state == RELEASE_TO_REFRESH || state == DONE)) {
445 | // 如果下拉距离没达到刷新的距离且当前状态是释放刷新,改变状态为下拉刷新
446 | changeState(INIT);
447 | }
448 | if (pullDownY >= refreshDist && state == INIT) {
449 | // 如果下拉距离达到刷新的距离且当前状态是初始状态刷新,改变状态为释放刷新
450 | changeState(RELEASE_TO_REFRESH);
451 | }
452 | } else if (pullUpY < 0) {
453 | // 下面是判断上拉加载的,同上,注意pullUpY是负值
454 | if (-pullUpY <= loadmoreDist
455 | && (state == RELEASE_TO_LOAD || state == DONE)) {
456 | changeState(INIT);
457 | }
458 | // 上拉操作
459 | if (-pullUpY >= loadmoreDist && state == INIT) {
460 | changeState(RELEASE_TO_LOAD);
461 | }
462 |
463 | }
464 | // 因为刷新和加载操作不能同时进行,所以pullDownY和pullUpY不会同时不为0,因此这里用(pullDownY +
465 | // Math.abs(pullUpY))就可以不对当前状态作区分了
466 | if ((pullDownY + Math.abs(pullUpY)) > 8) {
467 | // 防止下拉过程中误触发长按事件和点击事件
468 | ev.setAction(MotionEvent.ACTION_CANCEL);
469 | }
470 | break;
471 | case MotionEvent.ACTION_UP:
472 | if (pullDownY > refreshDist || -pullUpY > loadmoreDist)
473 | // 正在刷新时往下拉(正在加载时往上拉),释放后下拉头(上拉头)不隐藏
474 | {
475 | isTouch = false;
476 | }
477 | if (state == RELEASE_TO_REFRESH) {
478 | changeState(REFRESHING);
479 | // 刷新操作
480 | if (mListener != null)
481 | mListener.onRefresh(this);
482 | } else if (state == RELEASE_TO_LOAD) {
483 | changeState(LOADING);
484 | // 加载操作
485 | if (mListener != null)
486 | mListener.onLoadMore(this);
487 | }
488 | hide();
489 | default:
490 | break;
491 | }
492 | // 事件分发交给父类
493 | super.dispatchTouchEvent(ev);
494 | return true;
495 | }
496 |
497 | private class AutoRefreshAndLoadTask extends
498 | AsyncTask {
499 |
500 | @Override
501 | protected String doInBackground(Integer... params) {
502 | while (pullDownY < 4 / 3 * refreshDist) {
503 | pullDownY += MOVE_SPEED;
504 | publishProgress(pullDownY);
505 | try {
506 | Thread.sleep(params[0]);
507 | } catch (InterruptedException e) {
508 | e.printStackTrace();
509 | }
510 | }
511 | return null;
512 | }
513 |
514 | @Override
515 | protected void onPostExecute(String result) {
516 | changeState(REFRESHING);
517 | if (mListener != null)
518 | mListener.onRefresh(PullToRefreshLayout.this);
519 | hide();
520 | }
521 |
522 | @Override
523 | protected void onProgressUpdate(Float... values) {
524 | if (pullDownY > refreshDist)
525 | changeState(RELEASE_TO_REFRESH);
526 | requestLayout();
527 | }
528 |
529 | }
530 |
531 | public void autoRefresh() {
532 | AutoRefreshAndLoadTask task = new AutoRefreshAndLoadTask();
533 | task.execute(20);
534 | }
535 |
536 | public void autoLoad() {
537 | pullUpY = -loadmoreDist;
538 | requestLayout();
539 | changeState(LOADING);
540 | // 加载操作
541 | if (mListener != null)
542 | mListener.onLoadMore(this);
543 | }
544 |
545 | private void initView() {
546 | // 初始化下拉布局
547 | pullView = refreshView.findViewById(R.id.pull_icon);
548 | refreshStateTextView = (TextView) refreshView
549 | .findViewById(R.id.state_tv);
550 | refreshingView = refreshView.findViewById(R.id.refreshing_icon);
551 | refreshStateImageView = refreshView.findViewById(R.id.state_iv);
552 | // 初始化上拉布局
553 | pullUpView = loadmoreView.findViewById(R.id.pullup_icon);
554 | loadStateTextView = (TextView) loadmoreView
555 | .findViewById(R.id.loadstate_tv);
556 | loadingView = loadmoreView.findViewById(R.id.loading_icon);
557 | loadStateImageView = loadmoreView.findViewById(R.id.loadstate_iv);
558 | }
559 |
560 | @Override
561 | protected void onLayout(boolean changed, int l, int t, int r, int b) {
562 | if (!isLayout) {
563 | // 这里是第一次进来的时候做一些初始化
564 | refreshView = getChildAt(0);
565 | pullableView = getChildAt(1);
566 | loadmoreView = getChildAt(2);
567 | isLayout = true;
568 | initView();
569 | refreshDist = ((ViewGroup) refreshView).getChildAt(0)
570 | .getMeasuredHeight();
571 | loadmoreDist = ((ViewGroup) loadmoreView).getChildAt(0)
572 | .getMeasuredHeight();
573 | }
574 | // 改变子控件的布局,这里直接用(pullDownY + pullUpY)作为偏移量,这样就可以不对当前状态作区分
575 | refreshView.layout(0,
576 | (int) (pullDownY + pullUpY) - refreshView.getMeasuredHeight(),
577 | refreshView.getMeasuredWidth(), (int) (pullDownY + pullUpY));
578 | pullableView.layout(0, (int) (pullDownY + pullUpY),
579 | pullableView.getMeasuredWidth(), (int) (pullDownY + pullUpY)
580 | + pullableView.getMeasuredHeight());
581 | loadmoreView.layout(0,
582 | (int) (pullDownY + pullUpY) + pullableView.getMeasuredHeight(),
583 | loadmoreView.getMeasuredWidth(),
584 | (int) (pullDownY + pullUpY) + pullableView.getMeasuredHeight()
585 | + loadmoreView.getMeasuredHeight());
586 | }
587 |
588 | class MyTimer {
589 | private Handler handler;
590 | private Timer timer;
591 | private MyTask mTask;
592 |
593 | public MyTimer(Handler handler) {
594 | this.handler = handler;
595 | timer = new Timer();
596 | }
597 |
598 | public void schedule(long period) {
599 | if (mTask != null) {
600 | mTask.cancel();
601 | mTask = null;
602 | }
603 | mTask = new MyTask(handler);
604 | timer.schedule(mTask, 0, period);
605 | }
606 |
607 | public void cancel() {
608 | if (mTask != null) {
609 | mTask.cancel();
610 | mTask = null;
611 | }
612 | }
613 |
614 | class MyTask extends TimerTask {
615 | private Handler handler;
616 |
617 | public MyTask(Handler handler) {
618 | this.handler = handler;
619 | }
620 |
621 | @Override
622 | public void run() {
623 | handler.obtainMessage().sendToTarget();
624 | }
625 |
626 | }
627 | }
628 |
629 | public interface OnRefreshListener {
630 |
631 | void onRefresh(PullToRefreshLayout pullToRefreshLayout);
632 |
633 | void onLoadMore(PullToRefreshLayout pullToRefreshLayout);
634 | }
635 |
636 | }
637 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tandygong/gzx/nestscroll/views/Pullable.java:
--------------------------------------------------------------------------------
1 | package com.tandygong.gzx.nestscroll.views;
2 |
3 | public interface Pullable
4 | {
5 | boolean canPullDown();
6 | boolean canPullUp();
7 | }
8 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/reverse_anim.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/rotating.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/slide_in_from_bottom.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/slide_in_from_top.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/slide_out_to_bottom.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/slide_out_to_top.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_black_radius_5.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/progressbar.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
6 |
12 |
13 |
14 |
15 | -
16 |
17 |
18 |
20 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_nest_scroll_with_scroll_view.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
21 |
22 |
23 |
30 |
31 |
42 |
43 |
53 |
54 |
55 |
60 |
61 |
65 |
66 |
67 |
76 |
77 |
86 |
87 |
88 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
114 |
115 |
119 |
120 |
124 |
125 |
137 |
138 |
139 |
144 |
145 |
146 |
154 |
155 |
164 |
165 |
171 |
172 |
177 |
178 |
179 |
180 |
181 |
182 |
190 |
191 |
195 |
196 |
207 |
208 |
209 |
210 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_project_info.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_tab_school_info.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_tips_titles.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
18 |
19 |
25 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_fragment_container_school_info.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
12 |
13 |
14 |
15 |
20 |
21 |
26 |
27 |
28 |
36 |
37 |
44 |
45 |
46 |
53 |
54 |
60 |
61 |
72 |
73 |
82 |
83 |
84 |
87 |
88 |
95 |
96 |
102 |
103 |
114 |
115 |
116 |
117 |
118 |
125 |
126 |
133 |
134 |
140 |
141 |
153 |
154 |
155 |
156 |
159 |
160 |
167 |
168 |
174 |
175 |
186 |
187 |
188 |
189 |
190 |
191 |
201 |
202 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
224 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/load_more.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
14 |
15 |
19 |
20 |
27 |
28 |
36 |
37 |
45 |
46 |
54 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/refresh_head.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
14 |
15 |
19 |
20 |
27 |
28 |
36 |
37 |
45 |
46 |
54 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tandygong/NestScroll/c28e8fd7a5700a896f7c8c7a9ff746ee418259d4/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tandygong/NestScroll/c28e8fd7a5700a896f7c8c7a9ff746ee418259d4/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/guanliqi_back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tandygong/NestScroll/c28e8fd7a5700a896f7c8c7a9ff746ee418259d4/app/src/main/res/mipmap-xhdpi/guanliqi_back.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/guanliqi_xuanxiao.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tandygong/NestScroll/c28e8fd7a5700a896f7c8c7a9ff746ee418259d4/app/src/main/res/mipmap-xhdpi/guanliqi_xuanxiao.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tandygong/NestScroll/c28e8fd7a5700a896f7c8c7a9ff746ee418259d4/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/load_failed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tandygong/NestScroll/c28e8fd7a5700a896f7c8c7a9ff746ee418259d4/app/src/main/res/mipmap-xhdpi/load_failed.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/load_succeed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tandygong/NestScroll/c28e8fd7a5700a896f7c8c7a9ff746ee418259d4/app/src/main/res/mipmap-xhdpi/load_succeed.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/loading.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tandygong/NestScroll/c28e8fd7a5700a896f7c8c7a9ff746ee418259d4/app/src/main/res/mipmap-xhdpi/loading.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/pull_icon_big.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tandygong/NestScroll/c28e8fd7a5700a896f7c8c7a9ff746ee418259d4/app/src/main/res/mipmap-xhdpi/pull_icon_big.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/pullup_icon_big.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tandygong/NestScroll/c28e8fd7a5700a896f7c8c7a9ff746ee418259d4/app/src/main/res/mipmap-xhdpi/pullup_icon_big.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/refresh_failed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tandygong/NestScroll/c28e8fd7a5700a896f7c8c7a9ff746ee418259d4/app/src/main/res/mipmap-xhdpi/refresh_failed.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/refresh_succeed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tandygong/NestScroll/c28e8fd7a5700a896f7c8c7a9ff746ee418259d4/app/src/main/res/mipmap-xhdpi/refresh_succeed.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/refreshing.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tandygong/NestScroll/c28e8fd7a5700a896f7c8c7a9ff746ee418259d4/app/src/main/res/mipmap-xhdpi/refreshing.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/school_location.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tandygong/NestScroll/c28e8fd7a5700a896f7c8c7a9ff746ee418259d4/app/src/main/res/mipmap-xhdpi/school_location.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/school_ranking.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tandygong/NestScroll/c28e8fd7a5700a896f7c8c7a9ff746ee418259d4/app/src/main/res/mipmap-xhdpi/school_ranking.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/school_statistics.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tandygong/NestScroll/c28e8fd7a5700a896f7c8c7a9ff746ee418259d4/app/src/main/res/mipmap-xhdpi/school_statistics.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/school_weather.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tandygong/NestScroll/c28e8fd7a5700a896f7c8c7a9ff746ee418259d4/app/src/main/res/mipmap-xhdpi/school_weather.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/strategy_list.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tandygong/NestScroll/c28e8fd7a5700a896f7c8c7a9ff746ee418259d4/app/src/main/res/mipmap-xhdpi/strategy_list.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tandygong/NestScroll/c28e8fd7a5700a896f7c8c7a9ff746ee418259d4/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tandygong/NestScroll/c28e8fd7a5700a896f7c8c7a9ff746ee418259d4/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/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 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values/refs.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | NestScroll
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/test/java/com/tandygong/gzx/nestscroll/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.tandygong.gzx.nestscroll;
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 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:1.3.0'
9 |
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | }
19 | }
20 |
21 | task clean(type: Delete) {
22 | delete rootProject.buildDir
23 | }
24 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tandygong/NestScroll/c28e8fd7a5700a896f7c8c7a9ff746ee418259d4/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Apr 13 15:01:57 CST 2016
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.4-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 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------