├── .gitignore
├── Android-Sloth.iml
├── README.md
├── app
├── app.iml
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── xyz
│ │ └── ibat
│ │ └── sloth
│ │ └── ApplicationTest.java
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── xyz
│ │ └── ibat
│ │ └── sloth
│ │ ├── SlothApplication.java
│ │ ├── base
│ │ ├── BaseActivity.java
│ │ ├── BaseFragment.java
│ │ ├── FragmentFactory.java
│ │ ├── TabsFragment.java
│ │ ├── adapter
│ │ │ └── NewLoadMoreWrapper.java
│ │ └── webview
│ │ │ ├── WebActivity.java
│ │ │ └── WebFragment.java
│ │ ├── domain
│ │ ├── info
│ │ │ └── InfoFragment.java
│ │ ├── main
│ │ │ ├── activities
│ │ │ │ ├── FriendActivity.java
│ │ │ │ ├── ImagePreviewActivity.java
│ │ │ │ ├── MainActivity.java
│ │ │ │ ├── MeiziActivity.java
│ │ │ │ └── MessageActivity.java
│ │ │ ├── adapter
│ │ │ │ ├── HomeAdapter.java
│ │ │ │ ├── HomeHolder.java
│ │ │ │ ├── MeiziAdapter.java
│ │ │ │ └── MeiziHolder.java
│ │ │ ├── fragments
│ │ │ │ ├── DataFragment.java
│ │ │ │ └── MainFragment.java
│ │ │ └── model
│ │ │ │ └── DataModel.java
│ │ ├── map
│ │ │ └── MeiziFragment.java
│ │ └── mine
│ │ │ └── MineFragment.java
│ │ ├── network
│ │ ├── ImageLoader.java
│ │ ├── RetrofitFactory.java
│ │ └── api
│ │ │ └── ApiService.java
│ │ ├── utils
│ │ ├── DensityUtil.java
│ │ ├── SlothUtil.java
│ │ └── T.java
│ │ └── view
│ │ ├── AppBarStateChangeListener.java
│ │ ├── RefreshLayout.java
│ │ ├── SlothRecycler.java
│ │ ├── behavior
│ │ ├── BottomScrollBehavior.java
│ │ ├── FABScrollBehavior.java
│ │ ├── FollowBehavior.java
│ │ └── ScrollBehavior.java
│ │ ├── picasso
│ │ └── CircleTransform.java
│ │ └── widget
│ │ ├── CircleImageView.java
│ │ └── ZoomImageView.java
│ └── res
│ ├── drawable
│ ├── info_tab_selector.xml
│ ├── loadfail_btn_bg_selector.xml
│ ├── main_tab_selector.xml
│ ├── map_tab_selector.xml
│ ├── mine_tab_selector.xml
│ ├── progress_animation.xml
│ ├── progressbar.xml
│ ├── tab_text_selector.xml
│ └── webview_progress_bar_states.xml
│ ├── layout
│ ├── activity_base.xml
│ ├── activity_friend.xml
│ ├── activity_image_preview.xml
│ ├── activity_main.xml
│ ├── activity_meizi.xml
│ ├── activity_message.xml
│ ├── activity_web.xml
│ ├── common_toolbar.xml
│ ├── default_loading.xml
│ ├── fragment_base.xml
│ ├── fragment_one.xml
│ ├── fragment_tab.xml
│ ├── fragment_tab_info.xml
│ ├── fragment_tab_main.xml
│ ├── fragment_tab_map.xml
│ ├── fragment_tab_mine.xml
│ ├── fragment_web.xml
│ ├── item_fragment_home.xml
│ ├── item_meizi.xml
│ ├── item_refresh_foot.xml
│ └── navigationview_header.xml
│ ├── menu
│ ├── menu_drawer.xml
│ └── menu_main.xml
│ ├── mipmap-hdpi
│ ├── banner2.jpg
│ ├── ic_dashboard.png
│ ├── ic_discuss.png
│ ├── ic_done.png
│ ├── ic_event.png
│ ├── ic_forum.png
│ ├── ic_headset.png
│ ├── ic_launcher.png
│ ├── ic_menu.png
│ └── ic_toolbar_drawer.png
│ ├── mipmap-mdpi
│ └── ic_launcher.png
│ ├── mipmap-xhdpi
│ ├── ic_launcher.png
│ ├── ic_toolbar_drawer.png
│ ├── icon_arrow_back.png
│ ├── icon_head.jpg
│ ├── icon_info_default.png
│ ├── icon_info_pressed.png
│ ├── icon_load_failed.png
│ ├── icon_main_default.png
│ ├── icon_main_pressed.png
│ ├── icon_map_default.png
│ ├── icon_map_pressed.png
│ ├── icon_mine_default.png
│ ├── icon_mine_pressed.png
│ ├── icon_search.png
│ ├── icon_search_white.png
│ └── icon_share.png
│ ├── mipmap-xxhdpi
│ ├── ic_launcher.png
│ └── ic_toolbar_drawer.png
│ ├── mipmap-xxxhdpi
│ └── ic_launcher.png
│ ├── transition
│ ├── explode.xml
│ ├── fade.xml
│ └── slide.xml
│ ├── values-w820dp
│ └── dimens.xml
│ └── values
│ ├── attrs.xml
│ ├── colors.xml
│ ├── dimens.xml
│ ├── strings.xml
│ └── styles.xml
├── baseadapter-recyclerview
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── zhy
│ │ └── baseadapter_recyclerview
│ │ └── ApplicationTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ └── java
│ │ └── com
│ │ └── zhy
│ │ └── adapter
│ │ └── recyclerview
│ │ ├── CommonAdapter.java
│ │ ├── MultiItemTypeAdapter.java
│ │ ├── base
│ │ ├── ItemViewDelegate.java
│ │ ├── ItemViewDelegateManager.java
│ │ └── ViewHolder.java
│ │ ├── utils
│ │ └── WrapperUtils.java
│ │ └── wrapper
│ │ ├── EmptyWrapper.java
│ │ ├── HeaderAndFooterWrapper.java
│ │ └── LoadMoreWrapper.java
│ └── test
│ └── java
│ └── com
│ └── zhy
│ └── baseadapter_recyclerview
│ └── ExampleUnitTest.java
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── image
├── sloth_drawerlayout.png
├── sloth_home.png
├── sloth_image_preview.png
├── sloth_me.png
└── sloth_meizi.png
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | /.gradle
2 | /.idea
3 | /local.properties
4 | /build
5 | # OSX
6 | /gradlew
7 | *.DS_Store
8 |
9 | /gradlew.bat
10 |
11 | /Android-Sloth.iml
12 |
13 | /app/app.iml
14 |
15 | # Gradle files
16 | build/
17 | .gradle/
18 | */build/
19 |
20 | # IDEA
21 | *.iml
22 | .idea/*
23 | .idea/.name
24 | .idea/encodings.xml
25 | .idea/misc.xml
26 | .idea/modules.xml
27 | .idea/vcs.xml
28 | .idea/workspace.xml
29 |
30 |
31 |
32 |
33 | # Built application files
34 |
35 | *.ap_
36 |
37 |
38 | # Files for the Dalvik VM
39 | *.dex
40 |
41 |
42 | # Java class files
43 | *.class
44 |
45 |
46 | # Generated files
47 | antLauncher/bin
48 | antLauncher/gen
49 |
50 |
51 | # Local configuration file (sdk path, etc)
52 | local.properties
53 |
54 |
55 | # Log Files
56 | *.log
57 | gradle/*
58 | app/src/main/gen/
59 |
--------------------------------------------------------------------------------
/Android-Sloth.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Sloth
2 | ### 项目介绍:
3 |
4 | 这是一个用于Android学习的项目,使用了代码家的http://gank.io中的接口,
5 | 里面内容包括,Rxjava,Retroft,,Picasso,WebView预览图片,图片预览放大、
6 | 缩小、移动,Material Design控件使用和activity切换动画等.
7 | 目前代码结构还不是很好,以后会慢慢重构.有新的技术也会不断往项目里面添加.
8 | 希望能通过这个项目技术有一定得提升.当然你也可以安装到手机上,空闲时间看看技术文章和妹纸.
9 |
10 | ### 效果:
11 | 
12 | 
13 | 
14 | 
15 | 
16 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 23
5 | buildToolsVersion "22.0.0"
6 |
7 | defaultConfig {
8 | applicationId "xyz.ibat.sloth"
9 | minSdkVersion 14
10 | targetSdkVersion 23
11 | versionCode 1
12 | versionName "1.0"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 |
21 | }
22 |
23 | dependencies {
24 | compile fileTree(include: ['*.jar'], dir: 'libs')
25 | compile 'com.android.support:support-v4:23.1.1'
26 | compile 'com.android.support:appcompat-v7:23.1.1'
27 | compile 'com.android.support:design:23.1.1'
28 | compile 'com.jakewharton:butterknife:7.0.1'
29 | compile 'com.android.support:cardview-v7:23.2.0'
30 | compile 'io.reactivex:rxjava:1.2.5'
31 | compile 'io.reactivex:rxandroid:1.2.1'
32 | compile 'com.squareup.retrofit2:retrofit:2.1.0'
33 | compile 'com.squareup.retrofit2:converter-gson:2.1.0'
34 | compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
35 | compile 'com.squareup.picasso:picasso:2.5.2'
36 | compile project(':baseadapter-recyclerview')
37 | }
38 |
--------------------------------------------------------------------------------
/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 E:\Android\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 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/xyz/ibat/sloth/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package xyz.ibat.sloth;
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 |
6 |
7 |
8 |
9 |
15 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
28 |
32 |
35 |
38 |
42 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/app/src/main/java/xyz/ibat/sloth/SlothApplication.java:
--------------------------------------------------------------------------------
1 | package xyz.ibat.sloth;
2 |
3 | import android.app.Application;
4 | import android.content.Context;
5 |
6 | /**
7 | * Created by DongJr on 2016/4/1.
8 | */
9 | public class SlothApplication extends Application {
10 |
11 | private static Context mContext;
12 |
13 | @Override
14 | public void onCreate() {
15 | super.onCreate();
16 |
17 | mContext = getApplicationContext();
18 |
19 | }
20 |
21 | public static Context getContext() {
22 | return mContext;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/app/src/main/java/xyz/ibat/sloth/base/BaseActivity.java:
--------------------------------------------------------------------------------
1 | package xyz.ibat.sloth.base;
2 |
3 | import android.os.Build;
4 | import android.os.Bundle;
5 | import android.support.v7.app.AppCompatActivity;
6 | import android.view.WindowManager;
7 |
8 | import xyz.ibat.sloth.R;
9 |
10 | /**
11 | * Created by DongJr on 2016/03/31
12 | */
13 | public class BaseActivity extends AppCompatActivity {
14 |
15 |
16 | @Override
17 | protected void onCreate(Bundle savedInstanceState) {
18 | super.onCreate(savedInstanceState);
19 | setContentView(R.layout.activity_base);
20 |
21 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
22 | getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
23 | }
24 |
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/java/xyz/ibat/sloth/base/BaseFragment.java:
--------------------------------------------------------------------------------
1 | package xyz.ibat.sloth.base;
2 |
3 | import android.os.Bundle;
4 | import android.support.v4.app.Fragment;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 |
9 | import xyz.ibat.sloth.R;
10 |
11 | public class BaseFragment extends Fragment {
12 |
13 | @Override
14 | public View onCreateView(LayoutInflater inflater, ViewGroup container,
15 | Bundle savedInstanceState) {
16 | return inflater.inflate(R.layout.fragment_base, container, false);
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/app/src/main/java/xyz/ibat/sloth/base/FragmentFactory.java:
--------------------------------------------------------------------------------
1 | package xyz.ibat.sloth.base;
2 |
3 | import android.os.Bundle;
4 |
5 | import java.util.HashMap;
6 |
7 | import xyz.ibat.sloth.base.webview.WebFragment;
8 | import xyz.ibat.sloth.domain.main.fragments.MainFragment;
9 | import xyz.ibat.sloth.domain.map.MeiziFragment;
10 | import xyz.ibat.sloth.domain.mine.MineFragment;
11 |
12 | /**
13 | * Created by DongJr on 2016/4/15.
14 | */
15 | public class FragmentFactory {
16 |
17 | public static final String MAIN_TAG = "main";
18 | public static final String MAP_TAG = "map";
19 | public static final String INFO_TAG = "info";
20 | public static final String MINE_TAG = "mine";
21 |
22 | private MainFragment mainFragment;
23 | private MeiziFragment mapFragment;
24 | private WebFragment infoFragment;
25 | private MineFragment mineFragment;
26 |
27 |
28 | private static FragmentFactory mFactory;
29 | private HashMap mHashMap = new HashMap<>();
30 |
31 | private FragmentFactory() {
32 |
33 | }
34 |
35 | public static FragmentFactory getInstance() {
36 | if (mFactory == null) {
37 | synchronized (FragmentFactory.class) {
38 | if (mFactory == null) {
39 | mFactory = new FragmentFactory();
40 | }
41 | }
42 | }
43 | return mFactory;
44 | }
45 |
46 | public BaseFragment getFragmentByTag(String tag) {
47 |
48 | if (tag.equals(MAIN_TAG) && mainFragment == null) {
49 | mainFragment = new MainFragment();
50 | mHashMap.put(MAIN_TAG, mainFragment);
51 | }
52 | if (tag.equals(MAP_TAG) && mapFragment == null) {
53 | mapFragment = new MeiziFragment();
54 | mHashMap.put(MAP_TAG, mapFragment);
55 | }
56 | if (tag.equals(INFO_TAG) && infoFragment == null) {
57 | infoFragment = new WebFragment();
58 | Bundle bundle = new Bundle();
59 | bundle.putString(WebFragment.URL_TAG, "http://ibat.xyz");
60 | infoFragment.setArguments(bundle);
61 | mHashMap.put(INFO_TAG, infoFragment);
62 | }
63 | if (tag.equals(MINE_TAG) && mineFragment == null) {
64 | mineFragment = new MineFragment();
65 | mHashMap.put(MINE_TAG, mineFragment);
66 | }
67 | return mHashMap.get(tag);
68 | }
69 |
70 | }
71 |
--------------------------------------------------------------------------------
/app/src/main/java/xyz/ibat/sloth/base/TabsFragment.java:
--------------------------------------------------------------------------------
1 | package xyz.ibat.sloth.base;
2 |
3 | import android.os.Bundle;
4 | import android.support.v4.app.FragmentTransaction;
5 | import android.text.TextUtils;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 | import android.widget.FrameLayout;
10 | import android.widget.RadioButton;
11 | import android.widget.RadioGroup;
12 |
13 | import butterknife.Bind;
14 | import butterknife.ButterKnife;
15 | import xyz.ibat.sloth.R;
16 |
17 | /**
18 | * Created by DongJr on 2016/4/12.
19 | */
20 | public class TabsFragment extends BaseFragment implements View.OnClickListener {
21 |
22 | @Bind(R.id.fragment_tab)
23 | FrameLayout fragmentTab;
24 | @Bind(R.id.tab_group)
25 | RadioGroup tabGroup;
26 | @Bind(R.id.main_tab)
27 | RadioButton mainTab;
28 | @Bind(R.id.map_tab)
29 | RadioButton mapTab;
30 | @Bind(R.id.info_tab)
31 | RadioButton infoTab;
32 | @Bind(R.id.mine_tab)
33 | RadioButton mineTab;
34 |
35 | private FragmentFactory mFactory;
36 | private String mCurrentTag;
37 |
38 | @Override
39 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
40 | View view = inflater.inflate(R.layout.fragment_tab, container, false);
41 |
42 | ButterKnife.bind(this, view);
43 | return view;
44 | }
45 |
46 | @Override
47 | public void onViewCreated(View view, Bundle savedInstanceState) {
48 | initView();
49 | }
50 |
51 | private void initView() {
52 | mainTab.setChecked(true);
53 | mFactory = FragmentFactory.getInstance();
54 |
55 | mainTab.setOnClickListener(this);
56 | mapTab.setOnClickListener(this);
57 | infoTab.setOnClickListener(this);
58 | mineTab.setOnClickListener(this);
59 |
60 | initFragment(FragmentFactory.MAIN_TAG);
61 | }
62 |
63 | @Override
64 | public void onClick(View v) {
65 | switch (v.getId()) {
66 | case R.id.main_tab:
67 | initFragment(FragmentFactory.MAIN_TAG);
68 | break;
69 | case R.id.map_tab:
70 | initFragment(FragmentFactory.MAP_TAG);
71 | break;
72 | case R.id.info_tab:
73 | initFragment(FragmentFactory.INFO_TAG);
74 | break;
75 | case R.id.mine_tab:
76 | initFragment(FragmentFactory.MINE_TAG);
77 | break;
78 | }
79 | }
80 |
81 | private void initFragment(String tag) {
82 | BaseFragment baseFragment = mFactory.getFragmentByTag(tag);
83 | if (baseFragment == null) {
84 | throw new IllegalAccessError("tag is error!");
85 | }
86 | if (tag.equals(mCurrentTag)) {
87 | return;
88 | } else {
89 | FragmentTransaction transaction = getFragmentManager().beginTransaction();
90 | if (!TextUtils.isEmpty(mCurrentTag)) {
91 | transaction.hide(mFactory.getFragmentByTag(mCurrentTag));
92 | }
93 | if (!baseFragment.isAdded()) {
94 | transaction.add(R.id.fragment_tab, baseFragment);
95 | } else {
96 | transaction.show(baseFragment);
97 | }
98 | transaction.commitAllowingStateLoss();
99 | }
100 | mCurrentTag = tag;
101 | }
102 |
103 | @Override
104 | public void onDestroyView() {
105 | super.onDestroyView();
106 | ButterKnife.unbind(this);
107 | }
108 |
109 |
110 | }
111 |
--------------------------------------------------------------------------------
/app/src/main/java/xyz/ibat/sloth/base/adapter/NewLoadMoreWrapper.java:
--------------------------------------------------------------------------------
1 | package xyz.ibat.sloth.base.adapter;
2 |
3 | import android.content.Context;
4 | import android.support.v7.widget.RecyclerView;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.widget.ProgressBar;
8 | import android.widget.TextView;
9 |
10 | import com.zhy.adapter.recyclerview.wrapper.LoadMoreWrapper;
11 |
12 | import xyz.ibat.sloth.R;
13 |
14 | /**
15 | * Created by DongJr on 2017/1/16.
16 | */
17 |
18 | public class NewLoadMoreWrapper extends LoadMoreWrapper {
19 |
20 | private LoadState mState = LoadState.LOAD;
21 |
22 | private View mFooterView;
23 |
24 | private ProgressBar loadProgress;
25 | private TextView loadText;
26 |
27 | private LayoutInflater mInflater;
28 |
29 | public NewLoadMoreWrapper(Context context, RecyclerView.Adapter adapter,RecyclerView parent) {
30 | super(adapter);
31 |
32 | mInflater = LayoutInflater.from(context);
33 | mFooterView = mInflater.inflate(R.layout.default_loading,parent, false);
34 | loadProgress = (ProgressBar) mFooterView.findViewById(R.id.load_progress);
35 | loadText = (TextView) mFooterView.findViewById(R.id.loading_text);
36 | setLoadMoreView(mFooterView);
37 | }
38 |
39 | public void setLoadState(LoadState state) {
40 | this.mState = state;
41 | switch (state) {
42 | case LOAD:
43 | showLoadView();
44 | setShouldLoadMore(true);
45 | break;
46 | case ERROR:
47 | setShouldLoadMore(false);
48 | showLoadErrorView();
49 | break;
50 | case NOMORE:
51 | setShouldLoadMore(false);
52 | showLoadNoMoreView();
53 | break;
54 | default:
55 | throw new IllegalArgumentException("please input correct argument!");
56 | }
57 | }
58 |
59 | private void showLoadView() {
60 | loadProgress.setVisibility(View.VISIBLE);
61 | loadText.setText("正在加载...");
62 | }
63 |
64 | private void showLoadErrorView() {
65 | loadProgress.setVisibility(View.GONE);
66 | loadText.setText("加载失败啦...");
67 | }
68 |
69 | private void showLoadNoMoreView() {
70 | loadProgress.setVisibility(View.GONE);
71 | loadText.setText("已经到底啦");
72 | }
73 |
74 | public LoadState getCurrentState() {
75 | return mState;
76 | }
77 |
78 | public enum LoadState {
79 | LOAD,
80 | ERROR,
81 | NOMORE
82 | }
83 |
84 | }
85 |
--------------------------------------------------------------------------------
/app/src/main/java/xyz/ibat/sloth/base/webview/WebActivity.java:
--------------------------------------------------------------------------------
1 | package xyz.ibat.sloth.base.webview;
2 |
3 | import android.animation.AnimatorSet;
4 | import android.animation.ObjectAnimator;
5 | import android.annotation.SuppressLint;
6 | import android.content.Context;
7 | import android.content.Intent;
8 | import android.graphics.Bitmap;
9 | import android.os.Bundle;
10 | import android.support.v7.widget.Toolbar;
11 | import android.view.View;
12 | import android.view.animation.DecelerateInterpolator;
13 | import android.webkit.JavascriptInterface;
14 | import android.webkit.WebChromeClient;
15 | import android.webkit.WebResourceError;
16 | import android.webkit.WebResourceRequest;
17 | import android.webkit.WebSettings;
18 | import android.webkit.WebView;
19 | import android.webkit.WebViewClient;
20 | import android.widget.FrameLayout;
21 | import android.widget.LinearLayout;
22 | import android.widget.ProgressBar;
23 |
24 | import butterknife.Bind;
25 | import butterknife.ButterKnife;
26 | import xyz.ibat.sloth.R;
27 | import xyz.ibat.sloth.base.BaseActivity;
28 | import xyz.ibat.sloth.domain.main.activities.ImagePreviewActivity;
29 | import xyz.ibat.sloth.utils.T;
30 |
31 | public class WebActivity extends BaseActivity {
32 |
33 | @Bind(R.id.main_toolbar)
34 | Toolbar mainToolbar;
35 | @Bind(R.id.webview)
36 | WebView mWebView;
37 | @Bind(R.id.progress)
38 | ProgressBar mProgress;
39 | @Bind(R.id.btn_reload)
40 | FrameLayout btnReload;
41 | @Bind(R.id.load_fail_view)
42 | LinearLayout mLoadFailView;
43 |
44 | private static final String URL_TAG = "URL_TAG";
45 | private static final String TITLE_TAG = "TITLE_TAG";
46 |
47 |
48 | private String mUrl;
49 | private String mTitle;
50 | private boolean progressAnimStart = false;
51 | private boolean isReceivedError;
52 |
53 | public static void startActivity(Context context, String url) {
54 | startActivity(context, url, "Sloth");
55 | }
56 |
57 | public static void startActivity(Context context, String url, String title) {
58 | Intent intent = new Intent();
59 | intent.setClass(context, WebActivity.class);
60 | intent.putExtra(URL_TAG, url);
61 | intent.putExtra(TITLE_TAG, title);
62 | context.startActivity(intent);
63 | }
64 |
65 | @Override
66 | protected void onCreate(Bundle savedInstanceState) {
67 | super.onCreate(savedInstanceState);
68 | setContentView(R.layout.activity_web);
69 | ButterKnife.bind(this);
70 |
71 | Intent intent = getIntent();
72 | mUrl = intent.getStringExtra(URL_TAG);
73 | mTitle = intent.getStringExtra(TITLE_TAG);
74 |
75 | mainToolbar.setTitle(mTitle);
76 | setSupportActionBar(mainToolbar);
77 | mainToolbar.setNavigationIcon(R.mipmap.icon_arrow_back);
78 | mainToolbar.setNavigationOnClickListener(new View.OnClickListener() {
79 | @Override
80 | public void onClick(View v) {
81 | finish();
82 | }
83 | });
84 |
85 |
86 | mWebView.loadUrl(mUrl);
87 | initView();
88 | initWebView();
89 | }
90 |
91 | private void initView() {
92 | mProgress.setProgressDrawable(getResources()
93 | .getDrawable(R.drawable.webview_progress_bar_states));
94 |
95 | btnReload.setOnClickListener(new View.OnClickListener() {
96 | @Override
97 | public void onClick(View v) {
98 | mWebView.reload();
99 | mLoadFailView.setVisibility(View.GONE);
100 | isReceivedError = false;
101 | }
102 | });
103 |
104 | }
105 |
106 | @SuppressLint({"SetJavaScriptEnabled", "JavascriptInterface"})
107 | private void initWebView() {
108 | WebSettings webSettings = mWebView.getSettings();
109 | //设置与js交互
110 | webSettings.setJavaScriptEnabled(true);
111 | //设置是否支持缩放,默认true
112 | webSettings.setSupportZoom(false);
113 | //设置是否显示缩放工具
114 | webSettings.setBuiltInZoomControls(false);
115 |
116 |
117 | mWebView.setWebChromeClient(new SlothWebChromeClient());
118 |
119 | mWebView.setWebViewClient(new SlothWebViewClient());
120 |
121 |
122 | mWebView.addJavascriptInterface(new JSInterface(this), "webview");
123 |
124 | }
125 |
126 | private void addImageClickListner() {
127 | // 遍历所有的img节点,并添加onclick函数
128 | mWebView.loadUrl("javascript:(function(){" +
129 | "var objs = document.getElementsByTagName(\"img\"); " +
130 | "for(var i=0;i= 100) {
182 | progressAnimStart = false;
183 | mProgress.setProgress(newProgress);
184 | mProgress.setVisibility(View.GONE);
185 | } else {
186 | if (!progressAnimStart) {
187 | mProgress.setVisibility(View.VISIBLE);
188 | startProgressAnimation();
189 | }
190 | }
191 | }
192 |
193 | @Override
194 | public void onReceivedTitle(WebView view, String title) {
195 | super.onReceivedTitle(view, title);
196 | }
197 |
198 |
199 | }
200 |
201 | class SlothWebViewClient extends WebViewClient {
202 |
203 | @Override
204 | public boolean shouldOverrideUrlLoading(WebView view, String url) {
205 | //while return false means the current WebView handles the url.
206 | return super.shouldOverrideUrlLoading(view, url);
207 |
208 | }
209 |
210 | @Override
211 | public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
212 |
213 | mWebView.setVisibility(View.GONE);
214 | mLoadFailView.setVisibility(View.VISIBLE);
215 | T.show(R.string.network_error);
216 | isReceivedError = true;
217 |
218 | }
219 |
220 | @Override
221 | public void onPageFinished(WebView view, String url) {
222 | if (!isReceivedError) {
223 | mWebView.setVisibility(View.VISIBLE);
224 | }
225 | addImageClickListner();
226 | }
227 |
228 | @Override
229 | public void onPageStarted(WebView view, String url, Bitmap favicon) {
230 |
231 | super.onPageStarted(view, url, favicon);
232 | }
233 |
234 |
235 | }
236 |
237 | }
238 |
--------------------------------------------------------------------------------
/app/src/main/java/xyz/ibat/sloth/base/webview/WebFragment.java:
--------------------------------------------------------------------------------
1 | package xyz.ibat.sloth.base.webview;
2 |
3 | import android.animation.AnimatorSet;
4 | import android.animation.ObjectAnimator;
5 | import android.annotation.SuppressLint;
6 | import android.content.Context;
7 | import android.graphics.Bitmap;
8 | import android.os.Bundle;
9 | import android.support.annotation.Nullable;
10 | import android.support.v7.app.AppCompatActivity;
11 | import android.support.v7.widget.Toolbar;
12 | import android.view.LayoutInflater;
13 | import android.view.View;
14 | import android.view.ViewGroup;
15 | import android.view.animation.DecelerateInterpolator;
16 | import android.webkit.JavascriptInterface;
17 | import android.webkit.WebChromeClient;
18 | import android.webkit.WebResourceError;
19 | import android.webkit.WebResourceRequest;
20 | import android.webkit.WebSettings;
21 | import android.webkit.WebView;
22 | import android.webkit.WebViewClient;
23 | import android.widget.FrameLayout;
24 | import android.widget.LinearLayout;
25 | import android.widget.ProgressBar;
26 |
27 | import butterknife.Bind;
28 | import butterknife.ButterKnife;
29 | import xyz.ibat.sloth.R;
30 | import xyz.ibat.sloth.base.BaseFragment;
31 | import xyz.ibat.sloth.domain.main.activities.ImagePreviewActivity;
32 | import xyz.ibat.sloth.utils.T;
33 |
34 | /**
35 | * Created by DongJr on 2017/3/16.
36 | */
37 |
38 | public class WebFragment extends BaseFragment {
39 |
40 | @Bind(R.id.progress)
41 | ProgressBar mProgress;
42 | @Bind(R.id.webview)
43 | WebView mWebView;
44 | @Bind(R.id.btn_reload)
45 | FrameLayout btnReload;
46 | @Bind(R.id.load_fail_view)
47 | LinearLayout mLoadFailView;
48 | @Bind(R.id.main_toolbar)
49 | Toolbar mainToolbar;
50 | private View mRootView;
51 |
52 | public static final String URL_TAG = "URL_TAG";
53 |
54 | private String mUrl;
55 | private boolean progressAnimStart = false;
56 | private boolean isReceivedError;
57 |
58 | @Nullable
59 | @Override
60 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
61 | mRootView = inflater.inflate(R.layout.fragment_web, container, false);
62 | ButterKnife.bind(this, mRootView);
63 |
64 | ((AppCompatActivity) getActivity()).setSupportActionBar(mainToolbar);
65 |
66 | return mRootView;
67 | }
68 |
69 | @Override
70 | public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
71 | Bundle bundle = getArguments();
72 | mUrl = bundle.getString(URL_TAG);
73 |
74 | if (mUrl != null) {
75 | mWebView.loadUrl(mUrl);
76 | initView();
77 | initWebView();
78 | }
79 | }
80 |
81 | private void initView() {
82 | mProgress.setProgressDrawable(getResources()
83 | .getDrawable(R.drawable.webview_progress_bar_states));
84 |
85 | btnReload.setOnClickListener(new View.OnClickListener() {
86 | @Override
87 | public void onClick(View v) {
88 | mWebView.reload();
89 | mLoadFailView.setVisibility(View.GONE);
90 | isReceivedError = false;
91 | }
92 | });
93 |
94 | }
95 |
96 | @SuppressLint({"SetJavaScriptEnabled", "JavascriptInterface"})
97 | private void initWebView() {
98 | WebSettings webSettings = mWebView.getSettings();
99 | //设置与js交互
100 | webSettings.setJavaScriptEnabled(true);
101 | //设置是否支持缩放,默认true
102 | webSettings.setSupportZoom(false);
103 | //设置是否显示缩放工具
104 | webSettings.setBuiltInZoomControls(false);
105 |
106 |
107 | mWebView.setWebChromeClient(new SlothWebChromeClient());
108 |
109 | mWebView.setWebViewClient(new SlothWebViewClient());
110 |
111 |
112 | mWebView.addJavascriptInterface(new JSInterface(getContext()), "webview");
113 |
114 | }
115 |
116 | private void addImageClickListner() {
117 | // 遍历所有的img节点,并添加onclick函数
118 | mWebView.loadUrl("javascript:(function(){" +
119 | "var objs = document.getElementsByTagName(\"img\"); " +
120 | "for(var i=0;i= 100) {
169 | progressAnimStart = false;
170 | mProgress.setProgress(newProgress);
171 | mProgress.setVisibility(View.GONE);
172 | } else {
173 | if (!progressAnimStart) {
174 | mProgress.setVisibility(View.VISIBLE);
175 | startProgressAnimation();
176 | }
177 | }
178 | }
179 |
180 | @Override
181 | public void onReceivedTitle(WebView view, String title) {
182 | super.onReceivedTitle(view, title);
183 | }
184 |
185 |
186 | }
187 |
188 | class SlothWebViewClient extends WebViewClient {
189 |
190 | @Override
191 | public boolean shouldOverrideUrlLoading(WebView view, String url) {
192 |
193 | WebActivity.startActivity(getContext(), url);
194 | //while return false means the current WebView handles the url.
195 | return true;
196 | }
197 |
198 | @Override
199 | public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
200 |
201 | mWebView.setVisibility(View.GONE);
202 | mLoadFailView.setVisibility(View.VISIBLE);
203 | T.show(R.string.network_error);
204 | isReceivedError = true;
205 |
206 | }
207 |
208 | @Override
209 | public void onPageFinished(WebView view, String url) {
210 | if (!isReceivedError) {
211 | mWebView.setVisibility(View.VISIBLE);
212 | }
213 | addImageClickListner();
214 | }
215 |
216 | @Override
217 | public void onPageStarted(WebView view, String url, Bitmap favicon) {
218 |
219 | super.onPageStarted(view, url, favicon);
220 | }
221 |
222 |
223 | }
224 | }
225 |
--------------------------------------------------------------------------------
/app/src/main/java/xyz/ibat/sloth/domain/info/InfoFragment.java:
--------------------------------------------------------------------------------
1 | package xyz.ibat.sloth.domain.info;
2 |
3 | import android.os.Bundle;
4 | import android.support.annotation.Nullable;
5 | import android.support.v7.widget.Toolbar;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 |
10 | import butterknife.Bind;
11 | import butterknife.ButterKnife;
12 | import xyz.ibat.sloth.R;
13 | import xyz.ibat.sloth.base.BaseActivity;
14 | import xyz.ibat.sloth.base.BaseFragment;
15 |
16 | /**
17 | * Created by DongJr on 2016/4/15.
18 | */
19 | public class InfoFragment extends BaseFragment {
20 | @Bind(R.id.main_toolbar)
21 | Toolbar mainToolbar;
22 |
23 | @Override
24 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
25 | View view = inflater.inflate(R.layout.fragment_tab_info, container, false);
26 | ButterKnife.bind(this, view);
27 | return view;
28 | }
29 |
30 |
31 | @Override
32 | public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
33 | ((BaseActivity) getActivity()).setSupportActionBar(mainToolbar);
34 | }
35 |
36 | @Override
37 | public void onDestroyView() {
38 | super.onDestroyView();
39 | ButterKnife.unbind(this);
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/app/src/main/java/xyz/ibat/sloth/domain/main/activities/FriendActivity.java:
--------------------------------------------------------------------------------
1 | package xyz.ibat.sloth.domain.main.activities;
2 |
3 | import android.os.Bundle;
4 | import android.support.v7.app.AppCompatActivity;
5 | import android.view.MotionEvent;
6 | import android.view.View;
7 |
8 | import butterknife.Bind;
9 | import butterknife.ButterKnife;
10 | import xyz.ibat.sloth.R;
11 |
12 | /**
13 | * create by DongJr 2016/05/04
14 | */
15 | public class FriendActivity extends AppCompatActivity {
16 |
17 | @Bind(R.id.first)
18 | View first;
19 | @Bind(R.id.second)
20 | View second;
21 |
22 |
23 | private float startY;
24 | private float endY;
25 | @Override
26 | protected void onCreate(Bundle savedInstanceState) {
27 | super.onCreate(savedInstanceState);
28 | setContentView(R.layout.activity_friend);
29 | ButterKnife.bind(this);
30 | }
31 |
32 | @Override
33 | public boolean onTouchEvent(MotionEvent event) {
34 | switch (event.getAction()){
35 | case MotionEvent.ACTION_DOWN:
36 | startY = event.getY();
37 | break;
38 | case MotionEvent.ACTION_MOVE:
39 | endY = event.getY();
40 | float moveY = endY - startY;
41 | first.setY(moveY);
42 | break;
43 | }
44 | return true;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/app/src/main/java/xyz/ibat/sloth/domain/main/activities/ImagePreviewActivity.java:
--------------------------------------------------------------------------------
1 | package xyz.ibat.sloth.domain.main.activities;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.os.Build;
6 | import android.os.Bundle;
7 | import android.transition.Transition;
8 | import android.transition.TransitionInflater;
9 | import android.view.Window;
10 |
11 | import butterknife.Bind;
12 | import butterknife.ButterKnife;
13 | import xyz.ibat.sloth.R;
14 | import xyz.ibat.sloth.base.BaseActivity;
15 | import xyz.ibat.sloth.network.ImageLoader;
16 | import xyz.ibat.sloth.view.widget.ZoomImageView;
17 |
18 | public class ImagePreviewActivity extends BaseActivity {
19 |
20 | @Bind(R.id.image)
21 | ZoomImageView image;
22 |
23 | public static final String URL_TAG = "URL_TAG";
24 |
25 | public static final String SCALETYPE_TAG = "SCALETYPE_TAG";
26 |
27 | public static final String SCALETYPE_CENTERCROP = "CENTER_CROP";
28 |
29 | public static final String SCALETYPE_FITXY = "FIT_XY";
30 |
31 | private String SCALETYPE = SCALETYPE_FITXY;
32 |
33 | private String url;
34 |
35 | public static void startActivity(Context context, String url) {
36 | startActivity(context, url, SCALETYPE_FITXY);
37 | }
38 |
39 | public static void startActivity(Context context, String url, String scropType) {
40 | Intent intent = new Intent();
41 | intent.setClass(context, ImagePreviewActivity.class);
42 | intent.putExtra(URL_TAG, url);
43 | intent.putExtra(SCALETYPE_TAG, scropType);
44 | context.startActivity(intent);
45 | }
46 |
47 |
48 | @Override
49 | protected void onCreate(Bundle savedInstanceState) {
50 | getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
51 | super.onCreate(savedInstanceState);
52 | setContentView(R.layout.activity_image_preview);
53 | ButterKnife.bind(this);
54 |
55 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
56 | Transition explode = TransitionInflater.from(this).inflateTransition(R.transition.fade);
57 | //退出时使用
58 | getWindow().setExitTransition(explode);
59 | //第一次进入时使用
60 | getWindow().setEnterTransition(explode);
61 | //再次进入时使用
62 | getWindow().setReenterTransition(explode);
63 | }
64 |
65 | Intent intent = getIntent();
66 | url = intent.getStringExtra(URL_TAG);
67 | SCALETYPE = intent.getStringExtra(SCALETYPE_TAG);
68 |
69 | if (SCALETYPE_FITXY.equals(SCALETYPE)) {
70 | // image.setScaleType(ImageView.ScaleType.FIT_XY);
71 | } else if (SCALETYPE_CENTERCROP.equals(SCALETYPE)) {
72 | // image.setScaleType(ImageView.ScaleType.CENTER_CROP);
73 | } else {
74 | // image.setScaleType(ImageView.ScaleType.CENTER_CROP);
75 | }
76 |
77 | ImageLoader.load(url, image);
78 |
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/app/src/main/java/xyz/ibat/sloth/domain/main/activities/MainActivity.java:
--------------------------------------------------------------------------------
1 | package xyz.ibat.sloth.domain.main.activities;
2 |
3 | import android.os.Bundle;
4 | import android.support.v4.app.FragmentManager;
5 | import android.support.v4.app.FragmentTransaction;
6 |
7 | import butterknife.ButterKnife;
8 | import xyz.ibat.sloth.R;
9 | import xyz.ibat.sloth.base.BaseActivity;
10 | import xyz.ibat.sloth.base.TabsFragment;
11 |
12 | /**
13 | * create by DongJr 2016/03/31
14 | * 图片素材,参考 https://design.google.com/icons/
15 | * 子模块rooter实现: http://www.jianshu.com/p/7cb2cc9b726a?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io
16 | */
17 | public class MainActivity extends BaseActivity {
18 |
19 |
20 |
21 | @Override
22 | protected void onCreate(Bundle savedInstanceState) {
23 | super.onCreate(savedInstanceState);
24 | setContentView(R.layout.activity_main);
25 | ButterKnife.bind(this);
26 | initFragment();
27 | }
28 |
29 | private void initFragment() {
30 | FragmentManager manager = getSupportFragmentManager();
31 | FragmentTransaction transaction = manager.beginTransaction();
32 | transaction.replace(R.id.fl_root,new TabsFragment());
33 | transaction.commitAllowingStateLoss();
34 | }
35 |
36 |
37 |
38 |
39 | /**
40 | * Activity彻底运行起来之后的回调
41 | * Called when activity start-up is complete
42 | * (after onStart() and onRestoreInstanceState(Bundle) have been called).
43 | */
44 | @Override
45 | protected void onPostCreate(Bundle savedInstanceState) {
46 | super.onPostCreate(savedInstanceState);
47 | //箭头旋转动画的关键
48 | // mDrawerToggle.syncState();
49 | }
50 |
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/app/src/main/java/xyz/ibat/sloth/domain/main/activities/MeiziActivity.java:
--------------------------------------------------------------------------------
1 | package xyz.ibat.sloth.domain.main.activities;
2 |
3 | import android.app.ActivityOptions;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.os.Build;
7 | import android.os.Bundle;
8 | import android.support.v4.widget.SwipeRefreshLayout;
9 | import android.support.v7.widget.RecyclerView;
10 | import android.support.v7.widget.StaggeredGridLayoutManager;
11 | import android.support.v7.widget.Toolbar;
12 | import android.view.View;
13 | import android.view.ViewGroup;
14 | import android.widget.ImageView;
15 |
16 | import com.zhy.adapter.recyclerview.CommonAdapter;
17 | import com.zhy.adapter.recyclerview.MultiItemTypeAdapter;
18 | import com.zhy.adapter.recyclerview.base.ViewHolder;
19 | import com.zhy.adapter.recyclerview.wrapper.LoadMoreWrapper;
20 |
21 | import java.util.ArrayList;
22 | import java.util.List;
23 |
24 | import butterknife.Bind;
25 | import butterknife.ButterKnife;
26 | import rx.Subscriber;
27 | import xyz.ibat.sloth.R;
28 | import xyz.ibat.sloth.base.BaseActivity;
29 | import xyz.ibat.sloth.base.adapter.NewLoadMoreWrapper;
30 | import xyz.ibat.sloth.domain.main.model.DataModel;
31 | import xyz.ibat.sloth.network.ImageLoader;
32 | import xyz.ibat.sloth.network.RetrofitFactory;
33 | import xyz.ibat.sloth.utils.DensityUtil;
34 | import xyz.ibat.sloth.utils.T;
35 |
36 | import static xyz.ibat.sloth.R.id.meizi;
37 |
38 | public class MeiziActivity extends BaseActivity implements SwipeRefreshLayout.OnRefreshListener {
39 |
40 |
41 | @Bind(R.id.main_toolbar)
42 | Toolbar mainToolbar;
43 | @Bind(R.id.recyclerView)
44 | RecyclerView recyclerView;
45 | @Bind(R.id.refresh)
46 | SwipeRefreshLayout mRefresh;
47 |
48 | private CommonAdapter mAdapter;
49 | private NewLoadMoreWrapper mLoadMoreWrapper;
50 | private List mResultsList = new ArrayList<>();
51 |
52 | int mPageIndex = 1;
53 |
54 | public static void startActivity(Context context) {
55 | Intent intent = new Intent();
56 | intent.setClass(context, MeiziActivity.class);
57 | context.startActivity(intent);
58 | }
59 |
60 | @Override
61 | protected void onCreate(Bundle savedInstanceState) {
62 | super.onCreate(savedInstanceState);
63 | setContentView(R.layout.activity_meizi);
64 | ButterKnife.bind(this);
65 |
66 |
67 | mainToolbar.setTitle("妹纸");
68 | setSupportActionBar(mainToolbar);
69 | mainToolbar.setNavigationIcon(R.mipmap.icon_arrow_back);
70 | mainToolbar.setNavigationOnClickListener(new View.OnClickListener() {
71 | @Override
72 | public void onClick(View v) {
73 | finish();
74 | }
75 | });
76 | mRefresh.setColorSchemeResources(android.R.color.holo_blue_bright);
77 | mRefresh.setOnRefreshListener(this);
78 |
79 | StaggeredGridLayoutManager sgm = new StaggeredGridLayoutManager
80 | (2, StaggeredGridLayoutManager.VERTICAL);
81 |
82 | recyclerView.setLayoutManager(sgm);
83 | initAdapter();
84 | requestData();
85 | }
86 |
87 | private void initAdapter() {
88 | mAdapter = new CommonAdapter(this, R.layout.item_meizi, mResultsList) {
89 | @Override
90 | protected void convert(ViewHolder holder, DataModel.ResultsBean resultsBean, int position) {
91 | ImageView view = (ImageView) holder.getView(meizi);
92 | ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
93 | layoutParams.height = (int) (DensityUtil.dp2px(160) + Math.random() * 200f);
94 |
95 | ImageLoader.load(resultsBean.getUrl(), view);
96 | }
97 | };
98 | mLoadMoreWrapper = new NewLoadMoreWrapper(this, mAdapter, recyclerView);
99 | mLoadMoreWrapper.setLoadMoreView(R.layout.default_loading);
100 | mLoadMoreWrapper.setOnLoadMoreListener(new LoadMoreWrapper.OnLoadMoreListener() {
101 | @Override
102 | public void onLoadMoreRequested() {
103 | mPageIndex++;
104 | requestData();
105 | }
106 | });
107 |
108 | recyclerView.setAdapter(mLoadMoreWrapper);
109 |
110 | mAdapter.setOnItemClickListener(new MultiItemTypeAdapter.OnItemClickListener() {
111 | @Override
112 | public void onItemClick(View view, RecyclerView.ViewHolder holder, int position) {
113 | Intent intent = new Intent();
114 | intent.setClass(MeiziActivity.this, ImagePreviewActivity.class);
115 | intent.putExtra(ImagePreviewActivity.URL_TAG, mResultsList.get(position).getUrl());
116 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
117 | startActivity(intent, ActivityOptions.makeSceneTransitionAnimation
118 | (MeiziActivity.this).toBundle());
119 | } else {
120 | startActivity(intent);
121 | }
122 | }
123 |
124 | @Override
125 | public boolean onItemLongClick(View view, RecyclerView.ViewHolder holder, int position) {
126 | return false;
127 | }
128 | });
129 |
130 | }
131 |
132 |
133 | private void requestData() {
134 | Subscriber subscriber = new Subscriber() {
135 | @Override
136 | public void onCompleted() {
137 | if (mRefresh != null) {
138 | mRefresh.setRefreshing(false);
139 | }
140 | }
141 |
142 | @Override
143 | public void onError(Throwable e) {
144 | mLoadMoreWrapper.setLoadState(NewLoadMoreWrapper.LoadState.ERROR);
145 | T.show(e.getMessage());
146 | }
147 |
148 | @Override
149 | public void onNext(DataModel homeDataModel) {
150 |
151 | if (mPageIndex == 1) {
152 | mResultsList.clear();
153 | }
154 | List results = homeDataModel.getResults();
155 | if (results.size() < 10) {
156 | mLoadMoreWrapper.setLoadState(NewLoadMoreWrapper.LoadState.NOMORE);
157 | } else {
158 | mLoadMoreWrapper.setLoadState(NewLoadMoreWrapper.LoadState.LOAD);
159 | }
160 | mResultsList.addAll(results);
161 | mLoadMoreWrapper.notifyDataSetChanged();
162 | }
163 | };
164 |
165 | RetrofitFactory.getInstance().getAndroidData(subscriber, "福利", mPageIndex);
166 | }
167 |
168 |
169 | @Override
170 | public void onRefresh() {
171 | mPageIndex = 1;
172 | requestData();
173 | }
174 | }
175 |
--------------------------------------------------------------------------------
/app/src/main/java/xyz/ibat/sloth/domain/main/activities/MessageActivity.java:
--------------------------------------------------------------------------------
1 | package xyz.ibat.sloth.domain.main.activities;
2 |
3 | import android.os.Bundle;
4 | import android.support.design.widget.AppBarLayout;
5 | import android.support.design.widget.CollapsingToolbarLayout;
6 | import android.support.design.widget.CoordinatorLayout;
7 | import android.support.v7.app.AppCompatActivity;
8 | import android.support.v7.widget.Toolbar;
9 | import android.view.View;
10 | import android.widget.ImageView;
11 |
12 | import butterknife.Bind;
13 | import butterknife.ButterKnife;
14 | import xyz.ibat.sloth.R;
15 | /**
16 | * create by DongJr 2016/04/29
17 | */
18 | public class MessageActivity extends AppCompatActivity {
19 |
20 | @Bind(R.id.backdrop)
21 | ImageView backdrop;
22 | @Bind(R.id.toolbar)
23 | Toolbar toolbar;
24 | @Bind(R.id.collapsing_toolbar)
25 | CollapsingToolbarLayout collapsingToolbar;
26 | @Bind(R.id.appbar)
27 | AppBarLayout appbar;
28 | @Bind(R.id.main_content)
29 | CoordinatorLayout mainContent;
30 |
31 | // 使用CollapsingToolbarLayout实现折叠效果,需要注意3点
32 | // 1. AppBarLayout的高度固定
33 | // 2. CollapsingToolbarLayout的子视图设置layout_collapseMode属性
34 | // 3. 关联悬浮视图设置app:layout_anchor,app:layout_anchorGravity属性
35 | @Override
36 | protected void onCreate(Bundle savedInstanceState) {
37 | super.onCreate(savedInstanceState);
38 | setContentView(R.layout.activity_message);
39 | ButterKnife.bind(this);
40 | setSupportActionBar(toolbar);
41 | toolbar.setTitle("Sloth");
42 | toolbar.setNavigationIcon(R.mipmap.icon_arrow_back);
43 | toolbar.setNavigationOnClickListener(new View.OnClickListener() {
44 | @Override
45 | public void onClick(View view) {
46 | finish();
47 | }
48 | });
49 | }
50 |
51 |
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/app/src/main/java/xyz/ibat/sloth/domain/main/adapter/HomeAdapter.java:
--------------------------------------------------------------------------------
1 | package xyz.ibat.sloth.domain.main.adapter;
2 |
3 | import android.content.Context;
4 | import android.support.v7.widget.RecyclerView;
5 | import android.view.ViewGroup;
6 |
7 | import java.util.ArrayList;
8 | import java.util.List;
9 |
10 | import xyz.ibat.sloth.domain.main.model.DataModel;
11 |
12 | /**
13 | * Created by DongJr on 2017/1/13.
14 | */
15 |
16 | public class HomeAdapter extends RecyclerView.Adapter {
17 |
18 | private Context mContext;
19 |
20 | private List mList = new ArrayList<>();
21 |
22 | public HomeAdapter(Context context) {
23 | mContext = context;
24 | }
25 |
26 | public HomeAdapter(Context context, DataModel model) {
27 | mContext = context;
28 | List list = model.getResults();
29 | mList.addAll(list);
30 | }
31 |
32 | public void setData(DataModel model) {
33 | mList.clear();
34 | mList.addAll(model.getResults());
35 | notifyDataSetChanged();
36 | }
37 |
38 | @Override
39 | public HomeHolder onCreateViewHolder(ViewGroup parent, int viewType) {
40 | return HomeHolder.newIntance(mContext, parent);
41 | }
42 |
43 | @Override
44 | public void onBindViewHolder(HomeHolder holder, int position) {
45 | if (mList != null) {
46 | holder.getView(mList.get(position));
47 | }
48 | }
49 |
50 | @Override
51 | public int getItemCount() {
52 | return mList.size();
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/app/src/main/java/xyz/ibat/sloth/domain/main/adapter/HomeHolder.java:
--------------------------------------------------------------------------------
1 | package xyz.ibat.sloth.domain.main.adapter;
2 |
3 | import android.content.Context;
4 | import android.support.v7.widget.RecyclerView;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 | import android.widget.TextView;
9 |
10 | import xyz.ibat.sloth.R;
11 | import xyz.ibat.sloth.domain.main.model.DataModel;
12 |
13 | /**
14 | * Created by DongJr on 2017/1/13.
15 | */
16 |
17 | public class HomeHolder extends RecyclerView.ViewHolder {
18 |
19 | private TextView mTitle;
20 | private TextView mDate;
21 | private TextView mAuthor;
22 |
23 | public HomeHolder(View itemView) {
24 | super(itemView);
25 | mTitle = (TextView) itemView.findViewById(R.id.tv_title);
26 | mDate = (TextView) itemView.findViewById(R.id.tv_date);
27 | mAuthor = (TextView) itemView.findViewById(R.id.tv_author);
28 | }
29 |
30 | public static HomeHolder newIntance(Context context, ViewGroup parent) {
31 | View view = LayoutInflater.from(context).inflate(R.layout.item_fragment_home, parent, false);
32 | return new HomeHolder(view);
33 | }
34 |
35 | public void getView(DataModel.ResultsBean bean) {
36 | mTitle.setText(bean.getDesc());
37 | mDate.setText(bean.getPublishedAt());
38 | mAuthor.setText(bean.getWho());
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/app/src/main/java/xyz/ibat/sloth/domain/main/adapter/MeiziAdapter.java:
--------------------------------------------------------------------------------
1 | package xyz.ibat.sloth.domain.main.adapter;
2 |
3 | import android.content.Context;
4 | import android.support.v7.widget.RecyclerView;
5 | import android.view.ViewGroup;
6 |
7 | import java.util.ArrayList;
8 | import java.util.List;
9 |
10 | import xyz.ibat.sloth.domain.main.model.DataModel;
11 |
12 | /**
13 | * Created by jerry on 2017/1/14.
14 | */
15 |
16 | public class MeiziAdapter extends RecyclerView.Adapter{
17 |
18 | private Context mContext;
19 |
20 | private List mList = new ArrayList<>();
21 |
22 | public MeiziAdapter(Context context) {
23 | mContext = context;
24 | }
25 |
26 | public MeiziAdapter(Context context, DataModel model) {
27 | mContext = context;
28 | List list = model.getResults();
29 | mList.addAll(list);
30 | }
31 |
32 | public void setData(DataModel model) {
33 | mList.clear();
34 | mList.addAll(model.getResults());
35 | notifyDataSetChanged();
36 | }
37 |
38 | @Override
39 | public MeiziHolder onCreateViewHolder(ViewGroup parent, int viewType) {
40 | return MeiziHolder.newIntance(mContext,parent);
41 | }
42 |
43 | @Override
44 | public void onBindViewHolder(MeiziHolder holder, int position) {
45 | holder.getView(mList.get(position));
46 | }
47 |
48 | @Override
49 | public int getItemCount() {
50 | return mList.size();
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/app/src/main/java/xyz/ibat/sloth/domain/main/adapter/MeiziHolder.java:
--------------------------------------------------------------------------------
1 | package xyz.ibat.sloth.domain.main.adapter;
2 |
3 | import android.content.Context;
4 | import android.support.v7.widget.RecyclerView;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 | import android.widget.ImageView;
9 |
10 | import xyz.ibat.sloth.R;
11 | import xyz.ibat.sloth.domain.main.activities.ImagePreviewActivity;
12 | import xyz.ibat.sloth.domain.main.model.DataModel;
13 | import xyz.ibat.sloth.network.ImageLoader;
14 | import xyz.ibat.sloth.utils.DensityUtil;
15 |
16 | /**
17 | * Created by jerry on 2017/1/14.
18 | */
19 |
20 | public class MeiziHolder extends RecyclerView.ViewHolder{
21 |
22 | private ImageView meizi;
23 |
24 | public MeiziHolder(View itemView) {
25 | super(itemView);
26 | meizi = (ImageView) itemView.findViewById(R.id.meizi);
27 | }
28 |
29 | public static MeiziHolder newIntance(Context context, ViewGroup parent) {
30 | View view = LayoutInflater.from(context).inflate(R.layout.item_meizi, parent, false);
31 | return new MeiziHolder(view);
32 | }
33 |
34 | public void getView(final DataModel.ResultsBean bean) {
35 |
36 | ViewGroup.LayoutParams layoutParams = meizi.getLayoutParams();
37 | layoutParams.height = (int) (DensityUtil.dp2px(160) + Math.random()*200f);
38 | ImageLoader.load(bean.getUrl(),meizi);
39 |
40 | meizi.setOnClickListener(new View.OnClickListener() {
41 | @Override
42 | public void onClick(View v) {
43 | ImagePreviewActivity.startActivity(v.getContext(),bean.getUrl());
44 | }
45 | });
46 |
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/app/src/main/java/xyz/ibat/sloth/domain/main/fragments/DataFragment.java:
--------------------------------------------------------------------------------
1 | package xyz.ibat.sloth.domain.main.fragments;
2 |
3 | import android.os.Bundle;
4 | import android.support.design.widget.FloatingActionButton;
5 | import android.support.v4.app.Fragment;
6 | import android.support.v4.widget.SwipeRefreshLayout;
7 | import android.support.v7.widget.LinearLayoutManager;
8 | import android.support.v7.widget.RecyclerView;
9 | import android.view.LayoutInflater;
10 | import android.view.View;
11 | import android.view.ViewGroup;
12 |
13 | import com.zhy.adapter.recyclerview.CommonAdapter;
14 | import com.zhy.adapter.recyclerview.MultiItemTypeAdapter;
15 | import com.zhy.adapter.recyclerview.base.ViewHolder;
16 | import com.zhy.adapter.recyclerview.wrapper.LoadMoreWrapper;
17 |
18 | import java.util.ArrayList;
19 | import java.util.List;
20 | import java.util.Random;
21 |
22 | import butterknife.Bind;
23 | import butterknife.ButterKnife;
24 | import rx.Subscriber;
25 | import xyz.ibat.sloth.R;
26 | import xyz.ibat.sloth.base.adapter.NewLoadMoreWrapper;
27 | import xyz.ibat.sloth.base.webview.WebActivity;
28 | import xyz.ibat.sloth.domain.main.model.DataModel;
29 | import xyz.ibat.sloth.network.RetrofitFactory;
30 | import xyz.ibat.sloth.utils.T;
31 | import xyz.ibat.sloth.view.SlothRecycler;
32 | import xyz.ibat.sloth.view.behavior.FABScrollBehavior;
33 |
34 | /**
35 | * Created by DongJr on 2016/03/31
36 | */
37 | public class DataFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
38 |
39 | @Bind(R.id.recycler_one)
40 | SlothRecycler mRecyclerView;
41 | @Bind(R.id.refresh_one)
42 | SwipeRefreshLayout mRefresh;
43 | @Bind(R.id.fab)
44 | FloatingActionButton mFab;
45 |
46 | private CommonAdapter mAdapter;
47 | private NewLoadMoreWrapper mLoadMoreWrapper;
48 |
49 | public static String TYPE_TAG = "TYPE_TAG";
50 | private int mPageIndex = 1;
51 | private String mType;
52 |
53 | private List mResultsList = new ArrayList<>();
54 |
55 | @Override
56 | public View onCreateView(LayoutInflater inflater, ViewGroup container,
57 | Bundle savedInstanceState) {
58 | View view = inflater.inflate(R.layout.fragment_one, container, false);
59 | ButterKnife.bind(this, view);
60 | return view;
61 | }
62 |
63 | @Override
64 | public void onViewCreated(View view, Bundle savedInstanceState) {
65 | Bundle arguments = getArguments();
66 |
67 | if (arguments != null) {
68 | mType = arguments.getString(TYPE_TAG);
69 | }
70 |
71 | mRefresh.setColorSchemeResources(android.R.color.holo_blue_bright);
72 | mRefresh.setOnRefreshListener(this);
73 |
74 | mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false));
75 |
76 | initAdapter();
77 |
78 | requestData();
79 |
80 | mRecyclerView.addOnScrollListener(new FABScrollBehavior(mFab));
81 |
82 | mFab.setOnClickListener(new View.OnClickListener() {
83 | @Override
84 | public void onClick(View v) {
85 | if (!mResultsList.isEmpty()) {
86 | Random random = new Random();
87 | WebActivity.startActivity(getContext()
88 | , mResultsList.get(random.nextInt(mResultsList.size())).getUrl()
89 | , "随机看");
90 | }
91 | }
92 | });
93 |
94 | }
95 |
96 | private void initAdapter() {
97 | mAdapter = new CommonAdapter(getContext(), R.layout.item_fragment_home, mResultsList) {
98 | @Override
99 | protected void convert(ViewHolder holder, DataModel.ResultsBean resultsBean, int position) {
100 | holder.setText(R.id.tv_title, resultsBean.getDesc())
101 | .setText(R.id.tv_author, resultsBean.getWho())
102 | .setText(R.id.tv_date, resultsBean.getCreatedAt());
103 | }
104 | };
105 | mLoadMoreWrapper = new NewLoadMoreWrapper(getContext(), mAdapter, mRecyclerView);
106 | mLoadMoreWrapper.setOnLoadMoreListener(new LoadMoreWrapper.OnLoadMoreListener() {
107 | @Override
108 | public void onLoadMoreRequested() {
109 | mPageIndex++;
110 | requestData();
111 | }
112 | });
113 |
114 | mRecyclerView.setAdapter(mLoadMoreWrapper);
115 |
116 | mAdapter.setOnItemClickListener(new MultiItemTypeAdapter.OnItemClickListener() {
117 | @Override
118 | public void onItemClick(View view, RecyclerView.ViewHolder holder, int position) {
119 | DataModel.ResultsBean resultsBean = mResultsList.get(position);
120 | WebActivity.startActivity(getContext()
121 | , resultsBean.getUrl(), resultsBean.getDesc());
122 | }
123 |
124 | @Override
125 | public boolean onItemLongClick(View view, RecyclerView.ViewHolder holder, int position) {
126 | return false;
127 | }
128 | });
129 |
130 | }
131 |
132 | private void requestData() {
133 | RetrofitFactory.getInstance().getAndroidData(new Subscriber() {
134 | @Override
135 | public void onCompleted() {
136 | if (mRefresh != null) {
137 | mRefresh.setRefreshing(false);
138 | }
139 | }
140 |
141 | @Override
142 | public void onError(Throwable e) {
143 | mLoadMoreWrapper.setLoadState(NewLoadMoreWrapper.LoadState.ERROR);
144 | T.show(e.getMessage());
145 | }
146 |
147 | @Override
148 | public void onNext(DataModel model) {
149 | if (mPageIndex == 1) {
150 | mResultsList.clear();
151 | }
152 | List results = model.getResults();
153 | if (results.size() < 10) {
154 | mLoadMoreWrapper.setLoadState(NewLoadMoreWrapper.LoadState.NOMORE);
155 | } else {
156 | mLoadMoreWrapper.setLoadState(NewLoadMoreWrapper.LoadState.LOAD);
157 | }
158 | mResultsList.addAll(results);
159 | mLoadMoreWrapper.notifyDataSetChanged();
160 |
161 | }
162 | }, mType, mPageIndex);
163 | }
164 |
165 | @Override
166 | public void onDestroyView() {
167 | super.onDestroyView();
168 | ButterKnife.unbind(this);
169 | }
170 |
171 | @Override
172 | public void onRefresh() {
173 | mPageIndex = 1;
174 | requestData();
175 | }
176 |
177 | }
178 |
--------------------------------------------------------------------------------
/app/src/main/java/xyz/ibat/sloth/domain/main/model/DataModel.java:
--------------------------------------------------------------------------------
1 | package xyz.ibat.sloth.domain.main.model;
2 |
3 | import java.util.List;
4 |
5 | /**
6 | * Created by DongJr on 2017/1/13.
7 | */
8 |
9 | public class DataModel {
10 |
11 |
12 | /**
13 | * error : false
14 | * results : [{"_id":"5875e66c421aa9315ea79931","createdAt":"2017-01-11T16:01:48.998Z","desc":"在Chrome DevTools内查看Android设备上所有HTTP(S)流量","images":["http://img.gank.io/b33cc839-18de-48e0-8644-089e6986609a","http://img.gank.io/a4ce3373-2f20-4fe5-bbcf-9f6dc3847591"],"publishedAt":"2017-01-12T11:30:59.369Z","source":"web","type":"Android","url":"https://github.com/misakuo/Dream-Catcher","used":true,"who":"moxun"},{"_id":"5876e940421aa93161103df1","createdAt":"2017-01-12T10:26:08.237Z","desc":"类似 Facebook 加载时,条目的闪烁效果,酷酷的。","images":["http://img.gank.io/985a1011-632f-40c1-9ca5-1bd9cb17a69f","http://img.gank.io/c5c916fc-b391-40ec-9962-df8588f23cba"],"publishedAt":"2017-01-12T11:30:59.369Z","source":"chrome","type":"Android","url":"https://github.com/sharish/ShimmerRecyclerView","used":true,"who":"代码家"},{"_id":"5872fb61421aa9315bfbe843","createdAt":"2017-01-09T10:54:25.659Z","desc":"android多图选择 图片/视频 单选or多选,以及视频录制。","images":["http://img.gank.io/eafb5329-c252-42f3-a8cc-48f6b247c9f8","http://img.gank.io/f58b7772-ce21-4875-b709-2f21ba2d2c3f"],"publishedAt":"2017-01-11T12:05:20.787Z","source":"web","type":"Android","url":"https://github.com/LuckSiege/PictureSelector","used":true,"who":null},{"_id":"587469c5421aa9316407fb95","createdAt":"2017-01-10T12:57:41.909Z","desc":"top-5-android-libraries-january-2017","publishedAt":"2017-01-11T12:05:20.787Z","source":"web","type":"Android","url":"https://medium.cobeisfresh.com/top-5-android-libraries-january-2017-53e217783fc9","used":true,"who":"kg"},{"_id":"58759363421aa93161103ddd","createdAt":"2017-01-11T10:07:31.126Z","desc":"Android 多渠道打包的 Android Studio / IDEA 插件","images":["http://img.gank.io/e9e0de53-aaba-4e2b-a123-cdaac87eeb56"],"publishedAt":"2017-01-11T12:05:20.787Z","source":"web","type":"Android","url":"https://github.com/nukc/ApkMultiChannelPlugin","used":true,"who":"C君"},{"_id":"58759c0d421aa93161103ddf","createdAt":"2017-01-11T10:44:29.208Z","desc":"Android 状态切换按钮效果","images":["http://img.gank.io/10c58071-a555-4e1f-84ff-8220644a35e9"],"publishedAt":"2017-01-11T12:05:20.787Z","source":"chrome","type":"Android","url":"https://github.com/zagum/Android-SwitchIcon","used":true,"who":"代码家"},{"_id":"58759c56421aa9315bfbe856","createdAt":"2017-01-11T10:45:42.636Z","desc":"Android 跑马灯效果,适合做个小广告,通知之类的。","images":["http://img.gank.io/ba7b29c2-55d9-4cc5-9861-ffc19d332950"],"publishedAt":"2017-01-11T12:05:20.787Z","source":"chrome","type":"Android","url":"https://github.com/gongwen/MarqueeViewLibrary","used":true,"who":"代码家"},{"_id":"58732679421aa93161103dd0","createdAt":"2017-01-09T13:58:17.708Z","desc":"Tinker接入及源码分析,从简单介绍到如何接入再到加载补丁、合成补丁源码分析","images":["http://img.gank.io/1408b5b4-23b3-410e-80cb-9cb096d1ad8a"],"publishedAt":"2017-01-10T11:33:19.525Z","source":"web","type":"Android","url":"http://qlm.pw/2017/01/07/tinker%E6%8E%A5%E5%85%A5%E5%8F%8A%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90%EF%BC%88%E4%B8%80%EF%BC%89/","used":true,"who":"Linmin Qiu"},{"_id":"58732e0a421aa9316407fb8a","createdAt":"2017-01-09T14:30:34.824Z","desc":"两行代码搞定Android视图扩散切换效果~","images":["http://img.gank.io/082da85a-9c5a-4330-a6c9-8ab624792b9f"],"publishedAt":"2017-01-10T11:33:19.525Z","source":"web","type":"Android","url":"https://github.com/zhangke3016/ViewSpreadTranslationController","used":true,"who":"张珂"},{"_id":"58745452421aa9316407fb93","createdAt":"2017-01-10T11:26:10.880Z","desc":"支持计数效果的 FloatingActionButton","images":["http://img.gank.io/2047fbd1-57cc-4efe-be4e-a31487904825"],"publishedAt":"2017-01-10T11:33:19.525Z","source":"chrome","type":"Android","url":"https://github.com/andremion/CounterFab","used":true,"who":"代码家"}]
15 | */
16 |
17 | private boolean error;
18 | /**
19 | * _id : 5875e66c421aa9315ea79931
20 | * createdAt : 2017-01-11T16:01:48.998Z
21 | * desc : 在Chrome DevTools内查看Android设备上所有HTTP(S)流量
22 | * images : ["http://img.gank.io/b33cc839-18de-48e0-8644-089e6986609a","http://img.gank.io/a4ce3373-2f20-4fe5-bbcf-9f6dc3847591"]
23 | * publishedAt : 2017-01-12T11:30:59.369Z
24 | * source : web
25 | * type : Android
26 | * url : https://github.com/misakuo/Dream-Catcher
27 | * used : true
28 | * who : moxun
29 | */
30 |
31 | private List results;
32 |
33 | public boolean isError() {
34 | return error;
35 | }
36 |
37 | public void setError(boolean error) {
38 | this.error = error;
39 | }
40 |
41 | public List getResults() {
42 | return results;
43 | }
44 |
45 | public void setResults(List results) {
46 | this.results = results;
47 | }
48 |
49 | public static class ResultsBean {
50 | private String _id;
51 | private String createdAt;
52 | private String desc;
53 | private String publishedAt;
54 | private String source;
55 | private String type;
56 | private String url;
57 | private boolean used;
58 | private String who;
59 | private List images;
60 |
61 | public String get_id() {
62 | return _id;
63 | }
64 |
65 | public void set_id(String _id) {
66 | this._id = _id;
67 | }
68 |
69 | public String getCreatedAt() {
70 | return createdAt;
71 | }
72 |
73 | public void setCreatedAt(String createdAt) {
74 | this.createdAt = createdAt;
75 | }
76 |
77 | public String getDesc() {
78 | return desc;
79 | }
80 |
81 | public void setDesc(String desc) {
82 | this.desc = desc;
83 | }
84 |
85 | public String getPublishedAt() {
86 | return publishedAt;
87 | }
88 |
89 | public void setPublishedAt(String publishedAt) {
90 | this.publishedAt = publishedAt;
91 | }
92 |
93 | public String getSource() {
94 | return source;
95 | }
96 |
97 | public void setSource(String source) {
98 | this.source = source;
99 | }
100 |
101 | public String getType() {
102 | return type;
103 | }
104 |
105 | public void setType(String type) {
106 | this.type = type;
107 | }
108 |
109 | public String getUrl() {
110 | return url;
111 | }
112 |
113 | public void setUrl(String url) {
114 | this.url = url;
115 | }
116 |
117 | public boolean isUsed() {
118 | return used;
119 | }
120 |
121 | public void setUsed(boolean used) {
122 | this.used = used;
123 | }
124 |
125 | public String getWho() {
126 | return who;
127 | }
128 |
129 | public void setWho(String who) {
130 | this.who = who;
131 | }
132 |
133 | public List getImages() {
134 | return images;
135 | }
136 |
137 | public void setImages(List images) {
138 | this.images = images;
139 | }
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/app/src/main/java/xyz/ibat/sloth/domain/map/MeiziFragment.java:
--------------------------------------------------------------------------------
1 | package xyz.ibat.sloth.domain.map;
2 |
3 | import android.os.Bundle;
4 | import android.support.annotation.Nullable;
5 | import android.support.design.widget.FloatingActionButton;
6 | import android.support.v7.widget.RecyclerView;
7 | import android.support.v7.widget.StaggeredGridLayoutManager;
8 | import android.support.v7.widget.Toolbar;
9 | import android.view.LayoutInflater;
10 | import android.view.View;
11 | import android.view.ViewGroup;
12 |
13 | import butterknife.Bind;
14 | import butterknife.ButterKnife;
15 | import rx.Subscriber;
16 | import xyz.ibat.sloth.R;
17 | import xyz.ibat.sloth.base.BaseActivity;
18 | import xyz.ibat.sloth.base.BaseFragment;
19 | import xyz.ibat.sloth.domain.main.adapter.MeiziAdapter;
20 | import xyz.ibat.sloth.domain.main.model.DataModel;
21 | import xyz.ibat.sloth.network.RetrofitFactory;
22 | import xyz.ibat.sloth.utils.T;
23 |
24 | /**
25 | * Created by DongJr on 2016/4/15.
26 | */
27 | public class MeiziFragment extends BaseFragment {
28 |
29 | @Bind(R.id.main_toolbar)
30 | Toolbar mainToolbar;
31 | @Bind(R.id.recyclerView)
32 | RecyclerView recyclerView;
33 | @Bind(R.id.fab)
34 | FloatingActionButton fab;
35 |
36 | private MeiziAdapter mAdapter;
37 |
38 | @Override
39 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
40 | View view = inflater.inflate(R.layout.fragment_tab_map, container, false);
41 | ButterKnife.bind(this, view);
42 | return view;
43 | }
44 |
45 | @Override
46 | public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
47 | mainToolbar.setTitle("妹纸");
48 | ((BaseActivity) getActivity()).setSupportActionBar(mainToolbar);
49 |
50 | StaggeredGridLayoutManager sgm = new StaggeredGridLayoutManager
51 | (2, StaggeredGridLayoutManager.VERTICAL);
52 |
53 | recyclerView.setLayoutManager(sgm);
54 |
55 | requestData();
56 |
57 | fab.setOnClickListener(new View.OnClickListener() {
58 | @Override
59 | public void onClick(View v) {
60 | requestData();
61 | }
62 | });
63 |
64 | }
65 |
66 | private void requestData() {
67 | Subscriber subscriber = new Subscriber() {
68 | @Override
69 | public void onCompleted() {
70 |
71 | }
72 |
73 | @Override
74 | public void onError(Throwable e) {
75 | T.show(e.getMessage());
76 | }
77 |
78 | @Override
79 | public void onNext(DataModel dataModel) {
80 | if (mAdapter == null) {
81 | mAdapter = new MeiziAdapter(getContext(), dataModel);
82 | recyclerView.setAdapter(mAdapter);
83 | } else {
84 | mAdapter.setData(dataModel);
85 | }
86 | }
87 | };
88 |
89 | RetrofitFactory.getInstance().getRandomData(subscriber, "福利");
90 | }
91 |
92 |
93 | @Override
94 | public void onDestroyView() {
95 | super.onDestroyView();
96 | ButterKnife.unbind(this);
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/app/src/main/java/xyz/ibat/sloth/domain/mine/MineFragment.java:
--------------------------------------------------------------------------------
1 | package xyz.ibat.sloth.domain.mine;
2 |
3 | import android.os.Bundle;
4 | import android.support.annotation.Nullable;
5 | import android.support.design.widget.CollapsingToolbarLayout;
6 | import android.support.v7.widget.Toolbar;
7 | import android.text.Spannable;
8 | import android.text.SpannableStringBuilder;
9 | import android.text.method.LinkMovementMethod;
10 | import android.text.style.ClickableSpan;
11 | import android.text.style.URLSpan;
12 | import android.view.LayoutInflater;
13 | import android.view.View;
14 | import android.view.ViewGroup;
15 | import android.webkit.URLUtil;
16 | import android.widget.ImageView;
17 | import android.widget.TextView;
18 |
19 | import butterknife.Bind;
20 | import butterknife.ButterKnife;
21 | import xyz.ibat.sloth.R;
22 | import xyz.ibat.sloth.base.BaseActivity;
23 | import xyz.ibat.sloth.base.BaseFragment;
24 | import xyz.ibat.sloth.base.webview.WebActivity;
25 | import xyz.ibat.sloth.network.ImageLoader;
26 |
27 | /**
28 | * Created by DongJr on 2016/4/15.
29 | */
30 | public class MineFragment extends BaseFragment {
31 |
32 |
33 | @Bind(R.id.user_head)
34 | ImageView userHead;
35 | @Bind(R.id.toolbar)
36 | Toolbar toolbar;
37 | @Bind(R.id.collapsing_toolbar)
38 | CollapsingToolbarLayout collapsingToolbar;
39 | @Bind(R.id.tv_thanks)
40 | TextView tvThanks;
41 | @Bind(R.id.tv_blog)
42 | TextView tvBlog;
43 |
44 | @Override
45 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
46 | View view = inflater.inflate(R.layout.fragment_tab_mine, container, false);
47 | ButterKnife.bind(this, view);
48 | return view;
49 | }
50 |
51 | @Override
52 | public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
53 |
54 | collapsingToolbar.setTitle("小董同学");
55 | ((BaseActivity) getActivity()).setSupportActionBar(toolbar);
56 | ImageLoader.loadCircle(R.mipmap.icon_head, userHead);
57 |
58 |
59 |
60 | setTextLink();
61 | }
62 |
63 | private void setTextLink() {
64 | interceptLink(tvThanks);
65 | interceptLink(tvBlog);
66 | }
67 |
68 | private void interceptLink(TextView view) {
69 |
70 | view.setMovementMethod(LinkMovementMethod.getInstance());
71 |
72 | CharSequence text = view.getText();
73 |
74 | if (text instanceof Spannable) {
75 |
76 | Spannable spannable = (Spannable) text;
77 | URLSpan[] spans = spannable.getSpans(0, text.length(), URLSpan.class);
78 | if (spans.length == 0) {
79 | return;
80 | }
81 | SpannableStringBuilder ssb = new SpannableStringBuilder(text);
82 |
83 | for (URLSpan urlSpan : spans) {
84 | final String url = urlSpan.getURL();
85 | if (URLUtil.isNetworkUrl(url)) {
86 |
87 | ClickableSpan clickableSpan = new ClickableSpan() {
88 | @Override
89 | public void onClick(View widget) {
90 | WebActivity.startActivity(getActivity(), url);
91 | }
92 | };
93 | ssb.setSpan(clickableSpan, spannable.getSpanStart(urlSpan)
94 | , spannable.getSpanEnd(urlSpan), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
95 | }
96 | }
97 | view.setText(ssb);
98 | }
99 |
100 |
101 | }
102 |
103 |
104 | @Override
105 | public void onDestroyView() {
106 | super.onDestroyView();
107 | ButterKnife.unbind(this);
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/app/src/main/java/xyz/ibat/sloth/network/ImageLoader.java:
--------------------------------------------------------------------------------
1 | package xyz.ibat.sloth.network;
2 |
3 | import android.graphics.Bitmap;
4 | import android.widget.ImageView;
5 |
6 | import com.squareup.picasso.Picasso;
7 |
8 | import java.io.File;
9 |
10 | import xyz.ibat.sloth.SlothApplication;
11 | import xyz.ibat.sloth.view.picasso.CircleTransform;
12 |
13 | /**
14 | * Created by jerry on 2017/1/14.
15 | */
16 |
17 | public class ImageLoader {
18 |
19 |
20 | private ImageLoader() {
21 |
22 | }
23 |
24 | /**
25 | * ALPHA_8:每个像素占用1byte内存
26 | * ARGB_4444:每个像素占用2byte内存
27 | * ARGB_8888:每个像素占用4byte内存
28 | * RGB_565:每个像素占用2byte内存
29 | */
30 | public static void load(String url, ImageView view) {
31 | Picasso.with(SlothApplication.getContext())
32 | .load(url)
33 | .config(Bitmap.Config.RGB_565)
34 | .into(view);
35 | }
36 |
37 | public static void load(int drawableRes, ImageView view) {
38 | Picasso.with(SlothApplication.getContext())
39 | .load(drawableRes)
40 | .config(Bitmap.Config.RGB_565)
41 | .into(view);
42 | }
43 |
44 | public static void load(File file, ImageView view) {
45 | Picasso.with(SlothApplication.getContext())
46 | .load(file)
47 | .config(Bitmap.Config.RGB_565)
48 | .into(view);
49 | }
50 |
51 | public static void loadCircle(String url, ImageView view) {
52 | Picasso.with(SlothApplication.getContext())
53 | .load(url)
54 | .transform(new CircleTransform(SlothApplication.getContext()))
55 | .config(Bitmap.Config.RGB_565)
56 | .into(view);
57 | }
58 |
59 | public static void loadCircle(int drawableRes, ImageView view) {
60 | Picasso.with(SlothApplication.getContext())
61 | .load(drawableRes)
62 | .transform(new CircleTransform(SlothApplication.getContext()))
63 | .config(Bitmap.Config.RGB_565)
64 | .into(view);
65 | }
66 |
67 |
68 | }
69 |
70 |
--------------------------------------------------------------------------------
/app/src/main/java/xyz/ibat/sloth/network/RetrofitFactory.java:
--------------------------------------------------------------------------------
1 | package xyz.ibat.sloth.network;
2 |
3 | import retrofit2.Retrofit;
4 | import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
5 | import retrofit2.converter.gson.GsonConverterFactory;
6 | import rx.Subscriber;
7 | import rx.android.schedulers.AndroidSchedulers;
8 | import rx.schedulers.Schedulers;
9 | import xyz.ibat.sloth.domain.main.model.DataModel;
10 | import xyz.ibat.sloth.network.api.ApiService;
11 |
12 | /**
13 | * Created by DongJr on 2017/1/13.
14 | */
15 |
16 | public class RetrofitFactory {
17 |
18 | private static final String BASE_URL = "http://gank.io/api/";
19 |
20 | private Retrofit retrofit;
21 |
22 | private ApiService apiService;
23 |
24 | private RetrofitFactory() {
25 |
26 | retrofit = new Retrofit.Builder()
27 | .baseUrl(BASE_URL)
28 | .addConverterFactory(GsonConverterFactory.create())
29 | .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
30 | .build();
31 |
32 | apiService = retrofit.create(ApiService.class);
33 | }
34 |
35 | private static class SingletonHolder {
36 | private static final RetrofitFactory INSTANCE = new RetrofitFactory();
37 | }
38 |
39 | public static RetrofitFactory getInstance() {
40 | return SingletonHolder.INSTANCE;
41 | }
42 |
43 | public void getAndroidData(Subscriber subscriber, String type, int pageIndex) {
44 |
45 | apiService.getAndroidData(type, pageIndex)
46 | .subscribeOn(Schedulers.io())
47 | .observeOn(AndroidSchedulers.mainThread())
48 | .subscribe(subscriber);
49 |
50 | }
51 |
52 | public void getRandomData(Subscriber subscriber,String type){
53 |
54 | apiService.getRandomData(type)
55 | .subscribeOn(Schedulers.io())
56 | .observeOn(AndroidSchedulers.mainThread())
57 | .subscribe(subscriber);
58 |
59 | }
60 |
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/app/src/main/java/xyz/ibat/sloth/network/api/ApiService.java:
--------------------------------------------------------------------------------
1 | package xyz.ibat.sloth.network.api;
2 |
3 | import retrofit2.http.GET;
4 | import retrofit2.http.Path;
5 | import rx.Observable;
6 | import xyz.ibat.sloth.domain.main.model.DataModel;
7 |
8 | /**
9 | * Created by DongJr on 2017/1/13.
10 | */
11 |
12 | public interface ApiService {
13 |
14 | @GET("data/{type}/10/{page}")
15 | Observable getAndroidData(@Path("type") String type, @Path("page") int page);
16 |
17 | @GET("random/data/{type}/20")
18 | Observable getRandomData(@Path("type") String type);
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/app/src/main/java/xyz/ibat/sloth/utils/DensityUtil.java:
--------------------------------------------------------------------------------
1 | package xyz.ibat.sloth.utils;
2 |
3 | import android.content.res.Resources;
4 |
5 | /**
6 | * Created by jerry on 2017/1/14.
7 | */
8 |
9 | public class DensityUtil {
10 |
11 | private DensityUtil() {
12 | /** cannot be instantiated **/
13 | throw new UnsupportedOperationException("cannot be instantiated");
14 | }
15 |
16 | /**
17 | * dp转px
18 | */
19 | public static int dp2px(float dpVal) {
20 | final float scale = Resources.getSystem().getDisplayMetrics().density;
21 | return (int) (dpVal * scale + 0.5f);
22 | }
23 |
24 | /**
25 | * sp转px
26 | */
27 | public static int sp2px(float spVal) {
28 | final float fontScale = Resources.getSystem().getDisplayMetrics().scaledDensity;
29 | return (int) (spVal * fontScale + 0.5f);
30 | }
31 |
32 | /**
33 | * px转dp
34 | */
35 | public static float px2dp(float pxVal) {
36 | final float scale = Resources.getSystem().getDisplayMetrics().density;
37 | return (pxVal / scale);
38 | }
39 |
40 | /**
41 | * px转sp
42 | */
43 | public static float px2sp(float pxVal) {
44 | return (pxVal / Resources.getSystem().getDisplayMetrics().scaledDensity);
45 | }
46 |
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/app/src/main/java/xyz/ibat/sloth/utils/SlothUtil.java:
--------------------------------------------------------------------------------
1 | package xyz.ibat.sloth.utils;
2 |
3 | import android.widget.Toast;
4 |
5 | import xyz.ibat.sloth.SlothApplication;
6 |
7 | /**
8 | * Created by DongJr on 2016/4/1.
9 | */
10 | public class SlothUtil {
11 |
12 | public static void showToast(String msg) {
13 | Toast.makeText(SlothApplication.getContext(), msg, Toast.LENGTH_SHORT).show();
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/main/java/xyz/ibat/sloth/utils/T.java:
--------------------------------------------------------------------------------
1 | package xyz.ibat.sloth.utils;
2 |
3 | import android.widget.Toast;
4 |
5 | import xyz.ibat.sloth.SlothApplication;
6 |
7 | /**
8 | * Created by DongJr on 2017/1/13.
9 | */
10 |
11 | public class T {
12 |
13 | private static Toast toast;
14 |
15 | private T() {
16 |
17 | }
18 |
19 | public static void show(int msg) {
20 | if (toast == null) {
21 | toast = Toast.makeText(SlothApplication.getContext(), msg, Toast.LENGTH_SHORT);
22 | } else {
23 | toast.setText(msg);
24 | }
25 | toast.show();
26 | }
27 |
28 | public static void show(String msg) {
29 | if (toast == null) {
30 | toast = Toast.makeText(SlothApplication.getContext(), msg, Toast.LENGTH_SHORT);
31 | } else {
32 | toast.setText(msg);
33 | }
34 | toast.show();
35 | }
36 |
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/app/src/main/java/xyz/ibat/sloth/view/AppBarStateChangeListener.java:
--------------------------------------------------------------------------------
1 | package xyz.ibat.sloth.view;
2 |
3 | import android.support.design.widget.AppBarLayout;
4 | import android.util.Log;
5 |
6 | /**
7 | * Created by DongJr on 2017/1/5.
8 | */
9 |
10 | public abstract class AppBarStateChangeListener implements AppBarLayout.OnOffsetChangedListener {
11 |
12 | public enum State {
13 | EXPANDED,
14 | COLLAPSED,
15 | IDLE
16 | }
17 |
18 | private State mCurrentState = State.IDLE;
19 |
20 | @Override
21 | public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
22 |
23 |
24 | float percent = (float) Math.abs(verticalOffset) / (float) appBarLayout.getTotalScrollRange();
25 | Log.e("dong", percent + "================" + verticalOffset + "=======" + appBarLayout.getTotalScrollRange());
26 |
27 | if (verticalOffset == 0) {
28 | onStateChanged(appBarLayout, State.EXPANDED, percent);
29 | mCurrentState = State.EXPANDED;
30 | } else if (Math.abs(verticalOffset) >= appBarLayout.getTotalScrollRange()) {
31 | onStateChanged(appBarLayout, State.COLLAPSED, percent);
32 | mCurrentState = State.COLLAPSED;
33 | } else {
34 | onStateChanged(appBarLayout, State.IDLE, percent);
35 | mCurrentState = State.IDLE;
36 | }
37 |
38 | }
39 |
40 | public abstract void onStateChanged(AppBarLayout appBarLayout, State state, float percent);
41 | }
42 |
--------------------------------------------------------------------------------
/app/src/main/java/xyz/ibat/sloth/view/RefreshLayout.java:
--------------------------------------------------------------------------------
1 | package xyz.ibat.sloth.view;
2 |
3 | import android.content.Context;
4 | import android.support.v4.widget.SwipeRefreshLayout;
5 | import android.util.AttributeSet;
6 | import android.view.View;
7 | import android.widget.AbsListView;
8 | import android.widget.ListView;
9 | import android.widget.ProgressBar;
10 | import android.widget.TextView;
11 |
12 | import xyz.ibat.sloth.R;
13 |
14 | /**
15 | * Created by DongJr on 2016/4/5.
16 | */
17 | public class RefreshLayout extends SwipeRefreshLayout implements AbsListView.OnScrollListener {
18 |
19 | private OnLoadListener mOnloadListener;
20 |
21 | private ListView mListView;
22 |
23 | private int mLastVisiblePosition;
24 |
25 | //是否正在加载
26 | private boolean isLoading = false;
27 |
28 | private View mFootView;
29 |
30 | private ProgressBar mProgress;
31 | private TextView mTextView;
32 |
33 | public RefreshLayout(Context context) {
34 | super(context);
35 | init(context);
36 | }
37 |
38 | public RefreshLayout(Context context, AttributeSet attrs) {
39 | super(context, attrs);
40 | init(context);
41 | }
42 |
43 | public enum LoadState {
44 | ONLOADING,
45 | NOMORE
46 | }
47 |
48 | public void setLoadState(LoadState loadState) {
49 | switch (loadState) {
50 | case ONLOADING:
51 | mTextView.setText("正在刷新");
52 | mProgress.setVisibility(VISIBLE);
53 | break;
54 | case NOMORE:
55 | mTextView.setText("没有更多了");
56 | mProgress.setVisibility(GONE);
57 | break;
58 |
59 | }
60 | }
61 |
62 | private void init(Context context) {
63 | mFootView = View.inflate(context, R.layout.item_refresh_foot, null);
64 | mProgress = (ProgressBar) mFootView.findViewById(R.id.load_progress);
65 | mTextView = (TextView) mFootView.findViewById(R.id.loadmore_text);
66 | }
67 |
68 | @Override
69 | protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
70 | super.onLayout(changed, left, top, right, bottom);
71 | if (mListView == null) {
72 | getView();
73 | }
74 | }
75 |
76 | //绑定当前listView
77 | private void getView() {
78 | int childCount = getChildCount();
79 | if (childCount > 0) {
80 | for (int i = 0; i < childCount; i++) {
81 | View childView = getChildAt(i);
82 | if (childView instanceof ListView) {
83 | mListView = (ListView) childView;
84 | setScrollListener();
85 | }
86 | }
87 | }
88 | }
89 |
90 | private void setScrollListener() {
91 | if (mListView != null) {
92 | mListView.setOnScrollListener(this);
93 | }
94 | }
95 |
96 | private void loadData() {
97 | if (mOnloadListener != null) {
98 | setLoading(true);
99 | mOnloadListener.onLoad();
100 | }
101 | }
102 |
103 | public void setLoading(boolean loading) {
104 | isLoading = loading;
105 | if (isLoading) {
106 | //防止重绘
107 | if (mListView.getFooterViewsCount() == 0) {
108 | mListView.addFooterView(mFootView);
109 | }
110 | } else {
111 | mListView.removeFooterView(mFootView);
112 | }
113 | }
114 |
115 | public void setOnLoadListener(OnLoadListener onLoadListener) {
116 | mOnloadListener = onLoadListener;
117 | }
118 |
119 | public void setListener(OnRefreshListener onRefreshListener,OnLoadListener onLoadListener){
120 | setOnRefreshListener(onRefreshListener);
121 | mOnloadListener = onLoadListener;
122 | }
123 |
124 | @Override
125 | public void onScrollStateChanged(AbsListView view, int scrollState) {
126 |
127 | int visibleItemCount = view.getChildCount();
128 | int totalItemCount = mListView.getAdapter().getCount();
129 | mLastVisiblePosition = mListView.getLastVisiblePosition();
130 |
131 | if ((visibleItemCount > 0 && scrollState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE &&
132 | (mLastVisiblePosition) == totalItemCount - 1)) {
133 | if (!isLoading) {
134 | loadData();
135 | isLoading = false;
136 | }
137 | }
138 | }
139 |
140 | @Override
141 | public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
142 |
143 | }
144 |
145 |
146 | public interface OnLoadListener {
147 | void onLoad();
148 | }
149 | }
150 |
--------------------------------------------------------------------------------
/app/src/main/java/xyz/ibat/sloth/view/SlothRecycler.java:
--------------------------------------------------------------------------------
1 | package xyz.ibat.sloth.view;
2 |
3 | import android.content.Context;
4 | import android.support.v7.widget.GridLayoutManager;
5 | import android.support.v7.widget.LinearLayoutManager;
6 | import android.support.v7.widget.RecyclerView;
7 | import android.util.AttributeSet;
8 | import android.view.LayoutInflater;
9 | import android.view.View;
10 | import android.view.ViewGroup;
11 | import android.widget.ProgressBar;
12 | import android.widget.TextView;
13 |
14 | import java.util.List;
15 |
16 | import xyz.ibat.sloth.R;
17 |
18 | /**
19 | * Created by DongJr on 2016/4/6.
20 | */
21 | public class SlothRecycler extends RecyclerView {
22 |
23 | private boolean mIsLoading = false;
24 | private OnLoadListener mOnLoadListener;
25 | private int mLastVisiblePosition;
26 |
27 | private View mFootView;
28 | private ProgressBar mProgress;
29 | private TextView mTextView;
30 |
31 | public SlothRecycler(Context context) {
32 | super(context);
33 | init(context);
34 | }
35 |
36 | public SlothRecycler(Context context, AttributeSet attrs) {
37 | super(context, attrs);
38 | init(context);
39 | }
40 |
41 | public SlothRecycler(Context context, AttributeSet attrs, int defStyle) {
42 | super(context, attrs, defStyle);
43 | init(context);
44 | }
45 |
46 | public enum LoadState {
47 | ONLOADING,
48 | NOMORE
49 | }
50 |
51 | public void setLoadState(LoadState loadState) {
52 | switch (loadState) {
53 | case ONLOADING:
54 | mTextView.setText("正在刷新");
55 | mProgress.setVisibility(VISIBLE);
56 | break;
57 | case NOMORE:
58 | mTextView.setText("没有更多了");
59 | mProgress.setVisibility(GONE);
60 | break;
61 |
62 | }
63 | }
64 |
65 |
66 | private void init(Context context) {
67 | mFootView = View.inflate(context, R.layout.item_refresh_foot, null);
68 | mProgress = (ProgressBar) mFootView.findViewById(R.id.load_progress);
69 | mTextView = (TextView) mFootView.findViewById(R.id.loadmore_text);
70 | addOnScrollListener(new OnScrollListener() {
71 | @Override
72 | public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
73 | super.onScrolled(recyclerView, dx, dy);
74 | }
75 |
76 | @Override
77 | public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
78 | super.onScrollStateChanged(recyclerView, newState);
79 | LayoutManager layoutManager = recyclerView.getLayoutManager();
80 | if (!mIsLoading && getLastVisiblePosition() == layoutManager.getItemCount() - 1
81 | && newState == RecyclerView.SCROLL_STATE_IDLE) {
82 | loadData();
83 | mIsLoading = false;
84 | }
85 |
86 | }
87 | });
88 | }
89 |
90 | public int getLastVisiblePosition() {
91 | int totalItemCount = getLayoutManager().getItemCount();
92 | if (getLayoutManager() instanceof LinearLayoutManager) {
93 | mLastVisiblePosition = ((LinearLayoutManager) getLayoutManager()).findLastVisibleItemPosition();
94 | } else if (getLayoutManager() instanceof GridLayoutManager) {
95 | mLastVisiblePosition = ((GridLayoutManager) getLayoutManager()).findLastVisibleItemPosition();
96 | } else {
97 | mLastVisiblePosition = totalItemCount - 1;
98 | }
99 | return mLastVisiblePosition;
100 | }
101 |
102 | private void loadData() {
103 | if (mOnLoadListener != null) {
104 | setOnLoading(true);
105 | mOnLoadListener.onLoad();
106 | }
107 | }
108 |
109 | public void setOnLoading(boolean isLoading) {
110 | mIsLoading = isLoading;
111 |
112 | }
113 |
114 | public void setOnLoadListener(OnLoadListener onLoadListener) {
115 | mOnLoadListener = onLoadListener;
116 | }
117 |
118 | public interface OnLoadListener {
119 | void onLoad();
120 | }
121 |
122 |
123 | public static abstract class LoadMoreAdaper extends RecyclerView.Adapter {
124 | private Context context;
125 | private List list;
126 |
127 | public LoadMoreAdaper(Context context, List list) {
128 | this.context = context;
129 | this.list = list;
130 | }
131 |
132 | @Override
133 | public int getItemViewType(int position) {
134 | if (position == list.size()) {
135 | return 0;
136 | } else {
137 | return getItemType();
138 | }
139 | }
140 |
141 | public int getItemType() {
142 | return 1;
143 | }
144 |
145 | @Override
146 | public int getItemCount() {
147 | return list.size() + 1;
148 | }
149 |
150 | @Override
151 | public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
152 | if (viewType == 0) {
153 | View footView = LayoutInflater.from(context).inflate(R.layout.item_refresh_foot, parent, false);
154 | return new FootHolder(footView);
155 | } else {
156 | return onCreateHolder(parent, viewType);
157 | }
158 | }
159 |
160 | public abstract RecyclerView.ViewHolder onCreateHolder(ViewGroup parent, int viewType);
161 |
162 | @Override
163 | public abstract void onBindViewHolder(RecyclerView.ViewHolder holder, int position);
164 |
165 |
166 | }
167 |
168 | static class FootHolder extends RecyclerView.ViewHolder {
169 |
170 | public FootHolder(View itemView) {
171 | super(itemView);
172 | }
173 |
174 | }
175 | }
--------------------------------------------------------------------------------
/app/src/main/java/xyz/ibat/sloth/view/behavior/BottomScrollBehavior.java:
--------------------------------------------------------------------------------
1 | package xyz.ibat.sloth.view.behavior;
2 |
3 | import android.animation.Animator;
4 | import android.content.Context;
5 | import android.support.design.widget.CoordinatorLayout;
6 | import android.support.v4.view.ViewCompat;
7 | import android.util.AttributeSet;
8 | import android.util.Log;
9 | import android.view.View;
10 | import android.view.ViewPropertyAnimator;
11 | import android.view.animation.AccelerateDecelerateInterpolator;
12 | import android.view.animation.Interpolator;
13 |
14 | /**
15 | * Created by DongJr on 2016/5/4.
16 | */
17 | public class BottomScrollBehavior extends CoordinatorLayout.Behavior {
18 |
19 | int offsetTotal = 0;
20 |
21 | private static final Interpolator INTERPOLATOR = new AccelerateDecelerateInterpolator();
22 |
23 |
24 | private int sinceDirectionChange;
25 | private int hideHeight = 0;
26 |
27 | public BottomScrollBehavior(Context context, AttributeSet attrs){
28 | super(context,attrs);
29 | }
30 |
31 | @Override
32 | public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes) {
33 | return (nestedScrollAxes & ViewCompat.SCROLL_AXIS_VERTICAL) != 0;
34 | }
35 |
36 | @Override
37 | public void onNestedScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
38 | Log.e("behavior",dyConsumed+"===========dyConsumed===============");
39 | //dy>0 向上滑 else 向下滑
40 | if (dyConsumed > 0 && sinceDirectionChange < 0 || dyConsumed < 0 && sinceDirectionChange > 0) {
41 | child.animate().cancel();
42 | sinceDirectionChange = 0;
43 | }
44 | sinceDirectionChange += dyConsumed;
45 | if (sinceDirectionChange > child.getHeight()) {
46 | hide(child);
47 | } else if (sinceDirectionChange < 0 ) {
48 | show(child);
49 | }
50 | }
51 |
52 | @Override
53 | public boolean onNestedFling(CoordinatorLayout coordinatorLayout, View child, View target, float velocityX, float velocityY, boolean consumed) {
54 | //当快速滑动
55 | return super.onNestedFling(coordinatorLayout, child, target, velocityX, velocityY, consumed);
56 | }
57 |
58 | private void hide(final View view) {
59 | hideHeight = view.getHeight();
60 | ViewPropertyAnimator animator = view.animate().translationY(hideHeight)
61 | .setInterpolator(INTERPOLATOR).setDuration(400);
62 | animator.setListener(new Animator.AnimatorListener() {
63 | @Override
64 | public void onAnimationStart(Animator animator) {
65 |
66 | }
67 |
68 | @Override
69 | public void onAnimationEnd(Animator animator) {
70 | // view.setVisibility(View.INVISIBLE);
71 | }
72 |
73 | @Override
74 | public void onAnimationCancel(Animator animator) {
75 | show(view);
76 | }
77 |
78 | @Override
79 | public void onAnimationRepeat(Animator animator) {
80 |
81 | }
82 | });
83 | animator.start();
84 | }
85 |
86 |
87 | private void show(final View view) {
88 | ViewPropertyAnimator animator = view.animate().translationY(0)
89 | .setInterpolator(INTERPOLATOR).setDuration(400);
90 | animator.setListener(new Animator.AnimatorListener() {
91 | @Override
92 | public void onAnimationStart(Animator animator) {
93 |
94 | }
95 |
96 | @Override
97 | public void onAnimationEnd(Animator animator) {
98 | // view.setVisibility(View.VISIBLE);
99 | }
100 |
101 | @Override
102 | public void onAnimationCancel(Animator animator) {
103 | hide(view);
104 | }
105 |
106 | @Override
107 | public void onAnimationRepeat(Animator animator) {
108 |
109 | }
110 | });
111 | animator.start();
112 |
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/app/src/main/java/xyz/ibat/sloth/view/behavior/FABScrollBehavior.java:
--------------------------------------------------------------------------------
1 | package xyz.ibat.sloth.view.behavior;
2 |
3 | import android.animation.Animator;
4 | import android.support.v7.widget.RecyclerView;
5 | import android.util.Log;
6 | import android.view.View;
7 | import android.view.ViewPropertyAnimator;
8 | import android.view.animation.AccelerateDecelerateInterpolator;
9 | import android.view.animation.Interpolator;
10 |
11 | import xyz.ibat.sloth.utils.DensityUtil;
12 |
13 | /**
14 | * Created by DongJr on 2016/5/4.
15 | */
16 | public class FABScrollBehavior extends RecyclerView.OnScrollListener {
17 |
18 | int offsetTotal = 0;
19 |
20 | private static final Interpolator INTERPOLATOR = new AccelerateDecelerateInterpolator();
21 |
22 | private int mState;
23 | private int sinceDirectionChange;
24 | private int hideHeight = 0;
25 |
26 | private View innerView;
27 |
28 | public FABScrollBehavior(View innerView){
29 | this.innerView = innerView;
30 | }
31 |
32 |
33 | @Override
34 | public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
35 | if (mState != RecyclerView.SCROLL_STATE_DRAGGING){
36 | return;
37 | }
38 | Log.e("behavior",dy+"===========dy===============");
39 |
40 | //dy>0 向上滑 else 向下滑
41 | if (dy > 0 && sinceDirectionChange < 0 || dy < 0 && sinceDirectionChange > 0) {
42 | innerView.animate().cancel();
43 | sinceDirectionChange = 0;
44 | }
45 | sinceDirectionChange += dy;
46 | if (sinceDirectionChange > DensityUtil.dp2px(46)) {
47 | hide(innerView);
48 | } else if (sinceDirectionChange < 0 ) {
49 | show(innerView);
50 | }
51 | }
52 |
53 | @Override
54 | public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
55 | mState = newState;
56 | }
57 |
58 | private void hide(final View view) {
59 | hideHeight = view.getBottom();
60 | ViewPropertyAnimator animator = view.animate().translationY(hideHeight)
61 | .setInterpolator(INTERPOLATOR).setDuration(400);
62 | animator.setListener(new Animator.AnimatorListener() {
63 | @Override
64 | public void onAnimationStart(Animator animator) {
65 |
66 | }
67 |
68 | @Override
69 | public void onAnimationEnd(Animator animator) {
70 | // view.setVisibility(View.INVISIBLE);
71 | }
72 |
73 | @Override
74 | public void onAnimationCancel(Animator animator) {
75 | show(view);
76 | }
77 |
78 | @Override
79 | public void onAnimationRepeat(Animator animator) {
80 |
81 | }
82 | });
83 | animator.start();
84 | }
85 |
86 |
87 | private void show(final View view) {
88 | ViewPropertyAnimator animator = view.animate().translationY(0)
89 | .setInterpolator(INTERPOLATOR).setDuration(400);
90 | animator.setListener(new Animator.AnimatorListener() {
91 | @Override
92 | public void onAnimationStart(Animator animator) {
93 |
94 | }
95 |
96 | @Override
97 | public void onAnimationEnd(Animator animator) {
98 | // view.setVisibility(View.VISIBLE);
99 | }
100 |
101 | @Override
102 | public void onAnimationCancel(Animator animator) {
103 | hide(view);
104 | }
105 |
106 | @Override
107 | public void onAnimationRepeat(Animator animator) {
108 |
109 | }
110 | });
111 | animator.start();
112 |
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/app/src/main/java/xyz/ibat/sloth/view/behavior/FollowBehavior.java:
--------------------------------------------------------------------------------
1 | package xyz.ibat.sloth.view.behavior;
2 |
3 | import android.content.Context;
4 | import android.content.res.TypedArray;
5 | import android.support.design.widget.CoordinatorLayout;
6 | import android.util.AttributeSet;
7 | import android.view.View;
8 |
9 | import xyz.ibat.sloth.R;
10 |
11 | /**
12 | * Created by DongJr on 2016/5/4.
13 | */
14 | public class FollowBehavior extends CoordinatorLayout.Behavior {
15 |
16 | private int targetId;
17 |
18 | public FollowBehavior(Context context, AttributeSet attrs){
19 | super(context,attrs);
20 | //AttributeSet和TypedArray区别。都可以获取属性值,但TypedArray更方便些,如果属性引用了
21 | //values文件下的值,用AttributeSet拿到的是属性id,但TypedArray可以获得具体的值
22 | TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.FollowBehavior);
23 | for (int i = 0; i < a.getIndexCount(); i++) {
24 | int attr = a.getIndex(i);
25 | if(a.getIndex(i) == R.styleable.FollowBehavior_target){
26 | targetId = a.getResourceId(attr, -1);
27 | }
28 | }
29 | a.recycle();
30 | }
31 |
32 | //确定依赖哪个view
33 | @Override
34 | public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
35 | return dependency.getId() == targetId;
36 | }
37 |
38 | //child 是指应用behavior的View ,dependency 担任触发behavior的角色,其实就是上面依赖的view,并与child进行互动。
39 | //确定你是否依赖于这个View。CoordinatorLayout会将自己所有View遍历判断。
40 | //如果确定依赖。这个方法很重要。当所依赖的View变动时会回调这个方法。
41 | @Override
42 | public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {
43 | child.setY(dependency.getY()+dependency.getHeight());
44 | return true;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/app/src/main/java/xyz/ibat/sloth/view/behavior/ScrollBehavior.java:
--------------------------------------------------------------------------------
1 | package xyz.ibat.sloth.view.behavior;
2 |
3 | import android.content.Context;
4 | import android.support.design.widget.CoordinatorLayout;
5 | import android.util.AttributeSet;
6 | import android.util.Log;
7 | import android.view.View;
8 |
9 | /**
10 | * Created by DongJr on 2016/5/4.
11 | */
12 | public class ScrollBehavior extends CoordinatorLayout.Behavior {
13 |
14 | int offsetTotal = 0;
15 |
16 | public ScrollBehavior(Context context, AttributeSet attrs){
17 | super(context,attrs);
18 | }
19 |
20 | @Override
21 | public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes) {
22 | //nestedScrollAxes滑动方向
23 | return true;
24 | }
25 |
26 | @Override
27 | public void onNestedScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
28 | //滑动事件处理
29 | onScroll(child,dyConsumed);
30 | Log.e("behavior","=============dtConsumed======="+dyConsumed);
31 | Log.e("behavior","=============dtUnConsumed======="+dyUnconsumed);
32 | }
33 |
34 | private void onScroll(View child, int dyConsumed) {
35 | int old = offsetTotal;
36 | int top = offsetTotal - dyConsumed;
37 | top = Math.max(top, -child.getHeight());
38 | top = Math.min(top, 0);
39 | offsetTotal = top;
40 | if (old == offsetTotal){
41 | return;
42 | }
43 | int delta = offsetTotal-old;
44 | child.offsetTopAndBottom(delta);
45 | // int top = -dyConsumed;
46 | // top = Math.min(top,child.getHeight());
47 | // child.offsetTopAndBottom(top);
48 | }
49 |
50 |
51 | @Override
52 | public boolean onNestedFling(CoordinatorLayout coordinatorLayout, View child, View target, float velocityX, float velocityY, boolean consumed) {
53 | //当快速滑动
54 | return super.onNestedFling(coordinatorLayout, child, target, velocityX, velocityY, consumed);
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/app/src/main/java/xyz/ibat/sloth/view/picasso/CircleTransform.java:
--------------------------------------------------------------------------------
1 | package xyz.ibat.sloth.view.picasso;
2 |
3 | import android.content.Context;
4 | import android.graphics.Bitmap;
5 | import android.graphics.BitmapShader;
6 | import android.graphics.Canvas;
7 | import android.graphics.Paint;
8 |
9 | import com.squareup.picasso.Transformation;
10 |
11 | /**
12 | * Created by DongJr on 2017/1/17.
13 | */
14 |
15 | public class CircleTransform implements Transformation {
16 |
17 | private Context context;
18 |
19 | public CircleTransform(Context context) {
20 | this.context = context;
21 | }
22 |
23 | @Override
24 | public Bitmap transform(Bitmap source) {
25 | int size = Math.min(source.getWidth(), source.getHeight());
26 | int x = (source.getWidth() - size) / 2;
27 | int y = (source.getHeight() - size) / 2;
28 | Bitmap squaredBitmap = Bitmap.createBitmap(source, x, y, size, size);
29 | if (squaredBitmap != source) {
30 | source.recycle();
31 | }
32 | Bitmap bitmap = Bitmap.createBitmap(size, size, source.getConfig());
33 | Canvas canvas = new Canvas(bitmap);
34 | Paint paint = new Paint();
35 | BitmapShader shader = new BitmapShader(squaredBitmap,
36 | BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP);
37 | paint.setShader(shader);
38 | paint.setAntiAlias(true);
39 | paint.setStyle(Paint.Style.FILL);
40 | float r = size / 2f;
41 | canvas.drawCircle(r, r, r, paint);
42 | squaredBitmap.recycle();
43 | return bitmap;
44 | }
45 |
46 | @Override
47 | public String key() {
48 | return "circle";
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/info_tab_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/loadfail_btn_bg_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | -
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/main_tab_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/map_tab_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/mine_tab_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/progress_animation.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/progressbar.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/tab_text_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/webview_progress_bar_states.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
7 |
8 |
13 |
14 |
15 | -
16 |
17 |
18 |
19 |
20 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_base.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_friend.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
16 |
17 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_image_preview.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_meizi.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
12 |
16 |
17 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_message.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
15 |
16 |
28 |
29 |
38 |
39 |
46 |
47 |
48 |
49 |
50 |
51 |
55 |
56 |
61 |
62 |
68 |
74 |
75 |
80 |
81 |
85 |
86 |
87 |
88 |
89 |
96 |
102 |
103 |
108 |
109 |
113 |
114 |
115 |
116 |
117 |
124 |
130 |
131 |
136 |
137 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
158 |
159 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_web.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
14 |
19 |
20 |
23 |
24 |
28 |
29 |
30 |
31 |
40 |
41 |
46 |
47 |
53 |
54 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/common_toolbar.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/default_loading.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
14 |
15 |
22 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_base.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_one.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
14 |
15 |
19 |
20 |
21 |
30 |
31 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_tab.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
13 |
14 |
15 |
16 |
23 |
24 |
28 |
29 |
35 |
36 |
46 |
47 |
57 |
58 |
68 |
69 |
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_tab_info.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
20 |
21 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_tab_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
12 |
16 |
17 |
18 |
23 |
24 |
31 |
32 |
37 |
38 |
39 |
40 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_tab_map.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
19 |
20 |
23 |
24 |
28 |
29 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_tab_mine.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
15 |
16 |
28 |
29 |
35 |
36 |
43 |
44 |
45 |
46 |
57 |
58 |
59 |
60 |
61 |
62 |
66 |
67 |
71 |
72 |
82 |
83 |
92 |
93 |
103 |
104 |
115 |
116 |
126 |
127 |
138 |
139 |
148 |
149 |
150 |
151 |
152 |
153 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_web.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
25 |
26 |
31 |
32 |
35 |
36 |
40 |
41 |
42 |
43 |
52 |
53 |
58 |
59 |
65 |
66 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_fragment_home.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
19 |
20 |
31 |
32 |
44 |
45 |
46 |
52 |
53 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_meizi.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
16 |
17 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_refresh_foot.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
16 |
17 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/navigationview_header.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
18 |
19 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_drawer.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_main.xml:
--------------------------------------------------------------------------------
1 |
5 |
9 |
13 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/banner2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JrDong/Android-Material-Sloth/7dcad2a8a34c72db955034a55a8186cefbbfa4b5/app/src/main/res/mipmap-hdpi/banner2.jpg
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_dashboard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JrDong/Android-Material-Sloth/7dcad2a8a34c72db955034a55a8186cefbbfa4b5/app/src/main/res/mipmap-hdpi/ic_dashboard.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_discuss.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JrDong/Android-Material-Sloth/7dcad2a8a34c72db955034a55a8186cefbbfa4b5/app/src/main/res/mipmap-hdpi/ic_discuss.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_done.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JrDong/Android-Material-Sloth/7dcad2a8a34c72db955034a55a8186cefbbfa4b5/app/src/main/res/mipmap-hdpi/ic_done.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_event.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JrDong/Android-Material-Sloth/7dcad2a8a34c72db955034a55a8186cefbbfa4b5/app/src/main/res/mipmap-hdpi/ic_event.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_forum.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JrDong/Android-Material-Sloth/7dcad2a8a34c72db955034a55a8186cefbbfa4b5/app/src/main/res/mipmap-hdpi/ic_forum.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_headset.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JrDong/Android-Material-Sloth/7dcad2a8a34c72db955034a55a8186cefbbfa4b5/app/src/main/res/mipmap-hdpi/ic_headset.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JrDong/Android-Material-Sloth/7dcad2a8a34c72db955034a55a8186cefbbfa4b5/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_menu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JrDong/Android-Material-Sloth/7dcad2a8a34c72db955034a55a8186cefbbfa4b5/app/src/main/res/mipmap-hdpi/ic_menu.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_toolbar_drawer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JrDong/Android-Material-Sloth/7dcad2a8a34c72db955034a55a8186cefbbfa4b5/app/src/main/res/mipmap-hdpi/ic_toolbar_drawer.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JrDong/Android-Material-Sloth/7dcad2a8a34c72db955034a55a8186cefbbfa4b5/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JrDong/Android-Material-Sloth/7dcad2a8a34c72db955034a55a8186cefbbfa4b5/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_toolbar_drawer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JrDong/Android-Material-Sloth/7dcad2a8a34c72db955034a55a8186cefbbfa4b5/app/src/main/res/mipmap-xhdpi/ic_toolbar_drawer.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/icon_arrow_back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JrDong/Android-Material-Sloth/7dcad2a8a34c72db955034a55a8186cefbbfa4b5/app/src/main/res/mipmap-xhdpi/icon_arrow_back.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/icon_head.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JrDong/Android-Material-Sloth/7dcad2a8a34c72db955034a55a8186cefbbfa4b5/app/src/main/res/mipmap-xhdpi/icon_head.jpg
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/icon_info_default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JrDong/Android-Material-Sloth/7dcad2a8a34c72db955034a55a8186cefbbfa4b5/app/src/main/res/mipmap-xhdpi/icon_info_default.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/icon_info_pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JrDong/Android-Material-Sloth/7dcad2a8a34c72db955034a55a8186cefbbfa4b5/app/src/main/res/mipmap-xhdpi/icon_info_pressed.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/icon_load_failed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JrDong/Android-Material-Sloth/7dcad2a8a34c72db955034a55a8186cefbbfa4b5/app/src/main/res/mipmap-xhdpi/icon_load_failed.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/icon_main_default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JrDong/Android-Material-Sloth/7dcad2a8a34c72db955034a55a8186cefbbfa4b5/app/src/main/res/mipmap-xhdpi/icon_main_default.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/icon_main_pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JrDong/Android-Material-Sloth/7dcad2a8a34c72db955034a55a8186cefbbfa4b5/app/src/main/res/mipmap-xhdpi/icon_main_pressed.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/icon_map_default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JrDong/Android-Material-Sloth/7dcad2a8a34c72db955034a55a8186cefbbfa4b5/app/src/main/res/mipmap-xhdpi/icon_map_default.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/icon_map_pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JrDong/Android-Material-Sloth/7dcad2a8a34c72db955034a55a8186cefbbfa4b5/app/src/main/res/mipmap-xhdpi/icon_map_pressed.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/icon_mine_default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JrDong/Android-Material-Sloth/7dcad2a8a34c72db955034a55a8186cefbbfa4b5/app/src/main/res/mipmap-xhdpi/icon_mine_default.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/icon_mine_pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JrDong/Android-Material-Sloth/7dcad2a8a34c72db955034a55a8186cefbbfa4b5/app/src/main/res/mipmap-xhdpi/icon_mine_pressed.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/icon_search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JrDong/Android-Material-Sloth/7dcad2a8a34c72db955034a55a8186cefbbfa4b5/app/src/main/res/mipmap-xhdpi/icon_search.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/icon_search_white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JrDong/Android-Material-Sloth/7dcad2a8a34c72db955034a55a8186cefbbfa4b5/app/src/main/res/mipmap-xhdpi/icon_search_white.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/icon_share.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JrDong/Android-Material-Sloth/7dcad2a8a34c72db955034a55a8186cefbbfa4b5/app/src/main/res/mipmap-xhdpi/icon_share.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JrDong/Android-Material-Sloth/7dcad2a8a34c72db955034a55a8186cefbbfa4b5/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_toolbar_drawer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JrDong/Android-Material-Sloth/7dcad2a8a34c72db955034a55a8186cefbbfa4b5/app/src/main/res/mipmap-xxhdpi/ic_toolbar_drawer.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JrDong/Android-Material-Sloth/7dcad2a8a34c72db955034a55a8186cefbbfa4b5/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/transition/explode.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/transition/fade.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/transition/slide.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #2196F3
4 | #1976D2
5 | #FF4081
6 | #ffffff
7 | #00000000
8 | #66ffffff
9 | #000000
10 | #66000000
11 | #f2f2f2
12 | #333333
13 |
14 |
15 | #999999
16 | #5EDDCA
17 | #eaeaea
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
7 | 14sp
8 | 24sp
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Sloth
3 | Settings
4 | About
5 | 搜索
6 | 分享
7 |
8 |
9 | Hello blank fragment
10 | 首页
11 | 地图
12 | 咨询
13 | 我的
14 |
15 | 松开刷新
16 | 刷新中...
17 | 上次更新时间:
18 | 查看更多
19 | 下拉刷新
20 | 加载中
21 |
22 | 网络不给力哦
23 |
24 | \t\t这是用于Android学习的一个项目,里面的内容包括
25 | ,RxJava,Retroft,,Picasso,WebView预览图片,图片预览放大、缩小、移动,Material Design控件使用,activity酷炫切换动画等
26 | .目前代码结构还不是很好,以后会慢慢重构.有新的技术也会不断往项目里面添加.希望能通过这个项目技术有一定得提升
27 |
28 | \t\t项目用到了代码家的 gank.io 的api接口,还有张鸿洋的baseadapter等,鸿洋的博客( zhanghongyang.com )是我在刚接触android的时候就
29 | 一直在看的 , 学到了很多东西 . 感谢一直在为开源做贡献的人们 .
30 |
31 | \t\t附上我的博客: ibat.xyz .里面内容很少,但希望能坚持写下去
32 | \t\t邮箱:idongjr@gmail.com
33 | Please do not see me off.The journey I am walking on alone is lonely and dangerous.
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
16 |
17 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/baseadapter-recyclerview/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/baseadapter-recyclerview/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | //apply plugin: 'com.novoda.bintray-release'
3 |
4 | android {
5 | compileSdkVersion 23
6 | buildToolsVersion "23.0.1"
7 |
8 | defaultConfig {
9 | minSdkVersion 10
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 | dependencies {
22 | compile fileTree(dir: 'libs', include: ['*.jar'])
23 | testCompile 'junit:junit:4.12'
24 | compile 'com.android.support:recyclerview-v7:23.4.0'
25 | }
26 |
27 | //publish {
28 | // userOrg = 'hongyangandroid'
29 | // groupId = 'com.zhy'
30 | // artifactId = 'base-rvadapter'
31 | // publishVersion = '3.0.3'
32 | // desc = 'a easy adapter for recyclerview'
33 | // website = 'https://github.com/hongyangAndroid/baseAdapter'
34 | // licences = ['Apache-2.0']
35 | //}
36 |
--------------------------------------------------------------------------------
/baseadapter-recyclerview/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/zhy/android/sdk/android-sdk-macosx/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 |
--------------------------------------------------------------------------------
/baseadapter-recyclerview/src/androidTest/java/com/zhy/baseadapter_recyclerview/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.zhy.baseadapter_recyclerview;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase
10 | {
11 | public ApplicationTest()
12 | {
13 | super(Application.class);
14 | }
15 | }
--------------------------------------------------------------------------------
/baseadapter-recyclerview/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/baseadapter-recyclerview/src/main/java/com/zhy/adapter/recyclerview/CommonAdapter.java:
--------------------------------------------------------------------------------
1 | package com.zhy.adapter.recyclerview;
2 |
3 | import android.content.Context;
4 | import android.view.LayoutInflater;
5 |
6 | import com.zhy.adapter.recyclerview.base.ItemViewDelegate;
7 | import com.zhy.adapter.recyclerview.base.ViewHolder;
8 |
9 | import java.util.List;
10 |
11 | /**
12 | * Created by zhy on 16/4/9.
13 | */
14 | public abstract class CommonAdapter extends MultiItemTypeAdapter
15 | {
16 | protected Context mContext;
17 | protected int mLayoutId;
18 | protected List mDatas;
19 | protected LayoutInflater mInflater;
20 |
21 | public CommonAdapter(final Context context, final int layoutId, List datas)
22 | {
23 | super(context, datas);
24 | mContext = context;
25 | mInflater = LayoutInflater.from(context);
26 | mLayoutId = layoutId;
27 | mDatas = datas;
28 |
29 | addItemViewDelegate(new ItemViewDelegate()
30 | {
31 | @Override
32 | public int getItemViewLayoutId()
33 | {
34 | return layoutId;
35 | }
36 |
37 | @Override
38 | public boolean isForViewType( T item, int position)
39 | {
40 | return true;
41 | }
42 |
43 | @Override
44 | public void convert(ViewHolder holder, T t, int position)
45 | {
46 | CommonAdapter.this.convert(holder, t, position);
47 | }
48 | });
49 | }
50 |
51 | protected abstract void convert(ViewHolder holder, T t, int position);
52 |
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/baseadapter-recyclerview/src/main/java/com/zhy/adapter/recyclerview/MultiItemTypeAdapter.java:
--------------------------------------------------------------------------------
1 | package com.zhy.adapter.recyclerview;
2 |
3 | import android.content.Context;
4 | import android.support.v7.widget.RecyclerView;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 |
8 | import com.zhy.adapter.recyclerview.base.ItemViewDelegate;
9 | import com.zhy.adapter.recyclerview.base.ItemViewDelegateManager;
10 | import com.zhy.adapter.recyclerview.base.ViewHolder;
11 |
12 | import java.util.List;
13 |
14 | /**
15 | * Created by zhy on 16/4/9.
16 | */
17 | public class MultiItemTypeAdapter extends RecyclerView.Adapter {
18 | protected Context mContext;
19 | protected List mDatas;
20 |
21 | protected ItemViewDelegateManager mItemViewDelegateManager;
22 | protected OnItemClickListener mOnItemClickListener;
23 |
24 |
25 | public MultiItemTypeAdapter(Context context, List datas) {
26 | mContext = context;
27 | mDatas = datas;
28 | mItemViewDelegateManager = new ItemViewDelegateManager();
29 | }
30 |
31 | @Override
32 | public int getItemViewType(int position) {
33 | if (!useItemViewDelegateManager()) return super.getItemViewType(position);
34 | return mItemViewDelegateManager.getItemViewType(mDatas.get(position), position);
35 | }
36 |
37 |
38 | @Override
39 | public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
40 | ItemViewDelegate itemViewDelegate = mItemViewDelegateManager.getItemViewDelegate(viewType);
41 | int layoutId = itemViewDelegate.getItemViewLayoutId();
42 | ViewHolder holder = ViewHolder.createViewHolder(mContext, parent, layoutId);
43 | onViewHolderCreated(holder,holder.getConvertView());
44 | setListener(parent, holder, viewType);
45 | return holder;
46 | }
47 |
48 | public void onViewHolderCreated(ViewHolder holder,View itemView){
49 |
50 | }
51 |
52 | public void convert(ViewHolder holder, T t) {
53 | mItemViewDelegateManager.convert(holder, t, holder.getAdapterPosition());
54 | }
55 |
56 | protected boolean isEnabled(int viewType) {
57 | return true;
58 | }
59 |
60 |
61 | protected void setListener(final ViewGroup parent, final ViewHolder viewHolder, int viewType) {
62 | if (!isEnabled(viewType)) return;
63 | viewHolder.getConvertView().setOnClickListener(new View.OnClickListener() {
64 | @Override
65 | public void onClick(View v) {
66 | if (mOnItemClickListener != null) {
67 | int position = viewHolder.getAdapterPosition();
68 | mOnItemClickListener.onItemClick(v, viewHolder , position);
69 | }
70 | }
71 | });
72 |
73 | viewHolder.getConvertView().setOnLongClickListener(new View.OnLongClickListener() {
74 | @Override
75 | public boolean onLongClick(View v) {
76 | if (mOnItemClickListener != null) {
77 | int position = viewHolder.getAdapterPosition();
78 | return mOnItemClickListener.onItemLongClick(v, viewHolder, position);
79 | }
80 | return false;
81 | }
82 | });
83 | }
84 |
85 | @Override
86 | public void onBindViewHolder(ViewHolder holder, int position) {
87 | convert(holder, mDatas.get(position));
88 | }
89 |
90 | @Override
91 | public int getItemCount() {
92 | int itemCount = mDatas.size();
93 | return itemCount;
94 | }
95 |
96 |
97 | public List getDatas() {
98 | return mDatas;
99 | }
100 |
101 | public MultiItemTypeAdapter addItemViewDelegate(ItemViewDelegate itemViewDelegate) {
102 | mItemViewDelegateManager.addDelegate(itemViewDelegate);
103 | return this;
104 | }
105 |
106 | public MultiItemTypeAdapter addItemViewDelegate(int viewType, ItemViewDelegate itemViewDelegate) {
107 | mItemViewDelegateManager.addDelegate(viewType, itemViewDelegate);
108 | return this;
109 | }
110 |
111 | protected boolean useItemViewDelegateManager() {
112 | return mItemViewDelegateManager.getItemViewDelegateCount() > 0;
113 | }
114 |
115 | public interface OnItemClickListener {
116 | void onItemClick(View view, RecyclerView.ViewHolder holder, int position);
117 |
118 | boolean onItemLongClick(View view, RecyclerView.ViewHolder holder, int position);
119 | }
120 |
121 | public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
122 | this.mOnItemClickListener = onItemClickListener;
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/baseadapter-recyclerview/src/main/java/com/zhy/adapter/recyclerview/base/ItemViewDelegate.java:
--------------------------------------------------------------------------------
1 | package com.zhy.adapter.recyclerview.base;
2 |
3 |
4 | import android.view.View;
5 |
6 | /**
7 | * Created by zhy on 16/6/22.
8 | */
9 | public interface ItemViewDelegate
10 | {
11 |
12 | int getItemViewLayoutId();
13 |
14 | boolean isForViewType(T item, int position);
15 |
16 | void convert(ViewHolder holder, T t, int position);
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/baseadapter-recyclerview/src/main/java/com/zhy/adapter/recyclerview/base/ItemViewDelegateManager.java:
--------------------------------------------------------------------------------
1 | package com.zhy.adapter.recyclerview.base;
2 |
3 | import android.support.v4.util.SparseArrayCompat;
4 |
5 |
6 | /**
7 | * Created by zhy on 16/6/22.
8 | */
9 | public class ItemViewDelegateManager
10 | {
11 | SparseArrayCompat> delegates = new SparseArrayCompat();
12 |
13 | public int getItemViewDelegateCount()
14 | {
15 | return delegates.size();
16 | }
17 |
18 | public ItemViewDelegateManager addDelegate(ItemViewDelegate delegate)
19 | {
20 | int viewType = delegates.size();
21 | if (delegate != null)
22 | {
23 | delegates.put(viewType, delegate);
24 | viewType++;
25 | }
26 | return this;
27 | }
28 |
29 | public ItemViewDelegateManager addDelegate(int viewType, ItemViewDelegate delegate)
30 | {
31 | if (delegates.get(viewType) != null)
32 | {
33 | throw new IllegalArgumentException(
34 | "An ItemViewDelegate is already registered for the viewType = "
35 | + viewType
36 | + ". Already registered ItemViewDelegate is "
37 | + delegates.get(viewType));
38 | }
39 | delegates.put(viewType, delegate);
40 | return this;
41 | }
42 |
43 | public ItemViewDelegateManager removeDelegate(ItemViewDelegate delegate)
44 | {
45 | if (delegate == null)
46 | {
47 | throw new NullPointerException("ItemViewDelegate is null");
48 | }
49 | int indexToRemove = delegates.indexOfValue(delegate);
50 |
51 | if (indexToRemove >= 0)
52 | {
53 | delegates.removeAt(indexToRemove);
54 | }
55 | return this;
56 | }
57 |
58 | public ItemViewDelegateManager removeDelegate(int itemType)
59 | {
60 | int indexToRemove = delegates.indexOfKey(itemType);
61 |
62 | if (indexToRemove >= 0)
63 | {
64 | delegates.removeAt(indexToRemove);
65 | }
66 | return this;
67 | }
68 |
69 | public int getItemViewType(T item, int position)
70 | {
71 | int delegatesCount = delegates.size();
72 | for (int i = delegatesCount - 1; i >= 0; i--)
73 | {
74 | ItemViewDelegate delegate = delegates.valueAt(i);
75 | if (delegate.isForViewType( item, position))
76 | {
77 | return delegates.keyAt(i);
78 | }
79 | }
80 | throw new IllegalArgumentException(
81 | "No ItemViewDelegate added that matches position=" + position + " in data source");
82 | }
83 |
84 | public void convert(ViewHolder holder, T item, int position)
85 | {
86 | int delegatesCount = delegates.size();
87 | for (int i = 0; i < delegatesCount; i++)
88 | {
89 | ItemViewDelegate delegate = delegates.valueAt(i);
90 |
91 | if (delegate.isForViewType( item, position))
92 | {
93 | delegate.convert(holder, item, position);
94 | return;
95 | }
96 | }
97 | throw new IllegalArgumentException(
98 | "No ItemViewDelegateManager added that matches position=" + position + " in data source");
99 | }
100 |
101 |
102 | public ItemViewDelegate getItemViewDelegate(int viewType)
103 | {
104 | return delegates.get(viewType);
105 | }
106 |
107 | public int getItemViewLayoutId(int viewType)
108 | {
109 | return getItemViewDelegate(viewType).getItemViewLayoutId();
110 | }
111 |
112 | public int getItemViewType(ItemViewDelegate itemViewDelegate)
113 | {
114 | return delegates.indexOfValue(itemViewDelegate);
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/baseadapter-recyclerview/src/main/java/com/zhy/adapter/recyclerview/utils/WrapperUtils.java:
--------------------------------------------------------------------------------
1 | package com.zhy.adapter.recyclerview.utils;
2 |
3 | import android.support.v7.widget.GridLayoutManager;
4 | import android.support.v7.widget.RecyclerView;
5 | import android.support.v7.widget.StaggeredGridLayoutManager;
6 | import android.view.ViewGroup;
7 |
8 | /**
9 | * Created by zhy on 16/6/28.
10 | */
11 | public class WrapperUtils
12 | {
13 | public interface SpanSizeCallback
14 | {
15 | int getSpanSize(GridLayoutManager layoutManager , GridLayoutManager.SpanSizeLookup oldLookup, int position);
16 | }
17 |
18 | public static void onAttachedToRecyclerView(RecyclerView.Adapter innerAdapter, RecyclerView recyclerView, final SpanSizeCallback callback)
19 | {
20 | innerAdapter.onAttachedToRecyclerView(recyclerView);
21 |
22 | RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
23 | if (layoutManager instanceof GridLayoutManager)
24 | {
25 | final GridLayoutManager gridLayoutManager = (GridLayoutManager) layoutManager;
26 | final GridLayoutManager.SpanSizeLookup spanSizeLookup = gridLayoutManager.getSpanSizeLookup();
27 |
28 | gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup()
29 | {
30 | @Override
31 | public int getSpanSize(int position)
32 | {
33 | return callback.getSpanSize(gridLayoutManager, spanSizeLookup, position);
34 | }
35 | });
36 | gridLayoutManager.setSpanCount(gridLayoutManager.getSpanCount());
37 | }
38 | }
39 |
40 | public static void setFullSpan(RecyclerView.ViewHolder holder)
41 | {
42 | ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams();
43 |
44 | if (lp != null
45 | && lp instanceof StaggeredGridLayoutManager.LayoutParams)
46 | {
47 |
48 | StaggeredGridLayoutManager.LayoutParams p = (StaggeredGridLayoutManager.LayoutParams) lp;
49 |
50 | p.setFullSpan(true);
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/baseadapter-recyclerview/src/main/java/com/zhy/adapter/recyclerview/wrapper/EmptyWrapper.java:
--------------------------------------------------------------------------------
1 | package com.zhy.adapter.recyclerview.wrapper;
2 |
3 | import android.support.v7.widget.GridLayoutManager;
4 | import android.support.v7.widget.RecyclerView;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 |
8 | import com.zhy.adapter.recyclerview.base.ViewHolder;
9 | import com.zhy.adapter.recyclerview.utils.WrapperUtils;
10 |
11 |
12 | /**
13 | * Created by zhy on 16/6/23.
14 | */
15 | public class EmptyWrapper extends RecyclerView.Adapter
16 | {
17 | public static final int ITEM_TYPE_EMPTY = Integer.MAX_VALUE - 1;
18 |
19 | private RecyclerView.Adapter mInnerAdapter;
20 | private View mEmptyView;
21 | private int mEmptyLayoutId;
22 |
23 |
24 | public EmptyWrapper(RecyclerView.Adapter adapter)
25 | {
26 | mInnerAdapter = adapter;
27 | }
28 |
29 | private boolean isEmpty()
30 | {
31 | return (mEmptyView != null || mEmptyLayoutId != 0) && mInnerAdapter.getItemCount() == 0;
32 | }
33 |
34 | @Override
35 | public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
36 | {
37 | if (isEmpty())
38 | {
39 | ViewHolder holder;
40 | if (mEmptyView != null)
41 | {
42 | holder = ViewHolder.createViewHolder(parent.getContext(), mEmptyView);
43 | } else
44 | {
45 | holder = ViewHolder.createViewHolder(parent.getContext(), parent, mEmptyLayoutId);
46 | }
47 | return holder;
48 | }
49 | return mInnerAdapter.onCreateViewHolder(parent, viewType);
50 | }
51 |
52 | @Override
53 | public void onAttachedToRecyclerView(RecyclerView recyclerView)
54 | {
55 | WrapperUtils.onAttachedToRecyclerView(mInnerAdapter, recyclerView, new WrapperUtils.SpanSizeCallback()
56 | {
57 | @Override
58 | public int getSpanSize(GridLayoutManager gridLayoutManager, GridLayoutManager.SpanSizeLookup oldLookup, int position)
59 | {
60 | if (isEmpty())
61 | {
62 | return gridLayoutManager.getSpanCount();
63 | }
64 | if (oldLookup != null)
65 | {
66 | return oldLookup.getSpanSize(position);
67 | }
68 | return 1;
69 | }
70 | });
71 |
72 |
73 | }
74 |
75 | @Override
76 | public void onViewAttachedToWindow(RecyclerView.ViewHolder holder)
77 | {
78 | mInnerAdapter.onViewAttachedToWindow(holder);
79 | if (isEmpty())
80 | {
81 | WrapperUtils.setFullSpan(holder);
82 | }
83 | }
84 |
85 |
86 | @Override
87 | public int getItemViewType(int position)
88 | {
89 | if (isEmpty())
90 | {
91 | return ITEM_TYPE_EMPTY;
92 | }
93 | return mInnerAdapter.getItemViewType(position);
94 | }
95 |
96 | @Override
97 | public void onBindViewHolder(RecyclerView.ViewHolder holder, int position)
98 | {
99 | if (isEmpty())
100 | {
101 | return;
102 | }
103 | mInnerAdapter.onBindViewHolder(holder, position);
104 | }
105 |
106 | @Override
107 | public int getItemCount()
108 | {
109 | if (isEmpty()) return 1;
110 | return mInnerAdapter.getItemCount();
111 | }
112 |
113 |
114 |
115 | public void setEmptyView(View emptyView)
116 | {
117 | mEmptyView = emptyView;
118 | }
119 |
120 | public void setEmptyView(int layoutId)
121 | {
122 | mEmptyLayoutId = layoutId;
123 | }
124 |
125 | }
126 |
--------------------------------------------------------------------------------
/baseadapter-recyclerview/src/main/java/com/zhy/adapter/recyclerview/wrapper/HeaderAndFooterWrapper.java:
--------------------------------------------------------------------------------
1 | package com.zhy.adapter.recyclerview.wrapper;
2 |
3 | import android.support.v4.util.SparseArrayCompat;
4 | import android.support.v7.widget.GridLayoutManager;
5 | import android.support.v7.widget.RecyclerView;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 |
9 | import com.zhy.adapter.recyclerview.base.ViewHolder;
10 | import com.zhy.adapter.recyclerview.utils.WrapperUtils;
11 |
12 |
13 | /**
14 | * Created by zhy on 16/6/23.
15 | */
16 | public class HeaderAndFooterWrapper extends RecyclerView.Adapter
17 | {
18 | private static final int BASE_ITEM_TYPE_HEADER = 100000;
19 | private static final int BASE_ITEM_TYPE_FOOTER = 200000;
20 |
21 | private SparseArrayCompat mHeaderViews = new SparseArrayCompat<>();
22 | private SparseArrayCompat mFootViews = new SparseArrayCompat<>();
23 |
24 | private RecyclerView.Adapter mInnerAdapter;
25 |
26 | public HeaderAndFooterWrapper(RecyclerView.Adapter adapter)
27 | {
28 | mInnerAdapter = adapter;
29 | }
30 |
31 | @Override
32 | public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
33 | {
34 | if (mHeaderViews.get(viewType) != null)
35 | {
36 | ViewHolder holder = ViewHolder.createViewHolder(parent.getContext(), mHeaderViews.get(viewType));
37 | return holder;
38 |
39 | } else if (mFootViews.get(viewType) != null)
40 | {
41 | ViewHolder holder = ViewHolder.createViewHolder(parent.getContext(), mFootViews.get(viewType));
42 | return holder;
43 | }
44 | return mInnerAdapter.onCreateViewHolder(parent, viewType);
45 | }
46 |
47 | @Override
48 | public int getItemViewType(int position)
49 | {
50 | if (isHeaderViewPos(position))
51 | {
52 | return mHeaderViews.keyAt(position);
53 | } else if (isFooterViewPos(position))
54 | {
55 | return mFootViews.keyAt(position - getHeadersCount() - getRealItemCount());
56 | }
57 | return mInnerAdapter.getItemViewType(position - getHeadersCount());
58 | }
59 |
60 | private int getRealItemCount()
61 | {
62 | return mInnerAdapter.getItemCount();
63 | }
64 |
65 |
66 | @Override
67 | public void onBindViewHolder(RecyclerView.ViewHolder holder, int position)
68 | {
69 | if (isHeaderViewPos(position))
70 | {
71 | return;
72 | }
73 | if (isFooterViewPos(position))
74 | {
75 | return;
76 | }
77 | mInnerAdapter.onBindViewHolder(holder, position - getHeadersCount());
78 | }
79 |
80 | @Override
81 | public int getItemCount()
82 | {
83 | return getHeadersCount() + getFootersCount() + getRealItemCount();
84 | }
85 |
86 | @Override
87 | public void onAttachedToRecyclerView(RecyclerView recyclerView)
88 | {
89 | WrapperUtils.onAttachedToRecyclerView(mInnerAdapter, recyclerView, new WrapperUtils.SpanSizeCallback()
90 | {
91 | @Override
92 | public int getSpanSize(GridLayoutManager layoutManager, GridLayoutManager.SpanSizeLookup oldLookup, int position)
93 | {
94 | int viewType = getItemViewType(position);
95 | if (mHeaderViews.get(viewType) != null)
96 | {
97 | return layoutManager.getSpanCount();
98 | } else if (mFootViews.get(viewType) != null)
99 | {
100 | return layoutManager.getSpanCount();
101 | }
102 | if (oldLookup != null)
103 | return oldLookup.getSpanSize(position);
104 | return 1;
105 | }
106 | });
107 | }
108 |
109 | @Override
110 | public void onViewAttachedToWindow(RecyclerView.ViewHolder holder)
111 | {
112 | mInnerAdapter.onViewAttachedToWindow(holder);
113 | int position = holder.getLayoutPosition();
114 | if (isHeaderViewPos(position) || isFooterViewPos(position))
115 | {
116 | WrapperUtils.setFullSpan(holder);
117 | }
118 | }
119 |
120 | private boolean isHeaderViewPos(int position)
121 | {
122 | return position < getHeadersCount();
123 | }
124 |
125 | private boolean isFooterViewPos(int position)
126 | {
127 | return position >= getHeadersCount() + getRealItemCount();
128 | }
129 |
130 |
131 | public void addHeaderView(View view)
132 | {
133 | mHeaderViews.put(mHeaderViews.size() + BASE_ITEM_TYPE_HEADER, view);
134 | }
135 |
136 | public void addFootView(View view)
137 | {
138 | mFootViews.put(mFootViews.size() + BASE_ITEM_TYPE_FOOTER, view);
139 | }
140 |
141 | public int getHeadersCount()
142 | {
143 | return mHeaderViews.size();
144 | }
145 |
146 | public int getFootersCount()
147 | {
148 | return mFootViews.size();
149 | }
150 |
151 |
152 | }
153 |
--------------------------------------------------------------------------------
/baseadapter-recyclerview/src/main/java/com/zhy/adapter/recyclerview/wrapper/LoadMoreWrapper.java:
--------------------------------------------------------------------------------
1 | package com.zhy.adapter.recyclerview.wrapper;
2 |
3 | import android.support.v7.widget.GridLayoutManager;
4 | import android.support.v7.widget.RecyclerView;
5 | import android.support.v7.widget.StaggeredGridLayoutManager;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 |
9 | import com.zhy.adapter.recyclerview.base.ViewHolder;
10 | import com.zhy.adapter.recyclerview.utils.WrapperUtils;
11 |
12 | /**
13 | * Created by DongJr on 2017/1/16.
14 | */
15 |
16 | public class LoadMoreWrapper extends RecyclerView.Adapter {
17 | public static final int ITEM_TYPE_LOAD_MORE = Integer.MAX_VALUE - 2;
18 |
19 | private RecyclerView.Adapter mInnerAdapter;
20 | private View mLoadMoreView;
21 | private int mLoadMoreLayoutId;
22 | private boolean mShouldLoadMore = true;
23 |
24 | public LoadMoreWrapper(RecyclerView.Adapter adapter) {
25 | mInnerAdapter = adapter;
26 | }
27 |
28 | private boolean hasLoadMore() {
29 | return mLoadMoreView != null || mLoadMoreLayoutId != 0;
30 | }
31 |
32 | protected boolean isShowLoadMore(int position) {
33 | return hasLoadMore() && (position >= mInnerAdapter.getItemCount());
34 | }
35 |
36 | @Override
37 | public int getItemViewType(int position) {
38 | if (isShowLoadMore(position)) {
39 | return ITEM_TYPE_LOAD_MORE;
40 | }
41 | return mInnerAdapter.getItemViewType(position);
42 | }
43 |
44 | @Override
45 | public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
46 | if (viewType == ITEM_TYPE_LOAD_MORE) {
47 | ViewHolder holder;
48 | if (mLoadMoreView != null) {
49 | holder = ViewHolder.createViewHolder(parent.getContext(), mLoadMoreView);
50 | } else {
51 | holder = ViewHolder.createViewHolder(parent.getContext(), parent, mLoadMoreLayoutId);
52 | }
53 | return holder;
54 | }
55 | return mInnerAdapter.onCreateViewHolder(parent, viewType);
56 | }
57 |
58 | @Override
59 | public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
60 | if (isShowLoadMore(position)) {
61 | if (mOnLoadMoreListener != null && mShouldLoadMore) {
62 | mOnLoadMoreListener.onLoadMoreRequested();
63 | }
64 | return;
65 | }
66 | mInnerAdapter.onBindViewHolder(holder, position);
67 | }
68 |
69 | public void setShouldLoadMore(boolean shouldLoadMore) {
70 | this.mShouldLoadMore = shouldLoadMore;
71 | }
72 |
73 | @Override
74 | public void onAttachedToRecyclerView(RecyclerView recyclerView) {
75 | WrapperUtils.onAttachedToRecyclerView(mInnerAdapter, recyclerView, new WrapperUtils.SpanSizeCallback() {
76 | @Override
77 | public int getSpanSize(GridLayoutManager layoutManager, GridLayoutManager.SpanSizeLookup oldLookup, int position) {
78 | if (isShowLoadMore(position)) {
79 | return layoutManager.getSpanCount();
80 | }
81 | if (oldLookup != null) {
82 | return oldLookup.getSpanSize(position);
83 | }
84 | return 1;
85 | }
86 | });
87 | }
88 |
89 |
90 | @Override
91 | public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) {
92 | mInnerAdapter.onViewAttachedToWindow(holder);
93 |
94 | if (isShowLoadMore(holder.getLayoutPosition())) {
95 | setFullSpan(holder);
96 | }
97 | }
98 |
99 | private void setFullSpan(RecyclerView.ViewHolder holder) {
100 | ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams();
101 |
102 | if (lp != null
103 | && lp instanceof StaggeredGridLayoutManager.LayoutParams) {
104 | StaggeredGridLayoutManager.LayoutParams p = (StaggeredGridLayoutManager.LayoutParams) lp;
105 |
106 | p.setFullSpan(true);
107 | }
108 | }
109 |
110 | @Override
111 | public int getItemCount() {
112 | if (mInnerAdapter.getItemCount()==0){
113 | return 0;
114 | }
115 | return mInnerAdapter.getItemCount() + (hasLoadMore() ? 1 : 0);
116 | }
117 |
118 |
119 | public interface OnLoadMoreListener {
120 | void onLoadMoreRequested();
121 | }
122 |
123 | private OnLoadMoreListener mOnLoadMoreListener;
124 |
125 | public com.zhy.adapter.recyclerview.wrapper.LoadMoreWrapper setOnLoadMoreListener(OnLoadMoreListener loadMoreListener) {
126 | if (loadMoreListener != null) {
127 | mOnLoadMoreListener = loadMoreListener;
128 | }
129 | return this;
130 | }
131 |
132 | public com.zhy.adapter.recyclerview.wrapper.LoadMoreWrapper setLoadMoreView(View loadMoreView) {
133 | mLoadMoreView = loadMoreView;
134 | return this;
135 | }
136 |
137 | public com.zhy.adapter.recyclerview.wrapper.LoadMoreWrapper setLoadMoreView(int layoutId) {
138 | mLoadMoreLayoutId = layoutId;
139 | return this;
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/baseadapter-recyclerview/src/test/java/com/zhy/baseadapter_recyclerview/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.zhy.baseadapter_recyclerview;
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 | {
12 | @Test
13 | public void addition_isCorrect() throws Exception
14 | {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/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.2.3'
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 | # For more details on how to configure your build environment visit
4 | # http://www.gradle.org/docs/current/userguide/build_environment.html
5 | #
6 | # Specifies the JVM arguments used for the daemon process.
7 | # The setting is particularly useful for tweaking memory settings.
8 | # Default value: -Xmx1024m -XX:MaxPermSize=256m
9 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
10 | #
11 | # When configured, Gradle will run in incubating parallel mode.
12 | # This option should only be used with decoupled projects. More details, visit
13 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
14 | # org.gradle.parallel=true
15 | #Thu Jan 05 20:46:19 CST 2017
16 | systemProp.http.proxyHost=127.0.0.1
17 | systemProp.http.proxyPort=1080
18 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JrDong/Android-Material-Sloth/7dcad2a8a34c72db955034a55a8186cefbbfa4b5/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sat Jan 14 19:16:27 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-2.14.1-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 |
--------------------------------------------------------------------------------
/image/sloth_drawerlayout.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JrDong/Android-Material-Sloth/7dcad2a8a34c72db955034a55a8186cefbbfa4b5/image/sloth_drawerlayout.png
--------------------------------------------------------------------------------
/image/sloth_home.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JrDong/Android-Material-Sloth/7dcad2a8a34c72db955034a55a8186cefbbfa4b5/image/sloth_home.png
--------------------------------------------------------------------------------
/image/sloth_image_preview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JrDong/Android-Material-Sloth/7dcad2a8a34c72db955034a55a8186cefbbfa4b5/image/sloth_image_preview.png
--------------------------------------------------------------------------------
/image/sloth_me.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JrDong/Android-Material-Sloth/7dcad2a8a34c72db955034a55a8186cefbbfa4b5/image/sloth_me.png
--------------------------------------------------------------------------------
/image/sloth_meizi.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JrDong/Android-Material-Sloth/7dcad2a8a34c72db955034a55a8186cefbbfa4b5/image/sloth_meizi.png
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':baseadapter-recyclerview'
2 |
--------------------------------------------------------------------------------