.
23 | */
24 |
25 | package com.fall.gank.Utils;
26 |
27 | import rx.Observable;
28 | import rx.android.schedulers.AndroidSchedulers;
29 | import rx.schedulers.Schedulers;
30 |
31 | /**
32 | * Description:RxUtils
33 | * Created by:CaMnter
34 | * Time:2016-01-13 12:08
35 | */
36 | public class RxUtils {
37 | /**
38 | * {@link Observable.Transformer} that transforms the source observable to subscribe in the
39 | * io thread and observe on the Android's UI thread.
40 | */
41 | private static Observable.Transformer ioToMainThreadSchedulerTransformer;
42 |
43 |
44 | static {
45 | ioToMainThreadSchedulerTransformer = createIOToMainThreadScheduler();
46 | }
47 |
48 |
49 | /**
50 | * Get {@link Observable.Transformer} that transforms the source observable to subscribe in
51 | * the io thread and observe on the Android's UI thread.
52 | *
53 | * Because it doesn't interact with the emitted items it's safe ignore the unchecked casts.
54 | *
55 | * @return {@link Observable.Transformer}
56 | */
57 | @SuppressWarnings("unchecked")
58 | private static Observable.Transformer createIOToMainThreadScheduler() {
59 | return tObservable -> tObservable.subscribeOn(Schedulers.io())
60 | .unsubscribeOn(
61 | Schedulers.computation()) // TODO: remove when https://github.com/square/okhttp/issues/1592 is fixed
62 | .observeOn(AndroidSchedulers.mainThread());
63 | }
64 |
65 |
66 | @SuppressWarnings("unchecked")
67 | public static Observable.Transformer applyIOToMainThreadSchedulers() {
68 | return ioToMainThreadSchedulerTransformer;
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/app/src/main/java/com/fall/gank/entity/ClassificationResultsEntity.java:
--------------------------------------------------------------------------------
1 | package com.fall.gank.entity;
2 |
3 | import java.util.List;
4 |
5 | /**
6 | * Created by qqq34 on 2016/11/30.
7 | */
8 |
9 | public class ClassificationResultsEntity {
10 | /**
11 | * _id : 583c0452421aa9710cf54c47
12 | * createdAt : 2016-11-28T18:17:54.556Z
13 | * desc : 六种二维码生成的样式
14 | * images : ["http://img.gank.io/2f0b6c5f-6de7-4ba3-94ad-98bf721ee447"]
15 | * publishedAt : 2016-11-29T11:38:58.378Z
16 | * source : web
17 | * type : Android
18 | * url : https://github.com/vivian8725118/ZXingDemo/
19 | * used : true
20 | * who : Vivian
21 | */
22 |
23 | private String _id;
24 | private String createdAt;
25 | private String desc;
26 | private String publishedAt;
27 | private String source;
28 | private String type;
29 | private String url;
30 | private boolean used;
31 | private String who;
32 | private List images;
33 | private String videoUrl;
34 |
35 | public String getVideoUrl() {
36 | return videoUrl;
37 | }
38 |
39 | public void setVideoUrl(String videoUrl) {
40 | this.videoUrl = videoUrl;
41 | }
42 |
43 | public String get_id() {
44 | return _id;
45 | }
46 |
47 | public void set_id(String _id) {
48 | this._id = _id;
49 | }
50 |
51 | public String getCreatedAt() {
52 | return createdAt;
53 | }
54 |
55 | public void setCreatedAt(String createdAt) {
56 | this.createdAt = createdAt;
57 | }
58 |
59 | public String getDesc() {
60 | return desc;
61 | }
62 |
63 | public void setDesc(String desc) {
64 | this.desc = desc;
65 | }
66 |
67 | public String getPublishedAt() {
68 | return publishedAt;
69 | }
70 |
71 | public void setPublishedAt(String publishedAt) {
72 | this.publishedAt = publishedAt;
73 | }
74 |
75 | public String getSource() {
76 | return source;
77 | }
78 |
79 | public void setSource(String source) {
80 | this.source = source;
81 | }
82 |
83 | public String getType() {
84 | return type;
85 | }
86 |
87 | public void setType(String type) {
88 | this.type = type;
89 | }
90 |
91 | public String getUrl() {
92 | return url;
93 | }
94 |
95 | public void setUrl(String url) {
96 | this.url = url;
97 | }
98 |
99 | public boolean isUsed() {
100 | return used;
101 | }
102 |
103 | public void setUsed(boolean used) {
104 | this.used = used;
105 | }
106 |
107 | public String getWho() {
108 | return who;
109 | }
110 |
111 | public void setWho(String who) {
112 | this.who = who;
113 | }
114 |
115 | public List getImages() {
116 | return images;
117 | }
118 |
119 | public void setImages(List images) {
120 | this.images = images;
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/app/src/main/java/com/fall/gank/core/BaseActivity.java:
--------------------------------------------------------------------------------
1 | package com.fall.gank.core;
2 |
3 | import android.content.Intent;
4 | import android.databinding.BaseObservable;
5 | import android.os.Bundle;
6 | import android.support.annotation.Nullable;
7 | import android.support.design.widget.Snackbar;
8 | import android.support.v7.app.AppCompatDelegate;
9 | import android.view.View;
10 |
11 | import com.example.rxpermisson.PermissionAppCompatActivity;
12 | import com.fall.gank.callback.BaseActivityCallback;
13 |
14 | import java.io.Serializable;
15 | import java.util.ArrayList;
16 | import java.util.List;
17 |
18 |
19 | /**
20 | * Created by qqq34 on 2016/11/24.
21 | */
22 |
23 | public abstract class BaseActivity extends PermissionAppCompatActivity implements BaseActivityCallback, BaseView {
24 | public static final String KEY_VIEW_MODEL = "BaseActivity.viewmodel";
25 | private View view;
26 | private BaseObservable baseObservable;
27 | private AttachPresenterHelper mAttachPresenterHelper;
28 | protected List iPresenterList ; //储存引用的所有presenter,一个界面可能会有多个Presenter的情况
29 | @Override
30 | protected void onCreate(@Nullable Bundle savedInstanceState) {
31 | super.onCreate(savedInstanceState);
32 | iPresenterList = new ArrayList<>();
33 | if (savedInstanceState != null) {
34 | baseObservable = (BaseObservable) savedInstanceState.get(KEY_VIEW_MODEL);
35 | }
36 | initBinding();
37 | if (baseObservable != null) {
38 | initOldData(baseObservable);
39 | } else {
40 | initData();
41 | }
42 | mAttachPresenterHelper = new AttachPresenterHelper(iPresenterList);
43 | attachViewModel();
44 | initToolbar(savedInstanceState);
45 | initView(savedInstanceState);
46 | view = findViewById(android.R.id.content);
47 | initListeners();
48 | mAttachPresenterHelper.initPresenter(baseObservable == null, this);
49 |
50 | }
51 |
52 | protected abstract void initBinding();
53 |
54 |
55 | @Override
56 | protected void onDestroy() {
57 | mAttachPresenterHelper.destroyPresenter();
58 | super.onDestroy();
59 | }
60 |
61 |
62 | protected abstract void initToolbar(Bundle savedInstanceState);
63 |
64 |
65 | public void attachViewModel() {
66 | mAttachPresenterHelper.attachl();
67 | }
68 |
69 | @Override
70 | public void onShowSnackBar(String s) {
71 | Snackbar.make(view, s, Snackbar.LENGTH_SHORT).show();
72 | }
73 |
74 | @Override
75 | public void onStartActivity(Intent intent) {
76 | startActivity(intent);
77 | }
78 |
79 | @Override
80 | public void onSaveInstanceState(Bundle outState) {
81 | if (getViewModel() != null) {
82 | outState.putSerializable(KEY_VIEW_MODEL, (Serializable) getViewModel());
83 | }
84 | super.onSaveInstanceState(outState);
85 | }
86 |
87 | public boolean isDarkTheme() {
88 | return AppCompatDelegate.getDefaultNightMode() == AppCompatDelegate.MODE_NIGHT_YES;
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/app/src/main/java/com/fall/gank/core/BaseListPresenter.java:
--------------------------------------------------------------------------------
1 | package com.fall.gank.core;
2 |
3 | import android.databinding.BaseObservable;
4 | import android.util.Log;
5 |
6 | import com.anupcowkur.reservoir.Reservoir;
7 | import com.fall.gank.Utils.RxUtils;
8 | import com.fall.gank.viewmodel.BaseListViewModel;
9 |
10 | import java.util.List;
11 |
12 | import rx.Observable;
13 |
14 | /**
15 | * Created by qqq34 on 2017/1/18.
16 | */
17 |
18 | /**
19 | * @param List每一项 Item所对应的 ViewModel的类型
20 | * @param 整个List的界面所对应的ViewModel的类型,BaseListViewModel需要知道自己负责的ListItem的类型。
21 | */
22 |
23 | public abstract class BaseListPresenter> extends BasePresenter {
24 |
25 | protected int page = 1;
26 | protected T listViewModel;
27 |
28 | public BaseListPresenter(T listViewModel) {
29 | this.listViewModel = listViewModel;
30 | }
31 |
32 | protected void loadLocalData(Observable observable, boolean isNewCreate) {
33 | if (isNewCreate) {
34 | mCompositeSubscription.add(observable.compose(RxUtils.applyIOToMainThreadSchedulers())
35 | .toList()
36 | .subscribe(ivmList -> {
37 | if (ivmList.size() > 0) {
38 | listViewModel.setIVMs(ivmList);
39 | showList(listViewModel.getIVMs());
40 | listViewModel.isDataEnable.set(true);
41 | }
42 | }, throwable -> {
43 | getData(page);
44 | }, () -> getData(page)));
45 | } else {
46 | page = listViewModel.getPage();
47 | if (listViewModel.isRefresh.get()) {
48 | getData(page);
49 | }
50 | }
51 | }
52 |
53 | //获取到数据后,需要加载和储存Item的数据
54 |
55 | protected void loadDataComplete(List tempList) {
56 | if (page == 1) {
57 | listViewModel.getIVMs().clear();
58 | }
59 | listViewModel.getIVMs().addAll(tempList);
60 | tempList.clear();
61 | listViewModel.isRefresh.set(false);
62 | showList(listViewModel.getIVMs());
63 | if (page == 1) {
64 | mCompositeSubscription.add(Reservoir.putUsingObservable(getKey(), listViewModel.getIVMs())
65 | .compose(RxUtils.applyIOToMainThreadSchedulers())
66 | .subscribe(aBoolean -> {
67 | }, throwable -> {
68 | }));
69 | }
70 | listViewModel.isDataEnable.set(true);
71 | page++;
72 | listViewModel.setPage(page);
73 |
74 | }
75 |
76 |
77 | public void getData(int page) {
78 | if (page == 1) {
79 | this.page = 1;
80 | }
81 | listViewModel.setPage(this.page);
82 | listViewModel.isRefresh.set(true);
83 | }
84 |
85 |
86 | public void loadNext() {
87 | Log.d("next"," ");
88 | if (page == 1) page++;
89 | if (!listViewModel.isRefresh.get()) {
90 | getData(page);
91 | } else return;
92 | }
93 |
94 | protected abstract String getKey();
95 |
96 | }
97 |
--------------------------------------------------------------------------------
/app/src/main/java/com/fall/gank/Utils/BindingUtils.java:
--------------------------------------------------------------------------------
1 | package com.fall.gank.Utils;
2 |
3 | import android.databinding.BindingAdapter;
4 | import android.net.Uri;
5 | import android.support.v4.widget.SwipeRefreshLayout;
6 | import android.support.v7.widget.Toolbar;
7 | import android.view.View;
8 | import android.webkit.WebView;
9 | import android.widget.ImageView;
10 |
11 | import com.fall.gank.R;
12 | import com.fall.gank.callback.SwipeRefreshListener;
13 | import com.facebook.drawee.view.SimpleDraweeView;
14 |
15 | import me.zhanghai.android.materialprogressbar.MaterialProgressBar;
16 |
17 | /**
18 | * Created by qqq34 on 2016/11/30.
19 | */
20 |
21 | public class BindingUtils {
22 | @BindingAdapter("webProgress")
23 | public static void setPregress(final MaterialProgressBar materialProgressBar,int progress){
24 | materialProgressBar.setProgress(progress);
25 | if (progress==100){
26 | materialProgressBar.setVisibility(View.GONE);
27 | }else {
28 | materialProgressBar.setVisibility(View.VISIBLE);
29 | }
30 | }
31 | @BindingAdapter("frescoImageUri")
32 | public static void showImageByUrl(final SimpleDraweeView simpleDraweeView, String url) {
33 | FrescoUtils.displayWithResize(600, 600, Uri.parse(url), simpleDraweeView);
34 | }
35 |
36 | @BindingAdapter("frescoImageUriWithSmallSize")
37 | public static void showImageByUrlWithSmallSize(final SimpleDraweeView simpleDraweeView, String url) {
38 | FrescoUtils.displayWithResize(350, 350, Uri.parse(url), simpleDraweeView);
39 | }
40 |
41 | @BindingAdapter("setRefreshing")
42 | public static void setRefreshing(final SwipeRefreshLayout swipeRefreshLayout, boolean isRefresh) {
43 |
44 | swipeRefreshLayout.post(() -> swipeRefreshLayout.setRefreshing(isRefresh));
45 | }
46 |
47 | @BindingAdapter("onRefresh")
48 | public static void onRefresh(final SwipeRefreshLayout swipeRefreshLayout, SwipeRefreshListener swipeRefreshListener) {
49 | swipeRefreshLayout.setOnRefreshListener(swipeRefreshListener::onRefresh);
50 | }
51 |
52 | @BindingAdapter("homeTint")
53 | public static void setTint(final ImageView imageView, int current) {
54 | if (imageView.getTag().equals(current + "")) {
55 | imageView.setColorFilter(imageView.getResources().getColor(R.color.colorPrimary));
56 | } else {
57 | imageView.setColorFilter(imageView.getResources().getColor(R.color.SecondaryText));
58 | }
59 |
60 | }
61 |
62 | @BindingAdapter("classificationLikeTint")
63 | public static void setLikeTint(final ImageView imageView, boolean islike) {
64 | if (islike) {
65 | imageView.setColorFilter(imageView.getResources().getColor(R.color.favorite_color));
66 | } else {
67 | imageView.setColorFilter(imageView.getResources().getColor(R.color.SecondaryText));
68 | }
69 |
70 | }
71 |
72 | @BindingAdapter("webview_url")
73 | public static void setWebUrl(final WebView webView, String url) {
74 | webView.loadUrl(url);
75 | }
76 |
77 | @BindingAdapter("toolbar_title")
78 | public static void setTitle(final Toolbar toolbar, String s){
79 | toolbar.setTitle(s);
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/app/src/main/java/com/fall/gank/view/activity/PhotoActivity.java:
--------------------------------------------------------------------------------
1 | package com.fall.gank.view.activity;
2 |
3 | import android.Manifest;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.net.Uri;
7 | import android.os.Bundle;
8 | import android.support.design.widget.Snackbar;
9 | import android.support.v7.widget.Toolbar;
10 | import android.view.Menu;
11 |
12 | import com.example.rxpermisson.PermissionAppCompatActivity;
13 | import com.fall.gank.R;
14 | import com.fall.gank.Utils.FrescoUtils;
15 | import com.fall.gank.Utils.MDStatusBarCompat;
16 |
17 | import me.relex.photodraweeview.PhotoDraweeView;
18 | import rx.Subscription;
19 |
20 | /**
21 | * Created by qqq34 on 2016/12/12.
22 | */
23 |
24 | public class PhotoActivity extends PermissionAppCompatActivity {
25 | private static final String EXTRA_URL = "PhotoActivity.url";
26 | private Subscription mSubscription;
27 |
28 | @Override
29 | public void onCreate(Bundle savedInstanceState) {
30 | super.onCreate(savedInstanceState);
31 | setContentView(R.layout.activity_photo);
32 | String url = getIntent().getStringExtra(EXTRA_URL);
33 | MDStatusBarCompat.setImageTranslucent(this);
34 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
35 | toolbar.setTitle("查看图片");
36 | setSupportActionBar(toolbar);
37 | getSupportActionBar().setDisplayHomeAsUpEnabled(true);
38 | toolbar.setNavigationOnClickListener(view -> {
39 | finish();
40 | });
41 | PhotoDraweeView photoDraweeView = (PhotoDraweeView) findViewById(R.id.photo_drawee_view);
42 | photoDraweeView.setPhotoUri(Uri.parse(url));
43 | toolbar.setOnMenuItemClickListener(item -> {
44 | switch (item.getItemId()) {
45 | case R.id.save_photo:
46 | mSubscription = checkPermission(R.string.base_permission, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE)
47 | .subscribe(aBoolean -> {
48 | if (aBoolean) {
49 | FrescoUtils.savePicture(url, PhotoActivity.this);
50 | Snackbar.make(toolbar, "保存成功!路径:" + FrescoUtils.IMAGE_PIC_CACHE_DIR, Snackbar.LENGTH_LONG).show();
51 | }else {
52 | Snackbar.make(toolbar, "保存失败,app没有相应的权限", Snackbar.LENGTH_LONG).show();
53 |
54 | }
55 | }, throwable -> {
56 | });
57 |
58 |
59 | break;
60 | }
61 | return true;
62 | });
63 | }
64 |
65 | public static void newIntent(Context context, String url) {
66 | Intent intent = new Intent(context, PhotoActivity.class);
67 | intent.putExtra(EXTRA_URL, url);
68 | context.startActivity(intent);
69 | }
70 |
71 | @Override
72 | public boolean onCreateOptionsMenu(Menu menu) {
73 | getMenuInflater().inflate(R.menu.menu_photo, menu);
74 | return true;
75 | }
76 |
77 | @Override
78 | protected void onDestroy() {
79 | super.onDestroy();
80 | if (mSubscription != null) {
81 | mSubscription.unsubscribe();
82 | }
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/app/src/main/java/com/fall/gank/view/fragment/SettingFragment.java:
--------------------------------------------------------------------------------
1 | package com.fall.gank.view.fragment;
2 |
3 | import android.content.Intent;
4 | import android.content.res.Configuration;
5 | import android.databinding.BaseObservable;
6 | import android.os.Bundle;
7 | import android.support.annotation.Nullable;
8 | import android.support.v7.app.AppCompatDelegate;
9 | import android.support.v7.widget.SwitchCompat;
10 | import android.util.Log;
11 | import android.view.LayoutInflater;
12 | import android.view.View;
13 | import android.view.ViewGroup;
14 | import android.widget.CompoundButton;
15 |
16 | import com.fall.gank.core.BaseFragment;
17 | import com.fall.gank.core.IPresenter;
18 | import com.fall.gank.databinding.FragmentSettingBinding;
19 | import com.fall.gank.presenter.SettingFragmentPresenter;
20 | import com.fall.gank.view.activity.CollectionActivity;
21 | import com.fall.gank.viewmodel.SettingViewModel;
22 |
23 | import java.util.ArrayList;
24 | import java.util.List;
25 |
26 | /**
27 | * Created by qqq34 on 2016/11/29.
28 | */
29 |
30 | public class SettingFragment extends BaseFragment {
31 | private FragmentSettingBinding binding;
32 | private SettingFragmentPresenter mSettingFragmentPresenter;
33 | private SettingViewModel mSettingViewModel;
34 |
35 | @Override
36 | protected View initBinding(LayoutInflater inflater, ViewGroup container) {
37 | binding = FragmentSettingBinding.inflate(inflater, container, false);
38 | return binding.getRoot();
39 | }
40 |
41 | @Override
42 | public void initView(@Nullable Bundle savedInstanceState) {
43 |
44 | }
45 |
46 | @Override
47 | public void initListeners() {
48 | binding.switchbutton.setOnCheckedChangeListener((compoundButton, b) -> {
49 | if (b) {
50 | if (!isDarkTheme()) {
51 | AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
52 | mSettingFragmentPresenter.updateSetting(true);
53 | getActivity().recreate();
54 | }
55 |
56 |
57 | } else {
58 | if (isDarkTheme()) {
59 | AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
60 | mSettingFragmentPresenter.updateSetting(false);
61 | getActivity().recreate();
62 | }
63 |
64 | }
65 | });
66 | binding.collectionLayout.setOnClickListener(view -> {
67 | startActivity(new Intent(getActivity(), CollectionActivity.class));
68 | });
69 | }
70 |
71 | @Override
72 | public void initOldData(@Nullable BaseObservable baseObservable) {
73 | mSettingViewModel = (SettingViewModel) baseObservable;
74 | mSettingViewModel.setDarkTheme(isDarkTheme());
75 | binding.setViewModel(mSettingViewModel);
76 | mSettingFragmentPresenter = new SettingFragmentPresenter(mSettingViewModel);
77 | iPresenterList.add(mSettingFragmentPresenter);
78 | }
79 |
80 | @Override
81 | public void initData() {
82 |
83 | mSettingViewModel = new SettingViewModel(isDarkTheme());
84 | binding.setViewModel(mSettingViewModel);
85 | mSettingFragmentPresenter = new SettingFragmentPresenter(mSettingViewModel);
86 | iPresenterList.add(mSettingFragmentPresenter);
87 | }
88 |
89 |
90 | @Override
91 | public BaseObservable getViewModel() {
92 | return mSettingViewModel;
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/app/src/main/java/com/fall/gank/presenter/HomeFragmentPresenter.java:
--------------------------------------------------------------------------------
1 | package com.fall.gank.presenter;
2 |
3 | import android.Manifest;
4 | import android.util.Log;
5 |
6 | import com.anupcowkur.reservoir.Reservoir;
7 | import com.fall.gank.R;
8 | import com.fall.gank.Utils.RxUtils;
9 | import com.fall.gank.core.BaseListPresenter;
10 | import com.fall.gank.network.model.IDataManager;
11 | import com.fall.gank.network.model.impl.DataManager;
12 | import com.fall.gank.viewmodel.HomeItemViewModel;
13 | import com.fall.gank.viewmodel.HomeViewModel;
14 | import com.fall.gank.viewmodel.ImageItemViewModel;
15 | import com.google.gson.reflect.TypeToken;
16 | import com.tinkerpatch.sdk.TinkerPatch;
17 |
18 | import java.lang.reflect.Type;
19 | import java.util.ArrayList;
20 | import java.util.List;
21 |
22 | import rx.Observable;
23 |
24 | /**
25 | * Created by 康颢曦 on 2016/11/27.
26 | */
27 |
28 | public class HomeFragmentPresenter extends BaseListPresenter {
29 | private String KEY = "HomeFragmentPresenter.homeData";
30 | private IDataManager mManager = new DataManager();
31 | // private SingleTypeAdapter mAdapter;
32 | private List mHomeItemViewModels = new ArrayList<>();
33 |
34 | public HomeFragmentPresenter(HomeViewModel listViewModel) {
35 | super(listViewModel);
36 | }
37 |
38 | @Override
39 | public void onPresenterCreate(boolean isNewCreate) {
40 | if (isNewCreate) {
41 | mCompositeSubscription.add(checkPermission(R.string.base_permission, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE)
42 | .subscribe(aBoolean -> {
43 | if (aBoolean) {
44 | TinkerPatch.with().fetchPatchUpdate(true);
45 | }
46 | }, throwable -> {
47 | }));
48 |
49 | }
50 | Type collectionType = new TypeToken>() {}.getType();
51 | loadLocalData(Reservoir.getUsingObservable(KEY, HomeItemViewModel.class, collectionType), isNewCreate);
52 | }
53 |
54 | @Override
55 | public void getData(int page) {
56 | super.getData(page);
57 | mCompositeSubscription.add(mManager.getHomeData(this.page)
58 | .compose(RxUtils.applyIOToMainThreadSchedulers())
59 | .map(classificationEntity -> classificationEntity.getResults())
60 | .flatMap(Observable::from)
61 | .subscribe(classificationResultsEntity -> {
62 | String[] strings = classificationResultsEntity.getDesc().split("######");
63 | if (strings.length == 2) {
64 | mHomeItemViewModels.add(new HomeItemViewModel(classificationResultsEntity.getUrl(), strings[1], strings[0], classificationResultsEntity.getVideoUrl()));
65 | } else {
66 | mHomeItemViewModels.add(new HomeItemViewModel(classificationResultsEntity.getUrl(), classificationResultsEntity.getDesc(), "未知", classificationResultsEntity.getVideoUrl()));
67 | }
68 |
69 | }, throwable -> {
70 | listViewModel.isRefresh.set(false);
71 | loadError(throwable);
72 | }, () -> {
73 | loadDataComplete(mHomeItemViewModels);
74 | }));
75 | }
76 |
77 | @Override
78 | protected String getKey() {
79 | return KEY;
80 | }
81 |
82 |
83 | }
84 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/view_home_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 |
13 |
14 |
17 |
18 |
21 |
22 |
23 |
32 |
33 |
43 |
44 |
48 |
49 |
56 |
57 |
64 |
65 |
72 |
73 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
--------------------------------------------------------------------------------
/app/src/main/java/com/fall/gank/entity/ClassificationEntity.java:
--------------------------------------------------------------------------------
1 | package com.fall.gank.entity;
2 |
3 | import java.util.List;
4 |
5 | /**
6 | * Created by qqq34 on 2016/11/30.
7 | */
8 |
9 | public class ClassificationEntity {
10 |
11 | /**
12 | * error : false
13 | * results : [{"_id":"583c0452421aa9710cf54c47","createdAt":"2016-11-28T18:17:54.556Z","desc":"六种二维码生成的样式","images":["http://img.gank.io/2f0b6c5f-6de7-4ba3-94ad-98bf721ee447"],"publishedAt":"2016-11-29T11:38:58.378Z","source":"web","type":"Android","url":"https://github.com/vivian8725118/ZXingDemo/","used":true,"who":"Vivian"},{"_id":"583c4dc6421aa9710cf54c4a","createdAt":"2016-11-28T23:31:18.761Z","desc":"Java设计模式之单例模式","publishedAt":"2016-11-29T11:38:58.378Z","source":"web","type":"Android","url":"http://www.haotianyi.win/2016/11/java%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E4%B9%8B%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F.html","used":true,"who":"HaoTianYi"},{"_id":"583ce4dd421aa939befafac7","createdAt":"2016-11-29T10:15:57.829Z","desc":"验证码图片 ImageView,相当实用!","images":["http://img.gank.io/940c9fd7-3c57-4152-b496-271bca9f20ae"],"publishedAt":"2016-11-29T11:38:58.378Z","source":"chrome","type":"Android","url":"https://github.com/jineshfrancs/CaptchaImageView","used":true,"who":"代码家"},{"_id":"583ce5df421aa939bb4637bc","createdAt":"2016-11-29T10:20:15.562Z","desc":"超漂亮的,支持展开菜单的 Fab 按钮。","images":["http://img.gank.io/76f6993b-d103-40e0-8c30-fb1d246e23a0"],"publishedAt":"2016-11-29T11:38:58.378Z","source":"chrome","type":"Android","url":"https://github.com/JoaquimLey/faboptions","used":true,"who":"嗲马甲"},{"_id":"583ce6d8421aa939bb4637bd","createdAt":"2016-11-29T10:24:24.521Z","desc":"类似 Google Inbox 的实现,做的不错","images":["http://img.gank.io/bc5b51d8-2974-4c87-a6ec-8ccc451aea0b"],"publishedAt":"2016-11-29T11:38:58.378Z","source":"chrome","type":"Android","url":"https://github.com/memfis19/Cadar","used":true,"who":"代码家"},{"_id":"583129bf421aa929ac960afc","createdAt":"2016-11-20T12:42:39.884Z","desc":"Android 实现视屏播放器、边播边缓存功能、外加铲屎(IJKPlayer)","images":["http://img.gank.io/8196d110-32cf-41bc-86c6-801af152a743"],"publishedAt":"2016-11-28T11:32:07.534Z","source":"chrome","type":"Android","url":"http://www.jianshu.com/p/9fe377dd9750","used":true,"who":"Jason"},{"_id":"583a2a98421aa91cb7afe7f4","createdAt":"2016-11-27T08:36:40.493Z","desc":"很赞的登录注册布局","images":["http://img.gank.io/dacc7f4c-3872-4c00-b669-3ab13b430e01"],"publishedAt":"2016-11-28T11:32:07.534Z","source":"chrome","type":"Android","url":"https://github.com/irfaan008/OnePageSigninSignup","used":true,"who":"蒋朋"},{"_id":"583b7e97421aa9711460f744","createdAt":"2016-11-28T08:47:19.286Z","desc":"清晰灵活简单易用的应用更新库","images":["http://img.gank.io/9d7deebb-3fa8-43dc-a36c-81a11044b394"],"publishedAt":"2016-11-28T11:32:07.534Z","source":"web","type":"Android","url":"https://github.com/czy1121/update","used":true,"who":"ezy"},{"_id":"583b99d1421aa9710cf54c3e","createdAt":"2016-11-28T10:43:29.756Z","desc":"目测是目前来看做 Blur 效果速度最快的库","images":["http://img.gank.io/f826f969-027d-43d6-bb00-a89684e37346"],"publishedAt":"2016-11-28T11:32:07.534Z","source":"chrome","type":"Android","url":"https://github.com/wonderkiln/blurkit-android","used":true,"who":"嗲马甲"},{"_id":"5836a7fc421aa91cb7afe7e0","createdAt":"2016-11-24T16:42:36.919Z","desc":"支持https的ijkplayer播放器","images":["http://img.gank.io/22aa7a50-de1f-4697-8eb8-7bcc247cce58"],"publishedAt":"2016-11-25T11:29:49.832Z","source":"web","type":"Android","url":"https://github.com/l123456789jy/ijkplayer","used":true,"who":"Lazy"}]
14 | */
15 |
16 | private List results;
17 |
18 | public List getResults() {
19 | return results;
20 | }
21 |
22 | public void setResults(List results) {
23 | this.results = results;
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/java/com/fall/gank/core/BaseFragment.java:
--------------------------------------------------------------------------------
1 | package com.fall.gank.core;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.databinding.BaseObservable;
6 | import android.os.Bundle;
7 | import android.support.annotation.Nullable;
8 | import android.support.v4.app.Fragment;
9 | import android.support.v7.app.AppCompatDelegate;
10 | import android.util.Log;
11 | import android.view.LayoutInflater;
12 | import android.view.View;
13 | import android.view.ViewGroup;
14 |
15 | import com.fall.gank.callback.BaseActivityCallback;
16 |
17 | import java.io.Serializable;
18 | import java.util.ArrayList;
19 | import java.util.List;
20 |
21 | /**
22 | * Created by 康颢曦 on 2016/11/27.
23 | */
24 |
25 | public abstract class BaseFragment extends Fragment implements BaseView {
26 | public static final String KEY_VIEW_MODEL = "BaseFragment.viewmodel";
27 | private BaseObservable baseObservable;
28 | private BaseActivityCallback baseActivityCallback;
29 | private AttachPresenterHelper mAttachPresenterHelper;
30 | protected List iPresenterList ; //储存引用的所有presenter,一个界面可能会有多个Presenter的情况
31 | @Override
32 | public void onCreate(@Nullable Bundle savedInstanceState) {
33 | super.onCreate(savedInstanceState);
34 | setRetainInstance(true);
35 | }
36 |
37 |
38 | @Nullable
39 | @Override
40 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
41 | iPresenterList = new ArrayList<>();
42 | if (savedInstanceState != null) {
43 | baseObservable = (BaseObservable) savedInstanceState.get(KEY_VIEW_MODEL);
44 | }
45 | View view = initBinding(inflater, container);
46 | if (baseObservable != null) {
47 | initOldData(baseObservable);
48 | } else {
49 | initData();
50 | }
51 | mAttachPresenterHelper = new AttachPresenterHelper(iPresenterList);
52 | attachViewModel();
53 | initView(savedInstanceState);
54 | mAttachPresenterHelper.initPresenter(baseObservable == null, baseActivityCallback);
55 | initListeners();
56 | return view;
57 | }
58 |
59 | protected abstract View initBinding(LayoutInflater inflater, ViewGroup container);
60 |
61 | @Override
62 | public void onAttach(Context context) {
63 | Activity activity = (Activity) context;
64 | if (activity instanceof BaseActivity) {
65 | baseActivityCallback = (BaseActivity) activity;
66 | }
67 | super.onAttach(context);
68 |
69 | }
70 |
71 | @Override
72 | public void onDetach() {
73 | baseActivityCallback = null;
74 | super.onDetach();
75 | }
76 |
77 |
78 | public void attachViewModel() {
79 | mAttachPresenterHelper.attachl();
80 | }
81 |
82 | @Override
83 | public void onDestroy() {
84 | mAttachPresenterHelper.destroyPresenter();
85 | super.onDestroy();
86 | }
87 |
88 | @Override
89 | public void onSaveInstanceState(Bundle outState) {
90 | if (getViewModel() != null) {
91 | outState.putSerializable(KEY_VIEW_MODEL, (Serializable) getViewModel());
92 | }
93 | super.onSaveInstanceState(outState);
94 | }
95 |
96 | @Override
97 | public void setUserVisibleHint(boolean isVisibleToUser) {
98 | super.setUserVisibleHint(isVisibleToUser);
99 | if (isVisibleToUser) {
100 | Log.d("tag", "可见");
101 | }
102 | }
103 |
104 | public boolean isDarkTheme() {
105 | return AppCompatDelegate.getDefaultNightMode() == AppCompatDelegate.MODE_NIGHT_YES;
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/app/src/main/java/com/fall/gank/presenter/ClassificationPresenter.java:
--------------------------------------------------------------------------------
1 | package com.fall.gank.presenter;
2 |
3 | import android.util.Log;
4 |
5 | import com.anupcowkur.reservoir.Reservoir;
6 | import com.fall.gank.Utils.RxUtils;
7 | import com.fall.gank.core.BaseListPresenter;
8 | import com.fall.gank.database.Collection;
9 | import com.fall.gank.network.model.impl.DataManager;
10 | import com.fall.gank.network.model.IDataManager;
11 | import com.fall.gank.viewmodel.ClassificationViewModel;
12 | import com.fall.gank.viewmodel.ClassificationItemViewModel;
13 | import com.google.gson.reflect.TypeToken;
14 |
15 | import java.lang.reflect.Type;
16 | import java.util.ArrayList;
17 | import java.util.List;
18 |
19 | /**
20 | * Created by 康颢曦 on 2016/11/27.
21 | */
22 |
23 | public class ClassificationPresenter extends BaseListPresenter {
24 | private String KEY = "ClassificationPresenter.Key";
25 | private String type;
26 | private IDataManager mManager = new DataManager();
27 | private List mList = new ArrayList<>();
28 |
29 | public ClassificationPresenter(ClassificationViewModel listViewModel) {
30 | super(listViewModel);
31 | }
32 |
33 | @Override
34 | public void onPresenterCreate(boolean isNewCreate) {
35 | if (isNewCreate) {
36 | Type collectionType = new TypeToken>() {
37 | }.getType();
38 | mCompositeSubscription.add(Reservoir.getUsingObservable(KEY + type, ClassificationItemViewModel.class, collectionType)
39 | .compose(RxUtils.applyIOToMainThreadSchedulers())
40 | .map(classificationItemViewModel -> {
41 | List list = Collection.find(Collection.class, "url=?", classificationItemViewModel.url.get());
42 | if (list.size() > 0) {
43 | classificationItemViewModel.isLike.set(true);
44 | } else {
45 | classificationItemViewModel.isLike.set(false);
46 | }
47 | return classificationItemViewModel;
48 | })
49 | .toList()
50 | .subscribe(classificationItemViewModels -> {
51 |
52 | if (classificationItemViewModels.size() > 0) {
53 | listViewModel.setIVMs(classificationItemViewModels);
54 | // mAdapter.set(listViewModel.getHomeItemViewModelList());
55 | showList(listViewModel.getIVMs());
56 | listViewModel.isDataEnable.set(true);
57 | }
58 | }, throwable -> getData(page), () -> getData(page)));
59 | } else {
60 | page = listViewModel.getPage();
61 | if (listViewModel.isRefresh.get()) {
62 | getData(page);
63 | }
64 | }
65 | }
66 |
67 | @Override
68 | public void getData(int page) {
69 | super.getData(page);
70 | Log.d("page",page+"");
71 | mCompositeSubscription.add(mManager.getClassificationData(type, page)
72 | .compose(RxUtils.applyIOToMainThreadSchedulers())
73 | .subscribe(classificationItemViewModel -> {
74 | if (classificationItemViewModel != null) {
75 | mList.add(classificationItemViewModel);
76 | }
77 |
78 | }, throwable -> {
79 | listViewModel.isRefresh.set(false);
80 | loadError(throwable);
81 | }
82 | , () -> {
83 | loadDataComplete(mList);
84 | }));
85 | }
86 |
87 | @Override
88 | protected String getKey() {
89 | return KEY+type;
90 | }
91 | public void setType(String type) {
92 | this.type = type;
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/app/src/main/java/com/fall/gank/view/fragment/FuliFragment.java:
--------------------------------------------------------------------------------
1 | package com.fall.gank.view.fragment;
2 |
3 | import android.databinding.BaseObservable;
4 | import android.os.Bundle;
5 | import android.support.annotation.Nullable;
6 | import android.support.v7.widget.GridLayoutManager;
7 | import android.view.LayoutInflater;
8 | import android.view.View;
9 | import android.view.ViewGroup;
10 |
11 | import com.fall.gank.R;
12 | import com.fall.gank.Utils.ListLoadNextHelper;
13 | import com.fall.gank.core.BaseListFragment;
14 | import com.fall.gank.core.IPresenter;
15 | import com.fall.gank.databinding.FragmentFuliBinding;
16 | import com.fall.gank.presenter.FuliFragmentPresenter;
17 | import com.fall.gank.view.activity.PhotoActivity;
18 | import com.fall.gank.viewmodel.FuliViewModel;
19 | import com.fall.gank.viewmodel.ImageItemViewModel;
20 | import com.github.markzhai.recyclerview.SingleTypeAdapter;
21 |
22 | import java.util.ArrayList;
23 | import java.util.List;
24 |
25 | /**
26 | * Created by 康颢曦 on 2016/11/27.
27 | */
28 |
29 | public class FuliFragment extends BaseListFragment {
30 | private FragmentFuliBinding binding;
31 | private FuliFragmentPresenter fuliFragmentPresenter;
32 | private FuliViewModel fuliViewModel;
33 | private SingleTypeAdapter mAdapter;
34 | private GridLayoutManager mGridLayoutManager;
35 | private ListLoadNextHelper listLoadNextHelper;
36 | @Override
37 | protected View initBinding(LayoutInflater inflater, ViewGroup container) {
38 | binding = FragmentFuliBinding.inflate(inflater, container, false);
39 | return binding.getRoot();
40 | }
41 |
42 | @Override
43 | public void initView(@Nullable Bundle savedInstanceState) {
44 | mGridLayoutManager.scrollToPositionWithOffset(fuliViewModel.getPosition(), fuliViewModel.getLastOffset());
45 | }
46 |
47 | @Override
48 | public void initListeners() {
49 | super.initListeners();
50 | binding.swipeContainer.setColorSchemeColors(getResources().getColor(R.color.colorPrimary));
51 | binding.swipeContainer.setProgressBackgroundColorSchemeColor(getResources().getColor(R.color.swipeColor));
52 | binding.setRefreshListener(() -> fuliFragmentPresenter.getData(1));
53 | mAdapter.setPresenter((SingleTypeAdapter.Presenter) imageItemViewModel -> {
54 | PhotoActivity.newIntent(getContext(), imageItemViewModel.url.get());
55 | });
56 | listLoadNextHelper = new ListLoadNextHelper(binding.fuliList);
57 | listLoadNextHelper.setListOffsetListener((lastOffset, position) -> {
58 | fuliViewModel.setLastOffset(lastOffset);
59 | fuliViewModel.setPosition(position);
60 | });
61 | listLoadNextHelper.setScrollLastListener(() -> {
62 | if (fuliViewModel.isDataEnable.get()) {
63 | fuliFragmentPresenter.loadNext();
64 | }
65 | });
66 | }
67 |
68 | @Override
69 | public SingleTypeAdapter getAdapter() {
70 | return mAdapter;
71 | }
72 |
73 | @Override
74 | public void initOldData(@Nullable BaseObservable baseObservable) {
75 | fuliViewModel = (FuliViewModel) baseObservable;
76 | initList();
77 | fuliFragmentPresenter = new FuliFragmentPresenter(fuliViewModel);
78 | iPresenterList.add(fuliFragmentPresenter);
79 | }
80 |
81 | @Override
82 | public void initData() {
83 | fuliViewModel = new FuliViewModel();
84 | initList();
85 | fuliFragmentPresenter = new FuliFragmentPresenter(fuliViewModel);
86 | iPresenterList.add(fuliFragmentPresenter);
87 | }
88 |
89 |
90 |
91 | @Override
92 | public BaseObservable getViewModel() {
93 | return fuliViewModel;
94 | }
95 |
96 | private void initList() {
97 | mAdapter = new SingleTypeAdapter<>(getContext(), R.layout.view_image);
98 | if (fuliViewModel.getIVMs().size() > 0) {
99 | mAdapter.addAll(fuliViewModel.getIVMs());
100 | }
101 | binding.setAdapter(mAdapter);
102 | mGridLayoutManager = new GridLayoutManager(getContext(), 2);
103 | binding.setLayoutmanager(mGridLayoutManager);
104 | binding.setViewmodel(fuliViewModel);
105 |
106 | }
107 |
108 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/fall/gank/network/model/impl/DataManager.java:
--------------------------------------------------------------------------------
1 | package com.fall.gank.network.model.impl;
2 |
3 | import android.util.Log;
4 |
5 | import com.fall.gank.Utils.TimeUtils;
6 | import com.fall.gank.database.Collection;
7 | import com.fall.gank.entity.ClassificationEntity;
8 | import com.fall.gank.entity.ClassificationResultsEntity;
9 | import com.fall.gank.network.model.IDataManager;
10 | import com.fall.gank.network.model.IGankModel;
11 | import com.fall.gank.network.model.impl.GankModel;
12 | import com.fall.gank.viewmodel.ClassificationItemViewModel;
13 |
14 | import java.text.ParseException;
15 | import java.util.HashMap;
16 | import java.util.List;
17 |
18 | import rx.Observable;
19 |
20 | import static com.fall.gank.view.fragment.ClassificationFragment.COLLECTION_TYPE;
21 |
22 | /**
23 | * Created by qqq34 on 2016/11/30.
24 | */
25 |
26 | public class DataManager implements IDataManager {
27 | private IGankModel mIGankModel = GankModel.getInstance();
28 |
29 | @Override
30 | public Observable getHomeData(int page) {
31 | Log.d("tag", page + "");
32 | Observable observable = Observable.zip(mIGankModel.getClassifiData("福利", page), mIGankModel.getClassifiData("休息视频", page), this::createHomeData);
33 | return observable;
34 | }
35 |
36 | @Override
37 | public Observable getClassificationData(String section, int page) {
38 | Observable> observable;
39 | if (section.equals(COLLECTION_TYPE)) {
40 | observable = Observable.create(subscriber -> {
41 | try {
42 | if (page==1){
43 | List collections = Collection.listAll(Collection.class);
44 | subscriber.onNext(collections);
45 | subscriber.onCompleted();
46 | }else {
47 | subscriber.onNext(null);
48 | subscriber.onCompleted();
49 | }
50 |
51 | } catch (Exception e) {
52 | subscriber.onError(e);
53 | }
54 |
55 | });
56 | return observable.flatMap(Observable::from)
57 | .map(collection -> {
58 | ClassificationItemViewModel model = new ClassificationItemViewModel(collection.getClassificationName(), collection.getDimension(), collection.getYear(), collection.getMonthAndDay(), true, collection.getUrl());
59 | return model;
60 | });
61 | } else {
62 | return mIGankModel.getClassifiData(section, page)
63 | .map(classificationEntity -> classificationEntity.getResults())
64 | .flatMap(Observable::from)
65 | .map(classificationResultsEntity -> {
66 | HashMap hashMap;
67 | try {
68 | hashMap = TimeUtils.getTime(classificationResultsEntity.getPublishedAt());
69 | ClassificationItemViewModel model = new ClassificationItemViewModel(classificationResultsEntity.getType(), classificationResultsEntity.getDesc(), hashMap.get(TimeUtils.YEAR), hashMap.get(TimeUtils.MONTH) + "/" + hashMap.get(TimeUtils.DAY), false, classificationResultsEntity.getUrl());
70 | List list = Collection.find(Collection.class, "url=?", model.url.get());
71 | if (list.size() > 0) {
72 | model.isLike.set(true);
73 | } else {
74 | model.isLike.set(false);
75 | }
76 | return model;
77 | } catch (Exception e) {
78 | Observable.error(e);
79 | }
80 | return null;
81 | });
82 | }
83 |
84 |
85 | }
86 |
87 | private ClassificationEntity createHomeData(ClassificationEntity data1, ClassificationEntity data2) {
88 | for (int i = 0; i < data1.getResults().size(); i++) {
89 | ClassificationResultsEntity fuli = data1.getResults().get(i);
90 | ClassificationResultsEntity reset = data2.getResults().get(i);
91 | try {
92 | HashMap hashMap = TimeUtils.getTime(fuli.getPublishedAt());
93 | fuli.setDesc(hashMap.get(TimeUtils.YEAR) + "-" + hashMap.get(TimeUtils.MONTH) + "-" + hashMap.get(TimeUtils.DAY) + "######" + reset.getDesc());
94 | fuli.setVideoUrl(reset.getUrl());
95 | } catch (ParseException e) {
96 |
97 | fuli.setDesc(fuli.getDesc() + "######" + reset.getDesc());
98 | }
99 |
100 | }
101 | return data1;
102 | }
103 |
104 | }
105 |
--------------------------------------------------------------------------------
/app/src/main/java/com/fall/gank/view/fragment/HomeFragment.java:
--------------------------------------------------------------------------------
1 | package com.fall.gank.view.fragment;
2 |
3 | import android.databinding.BaseObservable;
4 | import android.os.Bundle;
5 | import android.support.annotation.Nullable;
6 | import android.support.v7.widget.LinearLayoutManager;
7 | import android.view.LayoutInflater;
8 | import android.view.View;
9 | import android.view.ViewGroup;
10 |
11 | import com.fall.gank.R;
12 | import com.fall.gank.adapter.HomeAdapterDecorator;
13 | import com.fall.gank.core.BaseListFragment;
14 | import com.fall.gank.core.IPresenter;
15 | import com.fall.gank.databinding.FragmentHomeBinding;
16 | import com.fall.gank.presenter.HomeFragmentPresenter;
17 | import com.fall.gank.view.activity.WebViewActivity;
18 | import com.fall.gank.view.widget.RecyclerviewScrollHelper;
19 | import com.fall.gank.view.widget.SlowlyScrollLinearLayoutManager;
20 | import com.fall.gank.viewmodel.HomeItemViewModel;
21 | import com.fall.gank.viewmodel.HomeViewModel;
22 | import com.github.markzhai.recyclerview.SingleTypeAdapter;
23 |
24 | import java.util.ArrayList;
25 | import java.util.List;
26 |
27 | /**
28 | * Created by 康颢曦 on 2016/11/27.
29 | */
30 |
31 | public class HomeFragment extends BaseListFragment {
32 | private FragmentHomeBinding binding;
33 | private HomeFragmentPresenter homeFragmentPresenter;
34 | private HomeViewModel homeViewModel;
35 | private SlowlyScrollLinearLayoutManager mLinearLayoutManager;
36 | private SingleTypeAdapter mHomeItemViewModelSingleTypeAdapter;
37 | private RecyclerviewScrollHelper mRecyclerviewScrollHelper;
38 |
39 | @Override
40 | protected View initBinding(LayoutInflater inflater, ViewGroup container) {
41 | binding = FragmentHomeBinding.inflate(inflater, container, false);
42 | return binding.getRoot();
43 | }
44 |
45 | @Override
46 | public void initView(@Nullable Bundle savedInstanceState) {
47 | binding.swipeContainer.setColorSchemeColors(getResources().getColor(R.color.colorPrimary));
48 | binding.swipeContainer.setProgressBackgroundColorSchemeColor(getResources().getColor(R.color.swipeColor));
49 | mLinearLayoutManager.scrollToPosition(homeViewModel.lastPosition.get());
50 | mHomeItemViewModelSingleTypeAdapter.setDecorator(new HomeAdapterDecorator() {
51 | @Override
52 | public void onHomeClick(HomeItemViewModel homeItemViewModel) {
53 | WebViewActivity.newIntent(getContext(),homeItemViewModel.getVideoUrl());
54 | }
55 | });
56 | mRecyclerviewScrollHelper = new RecyclerviewScrollHelper(binding.homeRecyclerview);
57 |
58 |
59 | }
60 |
61 | @Override
62 | public void initListeners() {
63 | super.initListeners();
64 | mRecyclerviewScrollHelper.setOnScrollLastListener(() -> {
65 | if (homeViewModel.isDataEnable.get()) {
66 | homeFragmentPresenter.loadNext();
67 | }
68 | });
69 |
70 | binding.setRefreshListener(() -> homeFragmentPresenter.getData(1));
71 | mHomeItemViewModelSingleTypeAdapter.setPresenter((SingleTypeAdapter.Presenter) homeItemViewModel -> {
72 |
73 | });
74 |
75 | }
76 |
77 | @Override
78 | public void initOldData(@Nullable BaseObservable baseObservable) {
79 |
80 | homeViewModel = (HomeViewModel) baseObservable;
81 | homeFragmentPresenter = new HomeFragmentPresenter(homeViewModel);
82 | initList();
83 | iPresenterList.add(homeFragmentPresenter);
84 | }
85 |
86 | @Override
87 | public void initData() {
88 |
89 | homeViewModel = new HomeViewModel();
90 | homeFragmentPresenter = new HomeFragmentPresenter(homeViewModel);
91 | initList();
92 | iPresenterList.add(homeFragmentPresenter);
93 | }
94 |
95 |
96 | @Override
97 | public BaseObservable getViewModel() {
98 | return homeViewModel;
99 | }
100 | private void initList() {
101 | mHomeItemViewModelSingleTypeAdapter = new SingleTypeAdapter<>(getContext(), R.layout.view_home_item);
102 | if (homeViewModel.getIVMs().size() > 0) {
103 | mHomeItemViewModelSingleTypeAdapter.addAll(homeViewModel.getIVMs());
104 | }
105 | binding.setAdapter(mHomeItemViewModelSingleTypeAdapter);
106 | mLinearLayoutManager = new SlowlyScrollLinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false);
107 | binding.setLayoutmanager(mLinearLayoutManager);
108 | binding.setViewmodel(homeViewModel);
109 | }
110 |
111 | @Override
112 | public void onSaveInstanceState(Bundle outState) {
113 | if (binding.homeRecyclerview.getLayoutManager() != null) {
114 |
115 | homeViewModel.lastPosition.set(mLinearLayoutManager.findLastVisibleItemPosition());
116 | }
117 | super.onSaveInstanceState(outState);
118 | }
119 |
120 | @Override
121 | public SingleTypeAdapter getAdapter() {
122 | return mHomeItemViewModelSingleTypeAdapter;
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/app/src/main/java/com/fall/gank/entity/GankDateData.java:
--------------------------------------------------------------------------------
1 | package com.fall.gank.entity;
2 |
3 | import java.util.List;
4 |
5 | /**
6 | * Created by 康颢曦 on 2016/11/29.
7 | */
8 |
9 | public class GankDateData {
10 |
11 | /**
12 | * error : false
13 | * results : ["2016-11-29","2016-11-28","2016-11-25","2016-11-24","2016-11-23","2016-11-22","2016-11-21","2016-11-18","2016-11-17","2016-11-16","2016-11-15","2016-11-14","2016-11-11","2016-11-10","2016-11-09","2016-11-08","2016-11-07","2016-11-04","2016-11-03","2016-11-02","2016-11-01","2016-10-31","2016-10-28","2016-10-27","2016-10-26","2016-10-25","2016-10-24","2016-10-21","2016-10-20","2016-10-19","2016-10-18","2016-10-17","2016-10-14","2016-10-13","2016-10-12","2016-10-11","2016-10-10","2016-10-09","2016-10-08","2016-09-30","2016-09-29","2016-09-28","2016-09-27","2016-09-26","2016-09-23","2016-09-22","2016-09-21","2016-09-20","2016-09-19","2016-09-18","2016-09-14","2016-09-13","2016-09-12","2016-09-10","2016-09-09","2016-09-08","2016-09-07","2016-09-06","2016-09-05","2016-09-02","2016-09-01","2016-08-31","2016-08-30","2016-08-29","2016-08-26","2016-08-25","2016-08-24","2016-08-23","2016-08-22","2016-08-19","2016-08-18","2016-08-17","2016-08-16","2016-08-15","2016-08-12","2016-08-11","2016-08-10","2016-08-09","2016-08-08","2016-08-05","2016-08-03","2016-08-02","2016-08-01","2016-07-29","2016-07-28","2016-07-27","2016-07-26","2016-07-25","2016-07-22","2016-07-20","2016-07-19","2016-07-18","2016-07-15","2016-07-14","2016-07-13","2016-07-12","2016-07-11","2016-07-08","2016-07-07","2016-07-06","2016-07-05","2016-07-04","2016-07-01","2016-06-30","2016-06-29","2016-06-28","2016-06-27","2016-06-24","2016-06-23","2016-06-22","2016-06-21","2016-06-20","2016-06-17","2016-06-16","2016-06-15","2016-06-14","2016-06-13","2016-06-12","2016-06-08","2016-06-07","2016-06-06","2016-06-03","2016-06-02","2016-06-01","2016-05-31","2016-05-30","2016-05-27","2016-05-26","2016-05-25","2016-05-24","2016-05-23","2016-05-20","2016-05-19","2016-05-18","2016-05-17","2016-05-16","2016-05-13","2016-05-12","2016-05-11","2016-05-10","2016-05-09","2016-05-06","2016-05-05","2016-05-04","2016-05-03","2016-04-29","2016-04-28","2016-04-27","2016-04-26","2016-04-25","2016-04-22","2016-04-21","2016-04-20","2016-04-19","2016-04-18","2016-04-15","2016-04-14","2016-04-13","2016-04-12","2016-04-11","2016-04-08","2016-04-07","2016-04-06","2016-04-05","2016-04-01","2016-03-31","2016-03-30","2016-03-29","2016-03-28","2016-03-25","2016-03-24","2016-03-23","2016-03-22","2016-03-21","2016-03-18","2016-03-17","2016-03-16","2016-03-15","2016-03-14","2016-03-11","2016-03-10","2016-03-09","2016-03-08","2016-03-07","2016-03-04","2016-03-03","2016-03-02","2016-03-01","2016-02-29","2016-02-26","2016-02-25","2016-02-24","2016-02-23","2016-02-22","2016-02-19","2016-02-18","2016-02-17","2016-02-16","2016-02-15","2016-02-04","2016-02-03","2016-02-02","2016-02-01","2016-01-29","2016-01-28","2016-01-27","2016-01-26","2016-01-25","2016-01-22","2016-01-21","2016-01-20","2016-01-19","2016-01-18","2016-01-15","2016-01-14","2016-01-13","2016-01-12","2016-01-11","2016-01-08","2016-01-07","2016-01-06","2016-01-05","2016-01-04","2015-12-31","2015-12-30","2015-12-29","2015-12-28","2015-12-25","2015-12-24","2015-12-23","2015-12-22","2015-12-21","2015-12-18","2015-12-17","2015-12-16","2015-12-15","2015-12-14","2015-12-11","2015-12-10","2015-12-09","2015-12-08","2015-12-07","2015-12-04","2015-12-03","2015-12-02","2015-12-01","2015-11-30","2015-11-27","2015-11-26","2015-11-25","2015-11-24","2015-11-23","2015-11-20","2015-11-19","2015-11-18","2015-11-17","2015-11-16","2015-11-13","2015-11-12","2015-11-11","2015-11-10","2015-11-09","2015-11-06","2015-11-05","2015-11-04","2015-11-03","2015-11-02","2015-10-30","2015-10-29","2015-10-28","2015-10-27","2015-10-26","2015-10-23","2015-10-22","2015-10-21","2015-10-20","2015-10-19","2015-10-16","2015-10-15","2015-10-14","2015-10-13","2015-10-12","2015-10-10","2015-10-09","2015-10-08","2015-09-30","2015-09-29","2015-09-28","2015-09-25","2015-09-24","2015-09-23","2015-09-22","2015-09-21","2015-09-18","2015-09-17","2015-09-16","2015-09-15","2015-09-14","2015-09-11","2015-09-10","2015-09-09","2015-09-08","2015-09-07","2015-09-06","2015-09-01","2015-08-31","2015-08-28","2015-08-27","2015-08-26","2015-08-25","2015-08-24","2015-08-21","2015-08-20","2015-08-19","2015-08-18","2015-08-17","2015-08-14","2015-08-13","2015-08-12","2015-08-11","2015-08-10","2015-08-07","2015-08-06","2015-08-05","2015-08-03","2015-07-31","2015-07-30","2015-07-29","2015-07-28","2015-07-27","2015-07-24","2015-07-23","2015-07-22","2015-07-21","2015-07-20","2015-07-17","2015-07-16","2015-07-15","2015-07-14","2015-07-13","2015-07-10","2015-07-09","2015-07-08","2015-07-07","2015-07-03","2015-07-02","2015-07-01","2015-06-30","2015-06-29","2015-06-26","2015-06-19","2015-06-18","2015-06-17","2015-06-16","2015-06-15","2015-06-12","2015-06-11","2015-06-10","2015-06-09","2015-06-05","2015-06-04","2015-06-03","2015-06-02","2015-05-29","2015-05-28","2015-05-27","2015-05-26","2015-05-25","2015-05-22","2015-05-21","2015-05-20","2015-05-19","2015-05-18"]
14 | */
15 |
16 | private List results;
17 |
18 | public List getResults() {
19 | return results;
20 | }
21 |
22 | public void setResults(List results) {
23 | this.results = results;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/view_classification_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
11 |
12 |
15 |
16 |
19 |
20 |
21 |
28 |
29 |
39 |
40 |
45 |
46 |
52 |
53 |
59 |
60 |
65 |
66 |
74 |
75 |
81 |
82 |
90 |
91 |
92 |
98 |
99 |
106 |
107 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/app/src/main/java/com/fall/gank/view/fragment/ClassificationFragment.java:
--------------------------------------------------------------------------------
1 | package com.fall.gank.view.fragment;
2 |
3 | import android.databinding.BaseObservable;
4 | import android.os.Bundle;
5 | import android.support.annotation.Nullable;
6 | import android.support.v7.widget.LinearLayoutManager;
7 | import android.view.LayoutInflater;
8 | import android.view.View;
9 | import android.view.ViewGroup;
10 |
11 | import com.fall.gank.R;
12 | import com.fall.gank.Utils.ListLoadNextHelper;
13 | import com.fall.gank.adapter.ClassificationAdapterDecorator;
14 | import com.fall.gank.core.BaseListFragment;
15 | import com.fall.gank.core.IPresenter;
16 | import com.fall.gank.databinding.FragmentClassificationBinding;
17 | import com.fall.gank.presenter.ClassificationPresenter;
18 | import com.fall.gank.view.activity.WebViewActivity;
19 | import com.fall.gank.viewmodel.ClassificationViewModel;
20 | import com.fall.gank.viewmodel.ClassificationItemViewModel;
21 | import com.github.markzhai.recyclerview.SingleTypeAdapter;
22 |
23 | import java.util.ArrayList;
24 | import java.util.List;
25 |
26 | /**
27 | * Created by 康颢曦 on 2016/11/27.
28 | */
29 |
30 | public class ClassificationFragment extends BaseListFragment {
31 | private FragmentClassificationBinding binding;
32 | private ClassificationPresenter mClassificationPresenter;
33 | private ClassificationViewModel mClassificationViewModel;
34 | private SingleTypeAdapter mSingleTypeAdapter;
35 | private LinearLayoutManager mLinearLayoutManager;
36 | public static String KEY = "ClassificationFragment.key";
37 | private ListLoadNextHelper listLoadNextHelper;
38 | public static final String COLLECTION_TYPE = "collection";
39 |
40 | @Override
41 | protected View initBinding(LayoutInflater inflater, ViewGroup container) {
42 | binding = FragmentClassificationBinding.inflate(inflater, container, false);
43 | return binding.getRoot();
44 | }
45 |
46 | @Override
47 | public void initView(@Nullable Bundle savedInstanceState) {
48 | mSingleTypeAdapter.setDecorator(new ClassificationAdapterDecorator());
49 | mLinearLayoutManager.scrollToPositionWithOffset(mClassificationViewModel.getPosition(), mClassificationViewModel.getLastOffset());
50 | }
51 |
52 | @Override
53 | public void initListeners() {
54 | super.initListeners();
55 | binding.swipeContainer.setColorSchemeColors(getResources().getColor(R.color.colorPrimary));
56 | binding.swipeContainer.setProgressBackgroundColorSchemeColor(getResources().getColor(R.color.swipeColor));
57 | binding.setRefreshListener(() -> mClassificationPresenter.getData(1));
58 | mSingleTypeAdapter.setPresenter((SingleTypeAdapter.Presenter) classificationItemViewModel -> {
59 | WebViewActivity.newIntent(getContext(), classificationItemViewModel.url.get());
60 | });
61 |
62 | listLoadNextHelper = new ListLoadNextHelper(binding.classificationList);
63 | listLoadNextHelper.setListOffsetListener((lastOffset, position) -> {
64 | mClassificationViewModel.setLastOffset(lastOffset);
65 | mClassificationViewModel.setPosition(position);
66 | });
67 | listLoadNextHelper.setScrollLastListener(() -> {
68 |
69 | if (mClassificationViewModel.isDataEnable.get()) {
70 | mClassificationPresenter.loadNext();
71 | }
72 | });
73 |
74 | }
75 |
76 | @Override
77 | public SingleTypeAdapter getAdapter() {
78 | return mSingleTypeAdapter;
79 | }
80 |
81 | @Override
82 | public void initOldData(@Nullable BaseObservable baseObservable) {
83 | mClassificationViewModel = (ClassificationViewModel) baseObservable;
84 | initList();
85 | mClassificationPresenter = new ClassificationPresenter(mClassificationViewModel);
86 | mClassificationPresenter.setType(mClassificationViewModel.getType());
87 |
88 |
89 | iPresenterList.add(mClassificationPresenter);
90 | }
91 |
92 | @Override
93 | public void initData() {
94 | mClassificationViewModel = new ClassificationViewModel();
95 | mClassificationViewModel.setType(getArguments().getString(KEY));
96 |
97 | initList();
98 | mClassificationPresenter = new ClassificationPresenter(mClassificationViewModel);
99 | mClassificationPresenter.setType(mClassificationViewModel.getType());
100 |
101 | iPresenterList.add(mClassificationPresenter);
102 | }
103 |
104 |
105 | @Override
106 | public BaseObservable getViewModel() {
107 | return mClassificationViewModel;
108 | }
109 |
110 | private void initList() {
111 | mSingleTypeAdapter = new SingleTypeAdapter<>(getContext(), R.layout.view_classification_item);
112 | // mClassificationViewModel.getClassificationItemViewModelList().add(new ClassificationItemViewModel("a","a","a","a",false));
113 | if (mClassificationViewModel.getIVMs().size() > 0) {
114 | mSingleTypeAdapter.addAll(mClassificationViewModel.getIVMs());
115 | }
116 | binding.setAdapter(mSingleTypeAdapter);
117 | mLinearLayoutManager = new LinearLayoutManager(getContext());
118 | binding.setLayoutmanager(mLinearLayoutManager);
119 | binding.setViewmodel(mClassificationViewModel);
120 |
121 | }
122 |
123 | public static ClassificationFragment newInstance(String type) {
124 | Bundle bundle = new Bundle();
125 | bundle.putString(KEY, type);
126 | ClassificationFragment classificationFragment = new ClassificationFragment();
127 | classificationFragment.setArguments(bundle);
128 | return classificationFragment;
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/app/src/main/java/com/fall/gank/view/activity/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.fall.gank.view.activity;
2 |
3 | import android.databinding.BaseObservable;
4 | import android.databinding.DataBindingUtil;
5 | import android.os.Bundle;
6 | import android.support.annotation.Nullable;
7 | import android.support.v4.app.Fragment;
8 | import android.support.v4.view.ViewPager;
9 | import android.support.v7.widget.Toolbar;
10 | import android.view.Menu;
11 | import com.fall.gank.R;
12 | import com.fall.gank.Utils.MDStatusBarCompat;
13 | import com.fall.gank.adapter.ViewPagerAdapter;
14 | import com.fall.gank.core.BaseActivity;
15 | import com.fall.gank.databinding.ActivityMainBinding;
16 | import com.fall.gank.presenter.MainActivityPresenter;
17 | import com.fall.gank.presenter.TestPresenter;
18 | import com.fall.gank.presenter.factory.PresenterFactory;
19 | import com.fall.gank.view.fragment.ClassificationFragment;
20 | import com.fall.gank.view.fragment.FuliFragment;
21 | import com.fall.gank.view.fragment.HomeFragment;
22 | import com.fall.gank.view.fragment.SettingFragment;
23 | import com.fall.gank.viewmodel.MainViewModel;
24 |
25 | import java.util.ArrayList;
26 | import java.util.List;
27 |
28 |
29 | public class MainActivity extends BaseActivity {
30 | private ActivityMainBinding binding;
31 | private MainViewModel mViewModel;
32 | private MainActivityPresenter mMainActivityPresenter;
33 | private List fragmentList;
34 | private ViewPagerAdapter viewPagerAdapter;
35 | private TestPresenter mTestPresenter;
36 |
37 |
38 | @Override
39 | public void initBinding() {
40 | binding = DataBindingUtil.setContentView(MainActivity.this, R.layout.activity_main);
41 | }
42 |
43 | @Override
44 | public void initView(@Nullable Bundle savedInstanceState) {
45 | MDStatusBarCompat.setOrdinaryToolBar(this);
46 | fragmentList = new ArrayList<>();
47 | fragmentList.add(new HomeFragment());
48 | fragmentList.add(ClassificationFragment.newInstance("Android"));
49 | fragmentList.add(ClassificationFragment.newInstance("iOS"));
50 | fragmentList.add(ClassificationFragment.newInstance("前端"));
51 | fragmentList.add(new FuliFragment());
52 | fragmentList.add(new SettingFragment());
53 | viewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager());
54 | viewPagerAdapter.setFragmentList(fragmentList);
55 | binding.viewpager.setAdapter(viewPagerAdapter);
56 | binding.viewpager.setOffscreenPageLimit(6);
57 | }
58 |
59 | @Override
60 | protected void initToolbar(Bundle savedInstanceState) {
61 | Toolbar toolbar = binding.toolbar;
62 | setSupportActionBar(toolbar);
63 | }
64 |
65 | @Override
66 | public void initListeners() {
67 |
68 |
69 | binding.viewpager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
70 | @Override
71 | public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
72 |
73 | }
74 |
75 | @Override
76 | public void onPageSelected(int position) {
77 | mViewModel.setCurrentSelecte(position);
78 | }
79 |
80 | @Override
81 | public void onPageScrollStateChanged(int state) {
82 |
83 | }
84 | });
85 | binding.setViewClick(view -> {
86 | switch (view.getId()) {
87 | case R.id.image_home: {
88 | mViewModel.setCurrentSelecte(0);
89 | binding.viewpager.setCurrentItem(0, false);
90 | break;
91 | }
92 | case R.id.image_android: {
93 | mViewModel.setCurrentSelecte(1);
94 | binding.viewpager.setCurrentItem(1, false);
95 | break;
96 | }
97 | case R.id.image_ios: {
98 | mViewModel.setCurrentSelecte(2);
99 | binding.viewpager.setCurrentItem(2, false);
100 | break;
101 | }
102 | case R.id.image_web: {
103 | mViewModel.setCurrentSelecte(3);
104 | binding.viewpager.setCurrentItem(3, false);
105 | break;
106 | }
107 | case R.id.image_fuli: {
108 | mViewModel.setCurrentSelecte(4);
109 | binding.viewpager.setCurrentItem(4, false);
110 | break;
111 | }
112 | case R.id.image_setting: {
113 | mViewModel.setCurrentSelecte(5);
114 | binding.viewpager.setCurrentItem(5, false);
115 | break;
116 | }
117 | }
118 | });
119 | binding.toolbar.setOnMenuItemClickListener(item -> {
120 | switch (item.getItemId()) {
121 | case R.id.go_github:
122 | WebViewActivity.newIntent(MainActivity.this, "https://github.com/348476129/MVVM-framework");
123 | break;
124 | case R.id.test:
125 | mTestPresenter.onTextClick();
126 | break;
127 | }
128 | return true;
129 | });
130 | }
131 |
132 | @Override
133 | public void initOldData(BaseObservable baseObservable) {
134 | mViewModel = (MainViewModel) baseObservable;
135 | binding.setMainViewModel(mViewModel);
136 | mMainActivityPresenter = new MainActivityPresenter(mViewModel);
137 | mTestPresenter = new PresenterFactory().getTextPresenter(mViewModel);
138 | iPresenterList.add(mMainActivityPresenter);
139 | iPresenterList.add(mTestPresenter);
140 | }
141 |
142 | @Override
143 | public void initData() {
144 | mViewModel = new MainViewModel(0);
145 | binding.setMainViewModel(mViewModel);
146 | mMainActivityPresenter = new MainActivityPresenter(mViewModel);
147 | mTestPresenter = new PresenterFactory().getTextPresenter(mViewModel);
148 | iPresenterList.add(mMainActivityPresenter);
149 | iPresenterList.add(mTestPresenter);
150 |
151 | }
152 |
153 |
154 | @Override
155 | public BaseObservable getViewModel() {
156 | return mViewModel;
157 | }
158 |
159 | @Override
160 | public boolean onCreateOptionsMenu(Menu menu) {
161 | getMenuInflater().inflate(R.menu.menu_home, menu);
162 | return true;
163 | }
164 |
165 | }
166 |
--------------------------------------------------------------------------------
/app/src/main/java/com/fall/gank/Utils/MDStatusBarCompat.java:
--------------------------------------------------------------------------------
1 | package com.fall.gank.Utils;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.os.Build;
6 | import android.support.design.widget.AppBarLayout;
7 | import android.support.design.widget.CollapsingToolbarLayout;
8 | import android.support.design.widget.CoordinatorLayout;
9 | import android.support.v4.content.ContextCompat;
10 | import android.support.v4.view.ViewCompat;
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.fall.gank.R;
17 |
18 | /**
19 | * @author 幸运Science-陈土燊
20 | * @description
21 | * @email chentushen.science@gmail.com,274240671@qq.com
22 | * @data 2016/4/14
23 | */
24 | public class MDStatusBarCompat {
25 |
26 | private static View mStatusBarView;
27 |
28 | /**
29 | * 简单型状态栏(ToolBar)
30 | *
31 | * @param activity
32 | */
33 | public static void setOrdinaryToolBar(Activity activity) {
34 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
35 | activity.getWindow().setStatusBarColor(ContextCompat.getColor(activity, R.color.colorPrimaryDark));
36 | } else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
37 | setKKStatusBar(activity, R.color.colorPrimaryDark);
38 | }
39 | }
40 |
41 | /**
42 | * 图片全屏透明状态栏(图片位于状态栏下面)
43 | *
44 | * @param activity
45 | */
46 | public static void setImageTransparent(Activity activity) {
47 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
48 | activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
49 | }
50 | }
51 |
52 | /**
53 | * 图片全屏半透明状态栏(图片位于状态栏下面)
54 | *
55 | * @param activity
56 | */
57 | public static void setImageTranslucent(Activity activity) {
58 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
59 | activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
60 | activity.getWindow().setStatusBarColor(ContextCompat.getColor(activity, R.color.statusBar));
61 | } else {
62 | setKKStatusBar(activity, R.color.statusBar);
63 | }
64 | }
65 |
66 | /**
67 | * ToolBar+TabLayout状态栏(ToolBar可伸缩)
68 | *
69 | * @param activity
70 | */
71 | public static void setToolbarTabLayout(Activity activity) {
72 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
73 | activity.getWindow().setStatusBarColor(ContextCompat.getColor(activity, R.color.colorPrimaryDark));
74 | }
75 | }
76 |
77 | /**
78 | * DrawerLayout+ToolBar+TabLayout状态栏(ToolBar可伸缩)
79 | *
80 | * @param activity
81 | * @param coordinatorLayout
82 | */
83 | public static void setDrawerToolbarTabLayout(Activity activity, CoordinatorLayout coordinatorLayout) {
84 | if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
85 | ViewGroup contentLayout = (ViewGroup) activity.findViewById(android.R.id.content);
86 | contentLayout.getChildAt(0).setFitsSystemWindows(false);
87 | coordinatorLayout.setFitsSystemWindows(true);
88 | setKKStatusBar(activity, R.color.statusBar);
89 | }
90 | }
91 |
92 | /**
93 | * DrawerLayout+ToolBar型状态栏
94 | *
95 | * @param activity
96 | */
97 | public static void setDrawerToolbar(Activity activity) {
98 | if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
99 | ViewGroup contentLayout = (ViewGroup) activity.findViewById(android.R.id.content);
100 | contentLayout.getChildAt(0).setFitsSystemWindows(false);
101 | setKKStatusBar(activity, R.color.statusBar);
102 | }
103 | }
104 |
105 | /**
106 | * CollapsingToolbarLayout状态栏(可折叠图片)
107 | *
108 | * @param activity
109 | * @param coordinatorLayout
110 | * @param appBarLayout
111 | * @param imageView
112 | * @param toolbar
113 | */
114 | public static void setCollapsingToolbar(Activity activity, CoordinatorLayout coordinatorLayout,
115 | AppBarLayout appBarLayout, ImageView imageView, Toolbar toolbar) {
116 | if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
117 | coordinatorLayout.setFitsSystemWindows(false);
118 | appBarLayout.setFitsSystemWindows(false);
119 | imageView.setFitsSystemWindows(false);
120 | toolbar.setFitsSystemWindows(true);
121 | CollapsingToolbarLayout.LayoutParams lp = (CollapsingToolbarLayout.LayoutParams) toolbar.getLayoutParams();
122 | lp.height = (int) (getStatusBarHeight(activity) +
123 | activity.getResources().getDimension(R.dimen.abc_action_bar_default_height_material));
124 | toolbar.setLayoutParams(lp);
125 | setKKStatusBar(activity, R.color.statusBar);
126 | setCollapsingToolbarStatus(appBarLayout);
127 | }
128 | }
129 |
130 | /**
131 | * Android4.4上CollapsingToolbar折叠时statusBar显示和隐藏
132 | *
133 | * @param appBarLayout
134 | */
135 | private static void setCollapsingToolbarStatus(AppBarLayout appBarLayout) {
136 | ViewCompat.setAlpha(mStatusBarView, 1);
137 | appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
138 | @Override
139 | public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
140 | int maxScroll = appBarLayout.getTotalScrollRange();
141 | float percentage = (float) Math.abs(verticalOffset) / (float) maxScroll;
142 | ViewCompat.setAlpha(mStatusBarView, percentage);
143 | }
144 | });
145 | }
146 |
147 | private static void setKKStatusBar(Activity activity, int statusBarColor) {
148 | ViewGroup contentView = (ViewGroup) activity.findViewById(android.R.id.content);
149 | mStatusBarView = contentView.getChildAt(0);
150 | //改变颜色时避免重复添加statusBarView
151 | if (mStatusBarView != null && mStatusBarView.getMeasuredHeight() == getStatusBarHeight(activity)) {
152 | mStatusBarView.setBackgroundColor(ContextCompat.getColor(activity, statusBarColor));
153 | return;
154 | }
155 | mStatusBarView = new View(activity);
156 | ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
157 | getStatusBarHeight(activity));
158 | mStatusBarView.setBackgroundColor(ContextCompat.getColor(activity, statusBarColor));
159 | contentView.addView(mStatusBarView, lp);
160 | }
161 |
162 | private static int getStatusBarHeight(Context context) {
163 | int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
164 | return context.getResources().getDimensionPixelSize(resourceId);
165 | }
166 | }
167 |
--------------------------------------------------------------------------------
/app/src/main/java/com/fall/gank/view/activity/WebViewActivity.java:
--------------------------------------------------------------------------------
1 | package com.fall.gank.view.activity;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.databinding.BaseObservable;
6 | import android.databinding.DataBindingUtil;
7 | import android.net.Uri;
8 | import android.os.Bundle;
9 | import android.support.annotation.Nullable;
10 | import android.support.design.widget.Snackbar;
11 | import android.support.v7.widget.Toolbar;
12 | import android.view.KeyEvent;
13 | import android.view.Menu;
14 | import android.view.View;
15 | import android.webkit.WebChromeClient;
16 | import android.webkit.WebSettings;
17 | import android.webkit.WebView;
18 | import android.webkit.WebViewClient;
19 |
20 | import com.fall.gank.R;
21 | import com.fall.gank.Utils.MDStatusBarCompat;
22 | import com.fall.gank.Utils.Utils;
23 | import com.fall.gank.core.BaseActivity;
24 | import com.fall.gank.core.IPresenter;
25 | import com.fall.gank.databinding.WebviewActivityBinding;
26 | import com.fall.gank.presenter.WebViewActivityPresenter;
27 | import com.fall.gank.viewmodel.WebViewModel;
28 |
29 | import java.util.ArrayList;
30 | import java.util.List;
31 |
32 | /**
33 | * Created by qqq34 on 2016/12/8.
34 | */
35 |
36 | public class WebViewActivity extends BaseActivity {
37 |
38 | private static final String EXTRA_URL = "WebViewActivity.url";
39 |
40 | private WebviewActivityBinding mWebviewActivityBinding;
41 | private WebViewModel mModel;
42 | private WebViewActivityPresenter mPresenter;
43 |
44 |
45 | public static void newIntent(Context context, String url) {
46 | Intent intent = new Intent(context, WebViewActivity.class);
47 | intent.putExtra(EXTRA_URL, url);
48 | context.startActivity(intent);
49 | }
50 |
51 | @Override
52 | protected void initBinding() {
53 | mWebviewActivityBinding = DataBindingUtil.setContentView(WebViewActivity.this, R.layout.webview_activity);
54 | }
55 |
56 | @Override
57 | protected void initToolbar(Bundle savedInstanceState) {
58 | Toolbar toolbar = mWebviewActivityBinding.toolbar;
59 | toolbar.setTitle(getString(R.string.app_name));
60 | setSupportActionBar(toolbar);
61 | getSupportActionBar().setDisplayHomeAsUpEnabled(true);
62 | }
63 |
64 | @Override
65 | public void initView(@Nullable Bundle savedInstanceState) {
66 | MDStatusBarCompat.setOrdinaryToolBar(this);
67 | WebView webView = mWebviewActivityBinding.webview;
68 | WebSettings settings = webView.getSettings();
69 | settings.setJavaScriptEnabled(true);
70 | settings.setLoadWithOverviewMode(true);
71 | settings.setAppCacheEnabled(true);
72 | settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
73 | settings.setSupportZoom(true);
74 | webView.setWebChromeClient(new ChromeClient());
75 | webView.setWebViewClient(new WebClient());
76 | mModel.webViewUrl.set(getIntent().getStringExtra(EXTRA_URL));
77 | }
78 |
79 | @Override
80 | public void initListeners() {
81 | mWebviewActivityBinding.toolbar.setNavigationOnClickListener(view -> {
82 | finish();
83 | });
84 | mWebviewActivityBinding.toolbar.setOnMenuItemClickListener(item -> {
85 | int id = item.getItemId();
86 | switch (id) {
87 | case R.id.refresh:
88 | mWebviewActivityBinding.webview.reload();
89 | return true;
90 | case R.id.copy:
91 | Utils.copyToClipBoard(this, mWebviewActivityBinding.webview.getUrl());
92 | Snackbar.make(mWebviewActivityBinding.webview, "复制成功", Snackbar.LENGTH_SHORT).show();
93 |
94 | return true;
95 | case R.id.open:
96 | Intent intent = new Intent();
97 | intent.setAction(Intent.ACTION_VIEW);
98 | Uri uri = Uri.parse(mWebviewActivityBinding.webview.getUrl());
99 | intent.setData(uri);
100 | if (intent.resolveActivity(getPackageManager()) != null) {
101 | startActivity(intent);
102 | } else {
103 | Snackbar.make(mWebviewActivityBinding.webview, "打开失败:没有安装能打开此链接的app", Snackbar.LENGTH_SHORT).show();
104 | }
105 | return true;
106 | }
107 | return super.onOptionsItemSelected(item);
108 | });
109 | }
110 |
111 | @Override
112 | public void initOldData(@Nullable BaseObservable baseObservable) {
113 | mModel = (WebViewModel) baseObservable;
114 |
115 | mWebviewActivityBinding.setWebViewModel(mModel);
116 | mPresenter = new WebViewActivityPresenter(mModel);
117 | iPresenterList.add(mPresenter);
118 | }
119 |
120 | @Override
121 | public void initData() {
122 | mModel = new WebViewModel();
123 | mWebviewActivityBinding.setWebViewModel(mModel);
124 | mPresenter = new WebViewActivityPresenter(mModel);
125 | iPresenterList.add(mPresenter);
126 | }
127 |
128 |
129 |
130 |
131 | @Override
132 | public BaseObservable getViewModel() {
133 | return mModel;
134 | }
135 |
136 | private class ChromeClient extends WebChromeClient {
137 |
138 | @Override
139 | public void onProgressChanged(WebView view, int newProgress) {
140 | super.onProgressChanged(view, newProgress);
141 | mModel.progress.set(newProgress);
142 | }
143 |
144 |
145 | @Override
146 | public void onReceivedTitle(WebView view, String title) {
147 | super.onReceivedTitle(view, title);
148 | mWebviewActivityBinding.toolbar.setTitle(title);
149 | }
150 | }
151 |
152 | @Override
153 | public boolean onKeyDown(int keyCode, KeyEvent event) {
154 | if (event.getAction() == KeyEvent.ACTION_DOWN) {
155 | switch (keyCode) {
156 | case KeyEvent.KEYCODE_BACK:
157 | if (mWebviewActivityBinding.webview.canGoBack()) {
158 | mWebviewActivityBinding.webview.goBack();
159 | } else {
160 | finish();
161 | }
162 | return true;
163 | }
164 | }
165 | return super.onKeyDown(keyCode, event);
166 | }
167 |
168 | private class WebClient extends WebViewClient {
169 |
170 | public boolean shouldOverrideUrlLoading(WebView view, String url) {
171 | if (url != null) view.loadUrl(url);
172 | return true;
173 | }
174 | }
175 |
176 | @Override
177 | protected void onDestroy() {
178 | super.onDestroy();
179 | mWebviewActivityBinding.webview.destroy();
180 | }
181 |
182 |
183 | @Override
184 | protected void onPause() {
185 | mWebviewActivityBinding.webview.onPause();
186 | super.onPause();
187 | }
188 |
189 |
190 | @Override
191 | protected void onResume() {
192 | super.onResume();
193 | mWebviewActivityBinding.webview.onResume();
194 | }
195 |
196 | @Override
197 | public boolean onCreateOptionsMenu(Menu menu) {
198 | getMenuInflater().inflate(R.menu.menu_webview, menu);
199 | return true;
200 | }
201 | }
202 |
--------------------------------------------------------------------------------