├── .gitignore
├── LICENSE.txt
├── README.md
├── app
├── .gitignore
├── build.gradle
├── libs
│ └── tencentX5WebView.jar
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── example
│ │ └── cnsunrun
│ │ └── debugdemo
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── cnsunrun
│ │ │ └── debugdemo
│ │ │ ├── DebugDemoApp.java
│ │ │ ├── app
│ │ │ ├── AppConstant.java
│ │ │ ├── ApplicationComponent.java
│ │ │ └── ApplicationModule.java
│ │ │ ├── mvp
│ │ │ ├── base
│ │ │ │ ├── IBasePresenter.java
│ │ │ │ └── IBaseView.java
│ │ │ ├── contract
│ │ │ │ ├── CopyListContract.java
│ │ │ │ └── QuanziListContract.java
│ │ │ ├── model
│ │ │ │ ├── bean
│ │ │ │ │ ├── CopyDetailsInfo.java
│ │ │ │ │ ├── CopyInfo.java
│ │ │ │ │ ├── QuanziDetailsInfo.java
│ │ │ │ │ ├── QuanziInfo.java
│ │ │ │ │ └── base
│ │ │ │ │ │ └── BaseResponseInfo.java
│ │ │ │ └── network
│ │ │ │ │ ├── RetrofitHelper.java
│ │ │ │ │ └── api
│ │ │ │ │ ├── ICopyService.java
│ │ │ │ │ └── IQuanziService.java
│ │ │ ├── presenter
│ │ │ │ ├── CopyListPresenter.java
│ │ │ │ ├── QuanziListPresenter.java
│ │ │ │ └── base
│ │ │ │ │ └── PresenterComponent.java
│ │ │ └── ui
│ │ │ │ ├── activity
│ │ │ │ ├── CopyDetailsActivity.java
│ │ │ │ ├── ImageDetailsActivity.java
│ │ │ │ ├── MainActivity.java
│ │ │ │ ├── QuanziDetailsActivity.java
│ │ │ │ ├── component
│ │ │ │ │ ├── CopyListComponent.java
│ │ │ │ │ └── QuanziListComponent.java
│ │ │ │ └── module
│ │ │ │ │ ├── CopyListModule.java
│ │ │ │ │ └── QuanziListModule.java
│ │ │ │ ├── adapter
│ │ │ │ ├── CommentAdapter.java
│ │ │ │ ├── CopyAdapter.java
│ │ │ │ ├── CopyDetailsAdapter.java
│ │ │ │ ├── QuanziAdapter.java
│ │ │ │ └── base
│ │ │ │ │ ├── AbsRecyclerViewAdapter.java
│ │ │ │ │ ├── EndlessRecyclerOnScrollListener.java
│ │ │ │ │ └── HeaderViewRecyclerAdapter.java
│ │ │ │ └── fragment
│ │ │ │ ├── CommunityFragment.java
│ │ │ │ ├── CopyListFragment.java
│ │ │ │ ├── ImageDetailsFragment.java
│ │ │ │ ├── MineFragment.java
│ │ │ │ └── QuanziListFragment.java
│ │ │ ├── utils
│ │ │ ├── ActivityScoped.java
│ │ │ ├── ActivityUtils.java
│ │ │ ├── DisplayUtil.java
│ │ │ └── ImgUrlUtil.java
│ │ │ └── widget
│ │ │ ├── CircleImageView.java
│ │ │ ├── CircleProgressView.java
│ │ │ └── MomentPicView.java
│ └── res
│ │ ├── drawable-hdpi
│ │ ├── ic_logo.png
│ │ ├── ic_tab_community.png
│ │ ├── ic_tab_home.png
│ │ ├── ic_tab_mine.png
│ │ └── ic_tab_quanzi.png
│ │ ├── drawable-xhdpi
│ │ └── ic_placeholder.png
│ │ ├── drawable-xxhdpi
│ │ ├── bg_announcement.9.png
│ │ ├── ic_arrow_right_gray.png
│ │ ├── ic_event_album.png
│ │ ├── ic_event_bbs.png
│ │ ├── ic_event_tag.png
│ │ ├── ic_event_time.png
│ │ ├── ic_event_topic.png
│ │ ├── ic_event_user.png
│ │ ├── ic_hot_topic_detail.png
│ │ ├── ic_no_module.png
│ │ ├── ic_original_topic_detail.png
│ │ ├── ic_tag.png
│ │ ├── ic_uncomment_chart.png
│ │ ├── ic_unfavour_heart.png
│ │ └── ic_water_comment.png
│ │ ├── drawable
│ │ ├── bg_message_board_in_online_event.xml
│ │ ├── bg_tag_secondary.xml
│ │ ├── bg_topic_tag.xml
│ │ ├── bg_type.xml
│ │ └── divider_gray.xml
│ │ ├── layout
│ │ ├── activity_copy_details.xml
│ │ ├── activity_image_details.xml
│ │ ├── activity_main.xml
│ │ ├── activity_quanzi_details.xml
│ │ ├── fragment_community.xml
│ │ ├── fragment_copy_list.xml
│ │ ├── fragment_image_details.xml
│ │ ├── fragment_mine.xml
│ │ ├── fragment_quanzi_list.xml
│ │ ├── item_comment.xml
│ │ ├── item_copy.xml
│ │ ├── item_copy_details.xml
│ │ ├── item_quanzi.xml
│ │ ├── layout_head_copy_details.xml
│ │ ├── layout_item_tag.xml
│ │ ├── layout_load_more.xml
│ │ ├── layout_loading.xml
│ │ └── layout_toolbar.xml
│ │ ├── mipmap-hdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-mdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxxhdpi
│ │ └── ic_launcher.png
│ │ └── values
│ │ ├── attrs.xml
│ │ ├── colors.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── example
│ └── cnsunrun
│ └── debugdemo
│ └── ExampleUnitTest.java
├── art
├── 01.png
├── 02.png
└── 03.png
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 | .externalNativeBuild
10 |
11 | .idea/compiler.xml
12 |
13 | .idea/copyright/profiles_settings.xml
14 |
15 | .idea/dictionaries/hcc.xml
16 |
17 | .idea/encodings.xml
18 |
19 | .idea/gradle.xml
20 |
21 | .idea/misc.xml
22 |
23 | .idea/modules.xml
24 |
25 | .idea/runConfigurations.xml
26 | .idea/vcs.xml
27 | .idea/workspace.xml___jb_tmp___
28 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
2 |
3 | Everyone is permitted to copy and distribute verbatim or modified
4 | copies of this license document, and changing it is allowed as long
5 | as the name is changed.
6 |
7 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
8 |
9 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
10 |
11 | 0. You just DO WHAT THE FUCK YOU WANT TO.
12 |
13 |
14 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Acg
2 |
3 | A acg community of app
4 |
5 | ## Screenshots
6 |
7 |
8 |
9 | ## instructions
10 |
11 | This app is fetching JUJU network apis to implement a acg community projects, like a friend to a star support, thank you.
12 |
13 | ## About me
14 |
15 | [](http://weibo.com/3223089177/profile?topnav=1&wvr=6&is_all=1)
16 |
17 | An android developer in Wuhan.
18 |
19 | If you want to make friends with me, You can focus on my weibo.
20 |
21 |
22 | ## License
23 |
24 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
25 |
26 | Everyone is permitted to copy and distribute verbatim or modified
27 | copies of this license document, and changing it is allowed as long
28 | as the name is changed.
29 |
30 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
31 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
32 |
33 | You just DO WHAT THE FUCK YOU WANT TO.
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | mavenCentral()
4 | maven { url "https://jitpack.io" }
5 | }
6 | dependencies {
7 | classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
8 | classpath 'me.tatarka:gradle-retrolambda:3.2.5'
9 | }
10 | }
11 | apply plugin: 'com.android.application'
12 | apply plugin: 'com.neenbedankt.android-apt'
13 | apply plugin: 'me.tatarka.retrolambda'
14 |
15 | android {
16 | compileSdkVersion 25
17 | buildToolsVersion "25.0.2"
18 | defaultConfig {
19 | applicationId "com.example.cnsunrun.debugdemo"
20 | minSdkVersion 19
21 | targetSdkVersion 25
22 | versionCode 1
23 | versionName "1.0"
24 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
25 | }
26 | buildTypes {
27 | release {
28 | minifyEnabled false
29 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
30 | }
31 | }
32 |
33 | compileOptions {
34 | sourceCompatibility JavaVersion.VERSION_1_8
35 | targetCompatibility JavaVersion.VERSION_1_8
36 | }
37 | }
38 |
39 | dependencies {
40 | compile fileTree(include: ['*.jar'], dir: 'libs')
41 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
42 | exclude group: 'com.android.support', module: 'support-annotations'
43 | })
44 | testCompile 'junit:junit:4.12'
45 | //Android Libs
46 | compile 'com.android.support:appcompat-v7:25.3.1'
47 | compile 'com.android.support:cardview-v7:25.3.1'
48 | compile 'com.android.support:design:25.3.1'
49 | //Retrofit2
50 | compile 'com.squareup.retrofit2:retrofit:2.2.0'
51 | compile 'com.squareup.retrofit2:converter-gson:2.0.1'
52 | compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
53 | //OkHttp3
54 | compile 'com.squareup.okhttp3:okhttp:3.6.0'
55 | compile 'com.squareup.okhttp3:logging-interceptor:3.6.0'
56 | //RxJava2
57 | compile 'io.reactivex.rxjava2:rxjava:2.0.2'
58 | compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
59 | //黄油刀注解7.x
60 | compile 'com.jakewharton:butterknife:7.0.1'
61 | //Glide 图片加载库
62 | compile 'com.github.bumptech.glide:glide:3.7.0'
63 | compile 'com.github.bumptech.glide:okhttp3-integration:1.4.0@aar'
64 | //stream流式操作辅助库
65 | compile 'com.annimon:stream:1.1.4'
66 | //BottomNavigationView
67 | compile 'com.aurelhubert:ahbottomnavigation:2.0.1'
68 | //RecyclerView Load More
69 | compile 'com.github.nukc:loadmorewrapper:1.6'
70 | //标签布局
71 | compile 'com.zhy:flowlayout-lib:1.0.3'
72 | //PhotoView
73 | compile 'com.github.chrisbanes:PhotoView:1.2.6'
74 | //Dagger2 依赖注入库
75 | apt 'com.google.dagger:dagger-compiler:2.2'
76 | compile 'com.google.dagger:dagger:2.2'
77 | provided 'javax.annotation:jsr250-api:1.0'
78 | }
79 |
--------------------------------------------------------------------------------
/app/libs/tencentX5WebView.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HotBitmapGG/Acg/25414834e776fb555d2b73e4dc39e9d00472c711/app/libs/tencentX5WebView.jar
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in D:\Android\Sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
19 | # Uncomment this to preserve the line number information for
20 | # debugging stack traces.
21 | #-keepattributes SourceFile,LineNumberTable
22 |
23 | # If you keep the line number information, uncomment this to
24 | # hide the original source file name.
25 | #-renamesourcefileattribute SourceFile
26 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/example/cnsunrun/debugdemo/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.example.cnsunrun.debugdemo;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumentation test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.example.cnsunrun.debugdemo", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
27 |
28 |
31 |
32 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/cnsunrun/debugdemo/DebugDemoApp.java:
--------------------------------------------------------------------------------
1 | package com.example.cnsunrun.debugdemo;
2 |
3 | import android.app.Application;
4 | import android.os.StrictMode;
5 |
6 | import com.example.cnsunrun.debugdemo.app.ApplicationComponent;
7 | import com.example.cnsunrun.debugdemo.app.ApplicationModule;
8 | import com.example.cnsunrun.debugdemo.app.DaggerApplicationComponent;
9 |
10 | /**
11 | * Created by cnsunrun on 2017/3/15.
12 | */
13 |
14 | public class DebugDemoApp extends Application {
15 |
16 | private static DebugDemoApp mAppContext;
17 |
18 | private ApplicationComponent applicationComponent;
19 |
20 | @Override
21 | public void onCreate() {
22 | super.onCreate();
23 | mAppContext = this;
24 | init();
25 | }
26 |
27 | private void init() {
28 | if (BuildConfig.DEBUG) {
29 | StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog().build());
30 | StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll().penaltyLog().build());
31 | }
32 |
33 | applicationComponent = DaggerApplicationComponent.builder()
34 | .applicationModule(new ApplicationModule(this))
35 | .build();
36 | }
37 |
38 | public static DebugDemoApp getAppContext() {
39 | return mAppContext;
40 | }
41 |
42 | public ApplicationComponent getApplicationComponent() {
43 | return applicationComponent;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/cnsunrun/debugdemo/app/AppConstant.java:
--------------------------------------------------------------------------------
1 | package com.example.cnsunrun.debugdemo.app;
2 |
3 | /**
4 | * Created by cnsunrun on 2017/4/18.
5 | *
6 | * 13489841 13489375
7 | */
8 |
9 | public class AppConstant {
10 |
11 | public static final String SUCCESS_CODE = "10000";
12 | }
13 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/cnsunrun/debugdemo/app/ApplicationComponent.java:
--------------------------------------------------------------------------------
1 | package com.example.cnsunrun.debugdemo.app;
2 |
3 | import android.content.Context;
4 |
5 | import com.example.cnsunrun.debugdemo.DebugDemoApp;
6 |
7 | import javax.inject.Singleton;
8 |
9 | import dagger.Component;
10 |
11 |
12 | @Singleton
13 | @Component(modules = {ApplicationModule.class})
14 | public interface ApplicationComponent {
15 |
16 | DebugDemoApp getApplication();
17 |
18 | Context getContext();
19 | }
20 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/cnsunrun/debugdemo/app/ApplicationModule.java:
--------------------------------------------------------------------------------
1 | package com.example.cnsunrun.debugdemo.app;
2 |
3 | import android.content.Context;
4 |
5 | import com.example.cnsunrun.debugdemo.DebugDemoApp;
6 |
7 | import javax.inject.Singleton;
8 |
9 | import dagger.Module;
10 | import dagger.Provides;
11 |
12 |
13 | @Module
14 | public class ApplicationModule {
15 |
16 | private Context context;
17 |
18 | public ApplicationModule(Context context) {
19 |
20 | this.context = context;
21 | }
22 |
23 | @Provides
24 | @Singleton
25 | DebugDemoApp provideApplication() {
26 |
27 | return (DebugDemoApp) context.getApplicationContext();
28 | }
29 |
30 | @Provides
31 | @Singleton
32 | Context provideContext() {
33 |
34 | return context;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/cnsunrun/debugdemo/mvp/base/IBasePresenter.java:
--------------------------------------------------------------------------------
1 | package com.example.cnsunrun.debugdemo.mvp.base;
2 |
3 | /**
4 | * presenter interface,所有Presenter必须实现此接口
5 | */
6 | public interface IBasePresenter {
7 |
8 | void subscribe();
9 |
10 | void unSubscribe();
11 | }
12 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/cnsunrun/debugdemo/mvp/base/IBaseView.java:
--------------------------------------------------------------------------------
1 | package com.example.cnsunrun.debugdemo.mvp.base;
2 |
3 | /**
4 | * view interface,所有View(此项目中的View主要是Fragment和自定义的ViewGroup)必须实现此接口
5 | */
6 |
7 | public interface IBaseView {
8 | void setPresenter(T presenter);
9 | }
10 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/cnsunrun/debugdemo/mvp/contract/CopyListContract.java:
--------------------------------------------------------------------------------
1 | package com.example.cnsunrun.debugdemo.mvp.contract;
2 |
3 | import com.example.cnsunrun.debugdemo.mvp.base.IBasePresenter;
4 | import com.example.cnsunrun.debugdemo.mvp.base.IBaseView;
5 | import com.example.cnsunrun.debugdemo.mvp.model.bean.CopyInfo;
6 |
7 | import java.util.List;
8 |
9 | /**
10 | * Created by cnsunrun on 2017/4/19.
11 | */
12 |
13 | public interface CopyListContract {
14 |
15 | interface View extends IBaseView {
16 | void displayData(List copyInfos);
17 | }
18 |
19 | interface Presenter extends IBasePresenter {
20 | void loadData();
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/cnsunrun/debugdemo/mvp/contract/QuanziListContract.java:
--------------------------------------------------------------------------------
1 | package com.example.cnsunrun.debugdemo.mvp.contract;
2 |
3 | import com.example.cnsunrun.debugdemo.mvp.base.IBasePresenter;
4 | import com.example.cnsunrun.debugdemo.mvp.base.IBaseView;
5 | import com.example.cnsunrun.debugdemo.mvp.model.bean.QuanziInfo;
6 |
7 | import java.util.List;
8 |
9 | /**
10 | * Created by cnsunrun on 2017/3/17.
11 | */
12 |
13 | public interface QuanziListContract {
14 |
15 | interface View extends IBaseView {
16 | void displayData(List quanziInfos);
17 | }
18 |
19 | interface Presenter extends IBasePresenter {
20 | void loadData();
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/cnsunrun/debugdemo/mvp/model/bean/CopyInfo.java:
--------------------------------------------------------------------------------
1 | package com.example.cnsunrun.debugdemo.mvp.model.bean;
2 |
3 | import com.google.gson.annotations.SerializedName;
4 |
5 | import java.util.List;
6 |
7 | /**
8 | * Created by cnsunrun on 2017/4/19.
9 | *
10 | * 副本列表模型类
11 | */
12 |
13 | public class CopyInfo {
14 |
15 |
16 | @SerializedName("activityo.hasnotice")
17 | private String activityoHasnotice;
18 | @SerializedName("activityo.list")
19 | private List activityoListBeans;
20 |
21 | public String getActivityoHasnotice() {
22 | return activityoHasnotice;
23 | }
24 |
25 | public void setActivityoHasnotice(String activityoHasnotice) {
26 | this.activityoHasnotice = activityoHasnotice;
27 | }
28 |
29 | public List getActivityoListBeans() {
30 | return activityoListBeans;
31 | }
32 |
33 | public void setActivityoListBeans(List activityoListBeans) {
34 | this.activityoListBeans = activityoListBeans;
35 | }
36 |
37 | public static class ActivityoListBean {
38 | /**
39 | * activityid : 1002549
40 | * picture : http://juheadpic.juju.la/group/cc10a9ad5460f3715d6baaf76bd91065.png
41 | * name : 刀剑乱舞国服
42 | * user_name : JUJU审核菌
43 | * timestr : null
44 | * form : 其他
45 | * counter : 132
46 | * iscreate : -1
47 | */
48 |
49 | private String activityid;
50 | private String picture;
51 | private String name;
52 | private String user_name;
53 | private Object timestr;
54 | private String form;
55 | private String counter;
56 | private int iscreate;
57 |
58 | public String getActivityid() {
59 | return activityid;
60 | }
61 |
62 | public void setActivityid(String activityid) {
63 | this.activityid = activityid;
64 | }
65 |
66 | public String getPicture() {
67 | return picture;
68 | }
69 |
70 | public void setPicture(String picture) {
71 | this.picture = picture;
72 | }
73 |
74 | public String getName() {
75 | return name;
76 | }
77 |
78 | public void setName(String name) {
79 | this.name = name;
80 | }
81 |
82 | public String getUser_name() {
83 | return user_name;
84 | }
85 |
86 | public void setUser_name(String user_name) {
87 | this.user_name = user_name;
88 | }
89 |
90 | public Object getTimestr() {
91 | return timestr;
92 | }
93 |
94 | public void setTimestr(Object timestr) {
95 | this.timestr = timestr;
96 | }
97 |
98 | public String getForm() {
99 | return form;
100 | }
101 |
102 | public void setForm(String form) {
103 | this.form = form;
104 | }
105 |
106 | public String getCounter() {
107 | return counter;
108 | }
109 |
110 | public void setCounter(String counter) {
111 | this.counter = counter;
112 | }
113 |
114 | public int getIscreate() {
115 | return iscreate;
116 | }
117 |
118 | public void setIscreate(int iscreate) {
119 | this.iscreate = iscreate;
120 | }
121 |
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/cnsunrun/debugdemo/mvp/model/bean/base/BaseResponseInfo.java:
--------------------------------------------------------------------------------
1 | package com.example.cnsunrun.debugdemo.mvp.model.bean.base;
2 |
3 | import com.google.gson.annotations.SerializedName;
4 |
5 | /**
6 | * Created by cnsunrun on 2017/3/15.
7 | */
8 |
9 | public class BaseResponseInfo {
10 |
11 | @SerializedName("code")
12 | public String code;
13 | @SerializedName("message")
14 | public String message;
15 | @SerializedName("result")
16 | public T result;
17 | @SerializedName("sid")
18 | public String sid;
19 |
20 | public String getCode() {
21 | return code;
22 | }
23 |
24 | public String getMessage() {
25 | return message;
26 | }
27 |
28 |
29 | public T getBaseResult() {
30 | return result;
31 | }
32 |
33 |
34 | public String getSid() {
35 | return sid;
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/cnsunrun/debugdemo/mvp/model/network/RetrofitHelper.java:
--------------------------------------------------------------------------------
1 | package com.example.cnsunrun.debugdemo.mvp.model.network;
2 |
3 | import com.example.cnsunrun.debugdemo.DebugDemoApp;
4 | import com.example.cnsunrun.debugdemo.mvp.model.network.api.ICopyService;
5 | import com.example.cnsunrun.debugdemo.mvp.model.network.api.IQuanziService;
6 | import com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
7 |
8 | import java.io.File;
9 | import java.util.concurrent.TimeUnit;
10 |
11 | import okhttp3.Cache;
12 | import okhttp3.OkHttpClient;
13 | import okhttp3.logging.HttpLoggingInterceptor;
14 | import retrofit2.Retrofit;
15 | import retrofit2.converter.gson.GsonConverterFactory;
16 |
17 | /**
18 | * Created by cnsunrun on 2017/3/11.
19 | */
20 |
21 | public class RetrofitHelper {
22 |
23 | private static OkHttpClient mOkHttpClient;
24 |
25 | public static final String BASE_URL = "http://server.juju.la/";
26 |
27 | static {
28 | initOkHttpClient();
29 | }
30 |
31 | /**
32 | * 创建圈子网络请求
33 | *
34 | * @return
35 | */
36 | public static IQuanziService createQuanziService() {
37 | Retrofit retrofit = new Retrofit.Builder()
38 | .baseUrl(BASE_URL)
39 | .client(mOkHttpClient)
40 | .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
41 | .addConverterFactory(GsonConverterFactory.create())
42 | .build();
43 | return retrofit.create(IQuanziService.class);
44 | }
45 |
46 |
47 | /**
48 | * 创建副本网络请求
49 | *
50 | * @return
51 | */
52 | public static ICopyService createCopyService() {
53 | Retrofit retrofit = new Retrofit.Builder()
54 | .baseUrl(BASE_URL)
55 | .client(mOkHttpClient)
56 | .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
57 | .addConverterFactory(GsonConverterFactory.create())
58 | .build();
59 | return retrofit.create(ICopyService.class);
60 | }
61 |
62 |
63 | /**
64 | * 初始化OKHttpClient
65 | */
66 | private static void initOkHttpClient() {
67 |
68 | HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
69 | interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
70 | if (mOkHttpClient == null) {
71 | synchronized (RetrofitHelper.class) {
72 | if (mOkHttpClient == null) {
73 | //设置Http缓存
74 | Cache cache = new Cache(
75 | new File(DebugDemoApp.getAppContext().getCacheDir(), "HttpCache"),
76 | 1024 * 1024 * 100);
77 |
78 | mOkHttpClient = new OkHttpClient.Builder()
79 | .cache(cache)
80 | // .addNetworkInterceptor(new CacheInterceptor())
81 | .addInterceptor(interceptor)
82 | .retryOnConnectionFailure(true)
83 | .connectTimeout(15, TimeUnit.SECONDS)
84 | .build();
85 | }
86 | }
87 | }
88 | }
89 |
90 |
91 | // /**
92 | // * 添加Okhttp缓存拦截器
93 | // */
94 | // private static class CacheInterceptor implements Interceptor {
95 | //
96 | // @Override
97 | // public Response intercept(Chain chain) throws IOException {
98 | //
99 | // // 有网络时 设置缓存超时时间1个小时
100 | // int maxAge = 60 * 60;
101 | // // 无网络时,设置超时为1天
102 | // int maxStale = 60 * 60 * 24;
103 | // Request request = chain.request();
104 | // if (NetWorkUtil.isNetworkConnected()) {
105 | // //有网络时只从网络获取
106 | // request = request.newBuilder()
107 | // .cacheControl(CacheControl.FORCE_NETWORK)
108 | // .build();
109 | // } else {
110 | // //无网络时只从缓存中读取
111 | // request = request.newBuilder()
112 | // .cacheControl(CacheControl.FORCE_CACHE)
113 | // .build();
114 | // }
115 | // Response response = chain.proceed(request);
116 | // if (NetWorkUtil.isNetworkConnected()) {
117 | // response = response.newBuilder()
118 | // .removeHeader("Pragma")
119 | // .header("Cache-Control", "public, max-age=" + maxAge)
120 | // .build();
121 | // } else {
122 | // response = response.newBuilder()
123 | // .removeHeader("Pragma")
124 | // .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
125 | // .build();
126 | // }
127 | // return response;
128 | // }
129 | // }
130 |
131 | }
132 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/cnsunrun/debugdemo/mvp/model/network/api/ICopyService.java:
--------------------------------------------------------------------------------
1 | package com.example.cnsunrun.debugdemo.mvp.model.network.api;
2 |
3 | import com.example.cnsunrun.debugdemo.mvp.model.bean.CopyDetailsInfo;
4 | import com.example.cnsunrun.debugdemo.mvp.model.bean.CopyInfo;
5 | import com.example.cnsunrun.debugdemo.mvp.model.bean.base.BaseResponseInfo;
6 |
7 | import io.reactivex.Flowable;
8 | import retrofit2.http.GET;
9 | import retrofit2.http.Headers;
10 | import retrofit2.http.Query;
11 |
12 | /**
13 | * Created by cnsunrun on 2017/4/19.
14 | *
15 | * http://server.juju.la/activityo/activityolist?pageid=1&form=1&sid=d89a68bddc0784e750f6f841eeb61647#
16 | */
17 |
18 | public interface ICopyService {
19 |
20 | /**
21 | * 获取副本列表
22 | *
23 | * @param pageId
24 | * @param form
25 | * @param sid
26 | * @return
27 | */
28 | @Headers({"Juju-Token: e2768897c0e5b4ba9e13ed7edf1ef8da", "Juju-Banben: A262", "User-Agent: Juju Android Client"})
29 | @GET("activityo/activityolist")
30 | Flowable> getCopys(@Query("pageid") int pageId,
31 | @Query("form") int form,
32 | @Query("sid") String sid);
33 |
34 | /**
35 | * 获取副本详情
36 | *
37 | * @param activityid
38 | * @param sid
39 | * @return
40 | */
41 | @Headers({"Juju-Token: e2768897c0e5b4ba9e13ed7edf1ef8da", "Juju-Banben: A262", "User-Agent: Juju Android Client"})
42 | @GET("activityo/activityodetail")
43 | Flowable getCopyDetails(@Query("activityid") String activityid,
44 | @Query("sid") String sid);
45 | }
46 |
47 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/cnsunrun/debugdemo/mvp/model/network/api/IQuanziService.java:
--------------------------------------------------------------------------------
1 | package com.example.cnsunrun.debugdemo.mvp.model.network.api;
2 |
3 | import com.example.cnsunrun.debugdemo.mvp.model.bean.QuanziDetailsInfo;
4 | import com.example.cnsunrun.debugdemo.mvp.model.bean.QuanziInfo;
5 | import com.example.cnsunrun.debugdemo.mvp.model.bean.base.BaseResponseInfo;
6 |
7 | import io.reactivex.Flowable;
8 | import retrofit2.http.GET;
9 | import retrofit2.http.Headers;
10 | import retrofit2.http.Query;
11 |
12 | /**
13 | * Created by cnsunrun on 2017/3/11.
14 | *
15 | * lastid=-1&activityid=-1&hotlastid=-1&type=1&userid=-1&dynamicuserids=1111&sid=dbe5b18fe665dbc25d22cdeb2d5cc436#
16 | */
17 |
18 | public interface IQuanziService {
19 |
20 | /**
21 | * 获取圈子列表数据
22 | *
23 | * @param lastid
24 | * @param activityid
25 | * @param hotlastid
26 | * @param type
27 | * @param userid
28 | * @param dynamicuserids
29 | * @param sid
30 | * @return
31 | */
32 | @Headers({"Juju-Token: e2768897c0e5b4ba9e13ed7edf1ef8da", "Juju-Banben: A262", "User-Agent: Juju Android Client"})
33 | @GET("newblog/bloglist")
34 | Flowable> getQuanziInfos(@Query("lastid") long lastid,
35 | @Query("activityid") long activityid,
36 | @Query("hotlastid") long hotlastid,
37 | @Query("type") int type,
38 | @Query("userid") int userid,
39 | @Query("dynamicuserids") int dynamicuserids,
40 | @Query("sid") String sid);
41 |
42 |
43 | /**
44 | * 获取圈子详情数据
45 | *
46 | * @param blogid
47 | * @param sid
48 | * @return
49 | */
50 | @Headers({"Juju-Token: e2768897c0e5b4ba9e13ed7edf1ef8da", "Juju-Banben: A262", "User-Agent: Juju Android Client"})
51 | @GET("newblog/blogview")
52 | Flowable> getQuanziDetailsInfo(@Query("blogid") String blogid,
53 | @Query("sid") String sid);
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/cnsunrun/debugdemo/mvp/presenter/CopyListPresenter.java:
--------------------------------------------------------------------------------
1 | package com.example.cnsunrun.debugdemo.mvp.presenter;
2 |
3 | import android.content.Context;
4 | import android.util.Log;
5 |
6 | import com.example.cnsunrun.debugdemo.app.AppConstant;
7 | import com.example.cnsunrun.debugdemo.app.ApplicationModule;
8 | import com.example.cnsunrun.debugdemo.mvp.contract.CopyListContract;
9 | import com.example.cnsunrun.debugdemo.mvp.model.network.RetrofitHelper;
10 | import com.example.cnsunrun.debugdemo.mvp.presenter.base.DaggerPresenterComponent;
11 | import com.example.cnsunrun.debugdemo.utils.ActivityScoped;
12 |
13 | import java.util.concurrent.TimeUnit;
14 |
15 | import javax.inject.Inject;
16 |
17 | import io.reactivex.android.schedulers.AndroidSchedulers;
18 | import io.reactivex.disposables.CompositeDisposable;
19 | import io.reactivex.disposables.Disposable;
20 | import io.reactivex.schedulers.Schedulers;
21 |
22 | /**
23 | * Created by cnsunrun on 2017/4/19.
24 | */
25 | @ActivityScoped
26 | public class CopyListPresenter implements CopyListContract.Presenter {
27 |
28 | private CopyListContract.View view;
29 |
30 | private CompositeDisposable compositeDisposable;
31 |
32 | @Inject
33 | CopyListPresenter(Context context, CopyListContract.View view) {
34 | this.view = view;
35 | view.setPresenter(this);
36 | compositeDisposable = new CompositeDisposable();
37 |
38 | DaggerPresenterComponent.builder()
39 | .applicationModule(new ApplicationModule(context))
40 | .build().inject(this);
41 | }
42 |
43 | @Override
44 | public void subscribe() {
45 | loadData();
46 | }
47 |
48 | @Override
49 | public void unSubscribe() {
50 | compositeDisposable.clear();
51 | }
52 |
53 | @Override
54 | public void loadData() {
55 |
56 | Disposable subscribe = RetrofitHelper.createCopyService()
57 | .getCopys(1, 1, "d89a68bddc0784e750f6f841eeb61647#")
58 | .delay(1000, TimeUnit.MILLISECONDS)
59 | .filter(copyInfoBaseResponseInfo -> copyInfoBaseResponseInfo.getCode().equals(AppConstant.SUCCESS_CODE))
60 | .map(copyInfoBaseResponseInfo -> copyInfoBaseResponseInfo.getBaseResult().getActivityoListBeans())
61 | .subscribeOn(Schedulers.io())
62 | .observeOn(AndroidSchedulers.mainThread())
63 | .subscribe(activityoListBeen -> view.displayData(activityoListBeen),
64 | throwable -> Log.e("tag", throwable.getMessage()));
65 |
66 | compositeDisposable.add(subscribe);
67 | }
68 |
69 | public void loadMoreData(int page) {
70 | Disposable subscribe = RetrofitHelper.createCopyService()
71 | .getCopys(page, 1, "d89a68bddc0784e750f6f841eeb61647#")
72 | .delay(1000, TimeUnit.MILLISECONDS)
73 | .filter(copyInfoBaseResponseInfo -> copyInfoBaseResponseInfo.getCode().equals(AppConstant.SUCCESS_CODE))
74 | .map(copyInfoBaseResponseInfo -> copyInfoBaseResponseInfo.getBaseResult().getActivityoListBeans())
75 | .subscribeOn(Schedulers.io())
76 | .observeOn(AndroidSchedulers.mainThread())
77 | .subscribe(activityoListBeen -> view.displayData(activityoListBeen),
78 | throwable -> Log.e("tag", throwable.getMessage()));
79 |
80 | compositeDisposable.add(subscribe);
81 | }
82 |
83 | }
84 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/cnsunrun/debugdemo/mvp/presenter/QuanziListPresenter.java:
--------------------------------------------------------------------------------
1 | package com.example.cnsunrun.debugdemo.mvp.presenter;
2 |
3 | import android.content.Context;
4 | import android.util.Log;
5 |
6 | import com.example.cnsunrun.debugdemo.app.AppConstant;
7 | import com.example.cnsunrun.debugdemo.app.ApplicationModule;
8 | import com.example.cnsunrun.debugdemo.mvp.contract.QuanziListContract;
9 | import com.example.cnsunrun.debugdemo.mvp.model.network.RetrofitHelper;
10 | import com.example.cnsunrun.debugdemo.mvp.presenter.base.DaggerPresenterComponent;
11 | import com.example.cnsunrun.debugdemo.utils.ActivityScoped;
12 |
13 | import java.util.concurrent.TimeUnit;
14 |
15 | import javax.inject.Inject;
16 |
17 | import io.reactivex.android.schedulers.AndroidSchedulers;
18 | import io.reactivex.disposables.CompositeDisposable;
19 | import io.reactivex.disposables.Disposable;
20 | import io.reactivex.schedulers.Schedulers;
21 |
22 | /**
23 | * Created by cnsunrun on 2017/3/17.
24 | */
25 | @ActivityScoped
26 | public class QuanziListPresenter implements QuanziListContract.Presenter {
27 |
28 | private QuanziListContract.View view;
29 |
30 | private CompositeDisposable subscription;
31 |
32 | @Inject
33 | QuanziListPresenter(Context context, QuanziListContract.View view) {
34 | this.view = view;
35 | view.setPresenter(this);
36 | subscription = new CompositeDisposable();
37 |
38 | DaggerPresenterComponent.builder()
39 | .applicationModule(new ApplicationModule(context))
40 | .build().inject(this);
41 | }
42 |
43 | @Override
44 | public void subscribe() {
45 | Log.e("tag","加载数据 subscribe");
46 | loadData();
47 | }
48 |
49 | @Override
50 | public void unSubscribe() {
51 | subscription.clear();
52 | }
53 |
54 | @Override
55 | public void loadData() {
56 | Log.e("tag","加载数据 loadData");
57 | Disposable subscribe = RetrofitHelper.createQuanziService()
58 | .getQuanziInfos(-1, -1, -1, 1, -1, 1111, "dbe5b18fe665dbc25d22cdeb2d5cc436#")
59 | .delay(1000, TimeUnit.MILLISECONDS)
60 | .filter(quanziInfoBaseResponseInfo -> quanziInfoBaseResponseInfo.getCode().equals(AppConstant.SUCCESS_CODE))
61 | .map(quanziInfoBaseResponseInfo -> quanziInfoBaseResponseInfo.getBaseResult().getBlogList())
62 | .subscribeOn(Schedulers.io())
63 | .observeOn(AndroidSchedulers.mainThread())
64 | .subscribe(blogListBeen -> view.displayData(blogListBeen),
65 | throwable -> Log.e("tag", throwable.getMessage()));
66 |
67 | subscription.add(subscribe);
68 | }
69 |
70 | public void loadMoreData(long lastId, long hotLastId) {
71 | Log.e("tag","加载数据 loadMoreData");
72 | Disposable subscribe = RetrofitHelper.createQuanziService()
73 | .getQuanziInfos(lastId, -1, hotLastId, 1, -1, 1111, "dbe5b18fe665dbc25d22cdeb2d5cc436#")
74 | .delay(1000, TimeUnit.MILLISECONDS)
75 | .filter(quanziInfoBaseResponseInfo -> quanziInfoBaseResponseInfo.getCode().equals(AppConstant.SUCCESS_CODE))
76 | .map(quanziInfoBaseResponseInfo -> quanziInfoBaseResponseInfo.getBaseResult().getBlogList())
77 | .subscribeOn(Schedulers.io())
78 | .observeOn(AndroidSchedulers.mainThread())
79 | .subscribe(blogListBeen -> view.displayData(blogListBeen),
80 | throwable -> Log.e("tag", throwable.getMessage()));
81 |
82 | subscription.add(subscribe);
83 |
84 | }
85 |
86 | }
87 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/cnsunrun/debugdemo/mvp/presenter/base/PresenterComponent.java:
--------------------------------------------------------------------------------
1 | package com.example.cnsunrun.debugdemo.mvp.presenter.base;
2 |
3 | import com.example.cnsunrun.debugdemo.app.ApplicationModule;
4 | import com.example.cnsunrun.debugdemo.mvp.presenter.CopyListPresenter;
5 | import com.example.cnsunrun.debugdemo.mvp.presenter.QuanziListPresenter;
6 |
7 | import javax.inject.Singleton;
8 |
9 | import dagger.Component;
10 |
11 |
12 | @Singleton
13 | @Component(modules = {ApplicationModule.class})
14 | public interface PresenterComponent {
15 |
16 | void inject(QuanziListPresenter presenter);
17 |
18 | void inject(CopyListPresenter presenter);
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/cnsunrun/debugdemo/mvp/ui/activity/ImageDetailsActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.cnsunrun.debugdemo.mvp.ui.activity;
2 |
3 | import android.os.Bundle;
4 | import android.support.annotation.Nullable;
5 | import android.support.v4.app.Fragment;
6 | import android.support.v4.app.FragmentManager;
7 | import android.support.v4.app.FragmentPagerAdapter;
8 | import android.support.v4.view.ViewPager;
9 | import android.support.v7.app.AppCompatActivity;
10 | import android.widget.TextView;
11 |
12 | import com.example.cnsunrun.debugdemo.R;
13 | import com.example.cnsunrun.debugdemo.mvp.ui.fragment.ImageDetailsFragment;
14 |
15 | import java.util.ArrayList;
16 | import java.util.List;
17 |
18 | import butterknife.Bind;
19 | import butterknife.ButterKnife;
20 |
21 | /**
22 | * Created by cnsunrun on 2017/4/24.
23 | */
24 |
25 | public class ImageDetailsActivity extends AppCompatActivity {
26 |
27 |
28 | @Bind(R.id.tv_index)
29 | TextView mIndex;
30 | @Bind(R.id.view_pager)
31 | ViewPager mViewPager;
32 | private ArrayList images_url;
33 | private int index;
34 |
35 | @Override
36 | protected void onCreate(@Nullable Bundle savedInstanceState) {
37 | super.onCreate(savedInstanceState);
38 | setContentView(R.layout.activity_image_details);
39 | ButterKnife.bind(this);
40 | index = getIntent().getIntExtra("index", -1);
41 | images_url = getIntent().getStringArrayListExtra("images_url");
42 |
43 | initView();
44 | }
45 |
46 | private void initView() {
47 | mIndex.setText((index + 1) + " / " + images_url.size());
48 | ImageViewPagerAdapter mAdapter = new ImageViewPagerAdapter(getSupportFragmentManager(), images_url);
49 | mViewPager.setAdapter(mAdapter);
50 | mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
51 | @Override
52 | public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
53 |
54 | }
55 |
56 | @Override
57 | public void onPageSelected(int position) {
58 | mIndex.setText((position + 1) + " / " + images_url.size());
59 | }
60 |
61 | @Override
62 | public void onPageScrollStateChanged(int state) {
63 |
64 | }
65 | });
66 | }
67 |
68 | @Override
69 | protected void onResume() {
70 | super.onResume();
71 | mViewPager.setCurrentItem(index);
72 | }
73 |
74 | private static class ImageViewPagerAdapter extends FragmentPagerAdapter {
75 |
76 | private List urls;
77 |
78 | public ImageViewPagerAdapter(FragmentManager fm, List urls) {
79 | super(fm);
80 | this.urls = urls;
81 | }
82 |
83 | @Override
84 | public Fragment getItem(int position) {
85 | return ImageDetailsFragment.newInstance(urls.get(position));
86 | }
87 |
88 | @Override
89 | public int getCount() {
90 | return urls.size();
91 | }
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/cnsunrun/debugdemo/mvp/ui/activity/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.cnsunrun.debugdemo.mvp.ui.activity;
2 |
3 | import android.os.Bundle;
4 | import android.support.annotation.Nullable;
5 | import android.support.v4.app.Fragment;
6 | import android.support.v4.app.FragmentTransaction;
7 | import android.support.v7.app.AppCompatActivity;
8 | import android.support.v7.widget.Toolbar;
9 |
10 | import com.aurelhubert.ahbottomnavigation.AHBottomNavigation;
11 | import com.aurelhubert.ahbottomnavigation.AHBottomNavigationItem;
12 | import com.example.cnsunrun.debugdemo.R;
13 | import com.example.cnsunrun.debugdemo.mvp.ui.fragment.CommunityFragment;
14 | import com.example.cnsunrun.debugdemo.mvp.ui.fragment.CopyListFragment;
15 | import com.example.cnsunrun.debugdemo.mvp.ui.fragment.MineFragment;
16 | import com.example.cnsunrun.debugdemo.mvp.ui.fragment.QuanziListFragment;
17 |
18 | import java.util.ArrayList;
19 | import java.util.List;
20 |
21 | import butterknife.Bind;
22 | import butterknife.ButterKnife;
23 |
24 | /**
25 | * Created by cnsunrun on 2017/4/19.
26 | */
27 |
28 | public class MainActivity extends AppCompatActivity {
29 |
30 | @Bind(R.id.toolbar)
31 | Toolbar mToolbar;
32 | @Bind(R.id.bottom_navigation)
33 | AHBottomNavigation mAhBottomNavigation;
34 |
35 | private int currentTabIndex;
36 | private List fragments = new ArrayList<>();
37 |
38 | @Override
39 | protected void onCreate(@Nullable Bundle savedInstanceState) {
40 | super.onCreate(savedInstanceState);
41 | setContentView(R.layout.activity_main);
42 | ButterKnife.bind(this);
43 |
44 | mToolbar.setTitle("");
45 | setSupportActionBar(mToolbar);
46 | fragments.add(CopyListFragment.newInstance());
47 | fragments.add(QuanziListFragment.newInstance());
48 | fragments.add(CommunityFragment.newInstance());
49 | fragments.add(MineFragment.newInstance());
50 | showFragment(fragments.get(0));
51 | initBottomNav();
52 |
53 | }
54 |
55 | private void showFragment(Fragment fragment) {
56 |
57 | getSupportFragmentManager()
58 | .beginTransaction()
59 | .replace(R.id.content, fragment)
60 | .commit();
61 | }
62 |
63 | private void initBottomNav() {
64 |
65 | AHBottomNavigationItem item1 = new AHBottomNavigationItem("主页",
66 | R.drawable.ic_tab_home);
67 | AHBottomNavigationItem item2 = new AHBottomNavigationItem("圈子",
68 | R.drawable.ic_tab_quanzi);
69 | AHBottomNavigationItem item3 = new AHBottomNavigationItem("社区",
70 | R.drawable.ic_tab_community);
71 | AHBottomNavigationItem item4 = new AHBottomNavigationItem("我的",
72 | R.drawable.ic_tab_mine);
73 |
74 | mAhBottomNavigation.addItem(item1);
75 | mAhBottomNavigation.addItem(item2);
76 | mAhBottomNavigation.addItem(item3);
77 | mAhBottomNavigation.addItem(item4);
78 |
79 | mAhBottomNavigation.setColored(false);
80 | mAhBottomNavigation.setForceTint(false);
81 | mAhBottomNavigation.setBehaviorTranslationEnabled(true);
82 | mAhBottomNavigation.setTitleState(AHBottomNavigation.TitleState.ALWAYS_SHOW);
83 | mAhBottomNavigation.setAccentColor(getResources().getColor(R.color.colorPrimaryDark));
84 | mAhBottomNavigation.setInactiveColor(getResources().getColor(R.color.colorPrimaryDark));
85 | mAhBottomNavigation.setCurrentItem(0);
86 | mAhBottomNavigation.setDefaultBackgroundColor(
87 | getResources().getColor(R.color.colorPrimary));
88 |
89 | mAhBottomNavigation.setOnTabSelectedListener((position, wasSelected) -> {
90 |
91 | if (currentTabIndex != position) {
92 | FragmentTransaction trx = getSupportFragmentManager().beginTransaction();
93 | trx.hide(fragments.get(currentTabIndex));
94 | if (!fragments.get(position).isAdded()) {
95 | trx.add(R.id.content, fragments.get(position));
96 | }
97 | trx.show(fragments.get(position)).commit();
98 | }
99 | currentTabIndex = position;
100 |
101 | return true;
102 | });
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/cnsunrun/debugdemo/mvp/ui/activity/QuanziDetailsActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.cnsunrun.debugdemo.mvp.ui.activity;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.content.Intent;
5 | import android.os.Bundle;
6 | import android.support.v4.widget.NestedScrollView;
7 | import android.support.v7.app.ActionBar;
8 | import android.support.v7.app.AppCompatActivity;
9 | import android.support.v7.widget.LinearLayoutManager;
10 | import android.support.v7.widget.RecyclerView;
11 | import android.support.v7.widget.Toolbar;
12 | import android.util.Log;
13 | import android.view.MenuItem;
14 | import android.view.View;
15 | import android.widget.ImageView;
16 | import android.widget.LinearLayout;
17 | import android.widget.TextView;
18 |
19 | import com.bumptech.glide.Glide;
20 | import com.bumptech.glide.load.engine.DiskCacheStrategy;
21 | import com.example.cnsunrun.debugdemo.R;
22 | import com.example.cnsunrun.debugdemo.mvp.model.bean.QuanziDetailsInfo;
23 | import com.example.cnsunrun.debugdemo.mvp.model.bean.base.BaseResponseInfo;
24 | import com.example.cnsunrun.debugdemo.mvp.model.network.RetrofitHelper;
25 | import com.example.cnsunrun.debugdemo.mvp.ui.adapter.CommentAdapter;
26 | import com.example.cnsunrun.debugdemo.widget.CircleImageView;
27 | import com.example.cnsunrun.debugdemo.widget.CircleProgressView;
28 | import com.example.cnsunrun.debugdemo.widget.MomentPicView;
29 |
30 | import java.util.ArrayList;
31 | import java.util.List;
32 |
33 | import butterknife.Bind;
34 | import butterknife.ButterKnife;
35 | import io.reactivex.android.schedulers.AndroidSchedulers;
36 | import io.reactivex.disposables.Disposable;
37 | import io.reactivex.schedulers.Schedulers;
38 |
39 | public class QuanziDetailsActivity extends AppCompatActivity {
40 |
41 | @Bind(R.id.multi_image)
42 | MomentPicView momentPicView;
43 | @Bind(R.id.toolbar)
44 | Toolbar mToolbar;
45 | @Bind(R.id.iv_head_image)
46 | CircleImageView mHeadImage;
47 | @Bind(R.id.tv_user_name)
48 | TextView mUserName;
49 | @Bind(R.id.tv_date)
50 | TextView mDate;
51 | @Bind(R.id.tv_content)
52 | TextView mContent;
53 | @Bind(R.id.tv_tags)
54 | TextView mTags;
55 | @Bind(R.id.tv_like_num)
56 | TextView mLikeNum;
57 | @Bind(R.id.tv_comments)
58 | TextView mComments;
59 | @Bind(R.id.recycler_view)
60 | RecyclerView mRecyclerView;
61 | @Bind(R.id.circle_progress)
62 | CircleProgressView mCircleProgressView;
63 | @Bind(R.id.root_layout)
64 | LinearLayout mRootLayout;
65 | @Bind(R.id.nested_scroll_view)
66 | NestedScrollView mNestedScrollView;
67 | @Bind(R.id.single_image)
68 | ImageView mSingleImage;
69 |
70 | private String id;
71 | private QuanziDetailsInfo mQuanziDetailsInfo;
72 | private Disposable subscribe;
73 | private String title;
74 |
75 | @Override
76 | protected void onCreate(Bundle savedInstanceState) {
77 | super.onCreate(savedInstanceState);
78 | setContentView(R.layout.activity_quanzi_details);
79 | ButterKnife.bind(this);
80 | mNestedScrollView.setNestedScrollingEnabled(true);
81 | Intent intent = getIntent();
82 | if (intent != null) {
83 | id = intent.getStringExtra("id");
84 | title = intent.getStringExtra("title");
85 | }
86 | initToolBar();
87 | loadData();
88 | }
89 |
90 | private void initToolBar() {
91 | mToolbar.setTitle(title);
92 | setSupportActionBar(mToolbar);
93 | ActionBar supportActionBar = getSupportActionBar();
94 | if (supportActionBar != null) {
95 | supportActionBar.setDisplayHomeAsUpEnabled(true);
96 | }
97 | }
98 |
99 | @Override
100 | public boolean onOptionsItemSelected(MenuItem item) {
101 | if (item.getItemId() == android.R.id.home) {
102 | onBackPressed();
103 | }
104 | return super.onOptionsItemSelected(item);
105 | }
106 |
107 | private void loadData() {
108 | subscribe = RetrofitHelper.createQuanziService()
109 | .getQuanziDetailsInfo(id, "dbe5b18fe665dbc25d22cdeb2d5cc436#")
110 | .doOnSubscribe(subscription -> {
111 | mRootLayout.setVisibility(View.GONE);
112 | mCircleProgressView.setVisibility(View.VISIBLE);
113 | mCircleProgressView.spin();
114 | })
115 | .filter(quanziDetailsInfoBaseResponseInfo -> quanziDetailsInfoBaseResponseInfo.getCode().equals("10000"))
116 | .map(BaseResponseInfo::getBaseResult)
117 | .subscribeOn(Schedulers.io())
118 | .observeOn(AndroidSchedulers.mainThread())
119 | .doOnComplete(() -> {
120 | mRootLayout.setVisibility(View.VISIBLE);
121 | mCircleProgressView.setVisibility(View.GONE);
122 | mCircleProgressView.stopSpinning();
123 | })
124 | .subscribe(quanziDetailsInfo -> {
125 | mQuanziDetailsInfo = quanziDetailsInfo;
126 | finishTask();
127 | }, throwable -> Log.e("tag", throwable.getMessage()));
128 |
129 | }
130 |
131 | @SuppressLint("SetTextI18n")
132 | private void finishTask() {
133 | //设置详情数据
134 | QuanziDetailsInfo.BlogBean blog = mQuanziDetailsInfo.getBlog();
135 | QuanziDetailsInfo.UserBean user = mQuanziDetailsInfo.getUser();
136 | List commentList = mQuanziDetailsInfo.getCommentList();
137 | //设置用户信息
138 | Glide.with(this)
139 | .load(user.getHeadpic())
140 | .centerCrop()
141 | .diskCacheStrategy(DiskCacheStrategy.ALL)
142 | .dontAnimate()
143 | .into(mHeadImage);
144 | mUserName.setText(user.getNicename());
145 | mDate.setText(blog.getJointime());
146 | //设置内容
147 | mContent.setText(blog.getContent());
148 | //设置图片
149 | List picturelist = blog.getPicturelist();
150 | if (picturelist != null && picturelist.size() > 0) {
151 | if (picturelist.size() > 1) {
152 | //设置多张图片展示
153 | mSingleImage.setVisibility(View.GONE);
154 | momentPicView.setImageUrls(picturelist);
155 | momentPicView.setOnClickItemListener((i, url) -> {
156 | Intent intent = new Intent(QuanziDetailsActivity.this, ImageDetailsActivity.class);
157 | intent.putExtra("index", i);
158 | intent.putExtra("images_url", url);
159 | QuanziDetailsActivity.this.startActivity(intent);
160 | });
161 | } else {
162 | //单张图片展示
163 | mSingleImage.setVisibility(View.VISIBLE);
164 | Glide.with(this)
165 | .load(picturelist.get(0))
166 | .centerCrop()
167 | .diskCacheStrategy(DiskCacheStrategy.ALL)
168 | .crossFade(0)
169 | .into(mSingleImage);
170 | mSingleImage.setOnClickListener(v -> {
171 | ArrayList urls = new ArrayList<>();
172 | urls.add(picturelist.get(0));
173 | Intent intent = new Intent(QuanziDetailsActivity.this, ImageDetailsActivity.class);
174 | intent.putExtra("index", 0);
175 | intent.putExtra("images_url", urls);
176 | QuanziDetailsActivity.this.startActivity(intent);
177 | });
178 | }
179 |
180 | }
181 | //设置标签
182 | List tagnames = blog.getTagnames();
183 | tagnames.forEach(tagnamesBean -> mTags.append(tagnamesBean.getName() + ","));
184 | //设置喜欢数量
185 | mLikeNum.setText(blog.getFavour_counter());
186 | //设置评论数量
187 | mComments.setText("评论 " + blog.getComment_counter());
188 | //设置评论列表
189 | if (commentList != null && commentList.size() > 0) {
190 | mComments.setVisibility(View.VISIBLE);
191 | mRecyclerView.setHasFixedSize(false);
192 | mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
193 | mRecyclerView.setNestedScrollingEnabled(false);
194 | CommentAdapter mAdapter = new CommentAdapter();
195 | mAdapter.setDataSources(commentList);
196 | mRecyclerView.setAdapter(mAdapter);
197 | } else {
198 | mComments.setVisibility(View.GONE);
199 | }
200 |
201 | }
202 |
203 | @Override
204 | protected void onDestroy() {
205 | ButterKnife.unbind(this);
206 | if (subscribe != null && !subscribe.isDisposed()) {
207 | subscribe.dispose();
208 | }
209 | super.onDestroy();
210 | }
211 | }
212 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/cnsunrun/debugdemo/mvp/ui/activity/component/CopyListComponent.java:
--------------------------------------------------------------------------------
1 | package com.example.cnsunrun.debugdemo.mvp.ui.activity.component;
2 |
3 | import com.example.cnsunrun.debugdemo.app.ApplicationComponent;
4 | import com.example.cnsunrun.debugdemo.mvp.ui.activity.module.CopyListModule;
5 | import com.example.cnsunrun.debugdemo.mvp.ui.fragment.CopyListFragment;
6 | import com.example.cnsunrun.debugdemo.utils.ActivityScoped;
7 |
8 | import dagger.Component;
9 |
10 | /**
11 | * Created by cnsunrun on 2017/4/19.
12 | */
13 | @ActivityScoped
14 | @Component(modules = CopyListModule.class, dependencies = ApplicationComponent.class)
15 | public interface CopyListComponent {
16 |
17 | void inject(CopyListFragment copyListFragment);
18 | }
19 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/cnsunrun/debugdemo/mvp/ui/activity/component/QuanziListComponent.java:
--------------------------------------------------------------------------------
1 | package com.example.cnsunrun.debugdemo.mvp.ui.activity.component;
2 |
3 | import com.example.cnsunrun.debugdemo.app.ApplicationComponent;
4 | import com.example.cnsunrun.debugdemo.mvp.ui.activity.module.QuanziListModule;
5 | import com.example.cnsunrun.debugdemo.mvp.ui.fragment.QuanziListFragment;
6 | import com.example.cnsunrun.debugdemo.utils.ActivityScoped;
7 |
8 | import dagger.Component;
9 |
10 | /**
11 | * Created by cnsunrun on 2017/3/17.
12 | */
13 | @ActivityScoped
14 | @Component(modules = QuanziListModule.class, dependencies = ApplicationComponent.class)
15 | public interface QuanziListComponent {
16 |
17 | void inject(QuanziListFragment quanziListFragment);
18 | }
19 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/cnsunrun/debugdemo/mvp/ui/activity/module/CopyListModule.java:
--------------------------------------------------------------------------------
1 | package com.example.cnsunrun.debugdemo.mvp.ui.activity.module;
2 |
3 | import com.example.cnsunrun.debugdemo.mvp.contract.CopyListContract;
4 |
5 | import dagger.Module;
6 | import dagger.Provides;
7 |
8 | /**
9 | * Created by cnsunrun on 2017/4/19.
10 | */
11 | @Module
12 | public class CopyListModule {
13 |
14 | private CopyListContract.View view;
15 |
16 | public CopyListModule(CopyListContract.View view) {
17 | this.view = view;
18 | }
19 |
20 | @Provides
21 | CopyListContract.View provideCopyListContractView() {
22 | return view;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/cnsunrun/debugdemo/mvp/ui/activity/module/QuanziListModule.java:
--------------------------------------------------------------------------------
1 | package com.example.cnsunrun.debugdemo.mvp.ui.activity.module;
2 |
3 | import com.example.cnsunrun.debugdemo.mvp.contract.QuanziListContract;
4 |
5 | import dagger.Module;
6 | import dagger.Provides;
7 |
8 | /**
9 | * Created by cnsunrun on 2017/3/17.
10 | */
11 | @Module
12 | public class QuanziListModule {
13 |
14 | private QuanziListContract.View view;
15 |
16 | public QuanziListModule(QuanziListContract.View view) {
17 | this.view = view;
18 | }
19 |
20 | @Provides
21 | QuanziListContract.View provideQuanziListContractView() {
22 | return view;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/cnsunrun/debugdemo/mvp/ui/adapter/CommentAdapter.java:
--------------------------------------------------------------------------------
1 | package com.example.cnsunrun.debugdemo.mvp.ui.adapter;
2 |
3 | import android.view.LayoutInflater;
4 | import android.view.View;
5 | import android.view.ViewGroup;
6 | import android.widget.TextView;
7 |
8 | import com.bumptech.glide.Glide;
9 | import com.bumptech.glide.load.engine.DiskCacheStrategy;
10 | import com.example.cnsunrun.debugdemo.R;
11 | import com.example.cnsunrun.debugdemo.mvp.model.bean.QuanziDetailsInfo;
12 | import com.example.cnsunrun.debugdemo.mvp.ui.adapter.base.AbsRecyclerViewAdapter;
13 | import com.example.cnsunrun.debugdemo.widget.CircleImageView;
14 |
15 | /**
16 | * Created by cnsunrun on 2017/4/20.
17 | */
18 |
19 | public class CommentAdapter extends AbsRecyclerViewAdapter {
20 |
21 | @Override
22 | public void onBindViewHolder(ClickableViewHolder holder, int position) {
23 | if (holder instanceof ItemViewHolder) {
24 | ItemViewHolder itemViewHolder = (ItemViewHolder) holder;
25 | QuanziDetailsInfo.CommentListBean commentListBean = mDataSources.get(position);
26 | Glide.with(getContext())
27 | .load(commentListBean.getHeadpic())
28 | .centerCrop()
29 | .diskCacheStrategy(DiskCacheStrategy.ALL)
30 | .dontAnimate()
31 | .into(itemViewHolder.mHeadImage);
32 | itemViewHolder.mUserName.setText(commentListBean.getNicename());
33 | itemViewHolder.mDate.setText(commentListBean.getJointime());
34 | itemViewHolder.mContent.setText(commentListBean.getContent());
35 | }
36 | super.onBindViewHolder(holder, position);
37 | }
38 |
39 | @Override
40 | public ClickableViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
41 | bindContext(parent.getContext());
42 | return new ItemViewHolder(LayoutInflater.from(getContext())
43 | .inflate(R.layout.item_comment, parent, false));
44 | }
45 |
46 | private class ItemViewHolder extends AbsRecyclerViewAdapter.ClickableViewHolder {
47 | CircleImageView mHeadImage;
48 | TextView mUserName;
49 | TextView mDate;
50 | TextView mContent;
51 |
52 | public ItemViewHolder(View itemView) {
53 | super(itemView);
54 | mHeadImage = $(R.id.item_head_image);
55 | mUserName = $(R.id.item_user_name);
56 | mDate = $(R.id.item_date);
57 | mContent = $(R.id.item_content);
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/cnsunrun/debugdemo/mvp/ui/adapter/CopyAdapter.java:
--------------------------------------------------------------------------------
1 | package com.example.cnsunrun.debugdemo.mvp.ui.adapter;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.view.LayoutInflater;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 | import android.widget.ImageView;
8 | import android.widget.TextView;
9 |
10 | import com.bumptech.glide.Glide;
11 | import com.bumptech.glide.load.engine.DiskCacheStrategy;
12 | import com.example.cnsunrun.debugdemo.R;
13 | import com.example.cnsunrun.debugdemo.mvp.model.bean.CopyInfo;
14 | import com.example.cnsunrun.debugdemo.mvp.ui.adapter.base.AbsRecyclerViewAdapter;
15 |
16 | /**
17 | * Created by cnsunrun on 2017/4/19.
18 | */
19 |
20 | public class CopyAdapter extends AbsRecyclerViewAdapter {
21 |
22 | @SuppressLint("SetTextI18n")
23 | @Override
24 | public void onBindViewHolder(ClickableViewHolder holder, int position) {
25 | if (holder instanceof ItemViewHolder) {
26 | ItemViewHolder itemViewHolder = (ItemViewHolder) holder;
27 | CopyInfo.ActivityoListBean activityoListBean = mDataSources.get(position);
28 | Glide.with(getContext())
29 | .load(activityoListBean.getPicture())
30 | .centerCrop()
31 | .diskCacheStrategy(DiskCacheStrategy.ALL)
32 | .crossFade()
33 | .into(itemViewHolder.mCopyImage);
34 | itemViewHolder.mCopyName.setText("副本:" + activityoListBean.getName());
35 | itemViewHolder.mCopyFounder.setText("队长:" + activityoListBean.getUser_name());
36 | }
37 | super.onBindViewHolder(holder, position);
38 | }
39 |
40 | @Override
41 | public ClickableViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
42 | bindContext(parent.getContext());
43 | return new ItemViewHolder(LayoutInflater.from(getContext()).inflate(R.layout.item_copy, parent, false));
44 | }
45 |
46 | private class ItemViewHolder extends AbsRecyclerViewAdapter.ClickableViewHolder {
47 | ImageView mCopyImage;
48 | TextView mCopyName;
49 | TextView mCopyFounder;
50 |
51 | public ItemViewHolder(View itemView) {
52 | super(itemView);
53 | mCopyImage = $(R.id.item_image);
54 | mCopyName = $(R.id.item_copy_name);
55 | mCopyFounder = $(R.id.item_copy_founder);
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/cnsunrun/debugdemo/mvp/ui/adapter/CopyDetailsAdapter.java:
--------------------------------------------------------------------------------
1 | package com.example.cnsunrun.debugdemo.mvp.ui.adapter;
2 |
3 | import android.content.Intent;
4 | import android.view.LayoutInflater;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 | import android.widget.TextView;
8 |
9 | import com.bumptech.glide.Glide;
10 | import com.bumptech.glide.load.engine.DiskCacheStrategy;
11 | import com.example.cnsunrun.debugdemo.R;
12 | import com.example.cnsunrun.debugdemo.mvp.model.bean.QuanziInfo;
13 | import com.example.cnsunrun.debugdemo.mvp.ui.activity.ImageDetailsActivity;
14 | import com.example.cnsunrun.debugdemo.mvp.ui.adapter.base.AbsRecyclerViewAdapter;
15 | import com.example.cnsunrun.debugdemo.widget.CircleImageView;
16 | import com.example.cnsunrun.debugdemo.widget.MomentPicView;
17 |
18 | import java.util.List;
19 |
20 | /**
21 | * Created by cnsunrun on 2017/4/24.
22 | */
23 |
24 | public class CopyDetailsAdapter extends AbsRecyclerViewAdapter {
25 |
26 | @Override
27 | public void onBindViewHolder(ClickableViewHolder holder, int position) {
28 | if (holder instanceof ItemViewHolder) {
29 | ItemViewHolder itemViewHolder = (ItemViewHolder) holder;
30 | QuanziInfo.BlogListBean blogListBean = mDataSources.get(position);
31 | Glide.with(getContext())
32 | .load(blogListBean.getHeadpic())
33 | .centerCrop()
34 | .diskCacheStrategy(DiskCacheStrategy.ALL)
35 | .dontAnimate()
36 | .into(itemViewHolder.mUserPhoto);
37 | itemViewHolder.mUserName.setText(blogListBean.getNicename());
38 | itemViewHolder.mTime.setText(blogListBean.getJointime());
39 | itemViewHolder.mContent.setText(blogListBean.getContent());
40 | List tagnames = blogListBean.getTagnames();
41 | if (!tagnames.isEmpty())
42 | itemViewHolder.mTags.setText(tagnames.get(0).getName());
43 | if (blogListBean.getPicturelist() != null && blogListBean.getPicturelist().size() > 0) {
44 | itemViewHolder.momentPicView.setImageUrls(blogListBean.getPicturelist());
45 | itemViewHolder.momentPicView.setOnClickItemListener((i, url) -> {
46 | Intent intent = new Intent(getContext(), ImageDetailsActivity.class);
47 | intent.putExtra("index", i);
48 | intent.putExtra("images_url", url);
49 | getContext().startActivity(intent);
50 | });
51 | }
52 | itemViewHolder.mForwardedNum.setText(blogListBean.getZhuanfa_counter().equals("0") ? "转发" : blogListBean.getZhuanfa_counter());
53 | itemViewHolder.mCommentNum.setText(blogListBean.getComment_counter().equals("0") ? "评论" : blogListBean.getComment_counter());
54 | itemViewHolder.mLikeNum.setText(blogListBean.getFavour_counter().equals("0") ? "喜欢" : blogListBean.getFavour_counter());
55 | }
56 | super.onBindViewHolder(holder, position);
57 | }
58 |
59 | @Override
60 | public ClickableViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
61 | bindContext(parent.getContext());
62 | return new ItemViewHolder(LayoutInflater.from(getContext())
63 | .inflate(R.layout.item_copy_details, parent, false));
64 | }
65 |
66 | private class ItemViewHolder extends AbsRecyclerViewAdapter.ClickableViewHolder {
67 | CircleImageView mUserPhoto;
68 | TextView mUserName;
69 | TextView mTime;
70 | TextView mContent;
71 | MomentPicView momentPicView;
72 | TextView mTags;
73 | TextView mForwardedNum;
74 | TextView mCommentNum;
75 | TextView mLikeNum;
76 |
77 |
78 | public ItemViewHolder(View itemView) {
79 | super(itemView);
80 | mUserPhoto = $(R.id.item_author_avatar);
81 | mUserName = $(R.id.item_author_name);
82 | mTime = $(R.id.item_time);
83 | mContent = $(R.id.item_content);
84 | momentPicView = $(R.id.item_multi_image);
85 | mTags = $(R.id.item_tag);
86 | mForwardedNum = $(R.id.tv_forwarded);
87 | mCommentNum = $(R.id.tv_comment_count);
88 | mLikeNum = $(R.id.tv_favour_count);
89 | }
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/cnsunrun/debugdemo/mvp/ui/adapter/QuanziAdapter.java:
--------------------------------------------------------------------------------
1 | package com.example.cnsunrun.debugdemo.mvp.ui.adapter;
2 |
3 | import android.view.LayoutInflater;
4 | import android.view.View;
5 | import android.view.ViewGroup;
6 | import android.widget.ImageView;
7 | import android.widget.TextView;
8 |
9 | import com.bumptech.glide.Glide;
10 | import com.bumptech.glide.load.engine.DiskCacheStrategy;
11 | import com.example.cnsunrun.debugdemo.R;
12 | import com.example.cnsunrun.debugdemo.mvp.model.bean.QuanziInfo;
13 | import com.example.cnsunrun.debugdemo.mvp.ui.adapter.base.AbsRecyclerViewAdapter;
14 | import com.example.cnsunrun.debugdemo.widget.CircleImageView;
15 |
16 | /**
17 | * Created by cnsunrun on 2017/3/11.
18 | */
19 |
20 | public class QuanziAdapter extends AbsRecyclerViewAdapter {
21 |
22 | @Override
23 | public ClickableViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
24 | bindContext(parent.getContext());
25 | return new ItemViewHolder(LayoutInflater.from(getContext()).inflate(R.layout.item_quanzi, parent, false));
26 | }
27 |
28 | @Override
29 | public void onBindViewHolder(ClickableViewHolder holder, int position) {
30 | if (holder instanceof ItemViewHolder) {
31 | final ItemViewHolder itemViewHolder = (ItemViewHolder) holder;
32 | QuanziInfo.BlogListBean blogListBean = mDataSources.get(position);
33 | Glide.with(getContext())
34 | .load(blogListBean.getPicture())
35 | .centerCrop()
36 | .diskCacheStrategy(DiskCacheStrategy.ALL)
37 | .into(itemViewHolder.mCoverImage);
38 | Glide.with(getContext())
39 | .load(blogListBean.getHeadpic())
40 | .centerCrop()
41 | .diskCacheStrategy(DiskCacheStrategy.ALL)
42 | .dontAnimate()
43 | .into(itemViewHolder.mHeadImage);
44 | itemViewHolder.mContent.setText(blogListBean.getContent());
45 | itemViewHolder.mUserName.setText(blogListBean.getNicename());
46 | itemViewHolder.mDate.setText(blogListBean.getJointime());
47 | itemViewHolder.mForwardingNum.setText(blogListBean.getZhuanfa_counter());
48 | itemViewHolder.mCommentNum.setText(blogListBean.getComment_counter());
49 | itemViewHolder.mLikeNum.setText(blogListBean.getFavour_counter());
50 | }
51 | super.onBindViewHolder(holder, position);
52 | }
53 |
54 |
55 | public class ItemViewHolder extends AbsRecyclerViewAdapter.ClickableViewHolder {
56 |
57 | ImageView mCoverImage;
58 | CircleImageView mHeadImage;
59 | TextView mUserName;
60 | TextView mDate;
61 | TextView mContent;
62 | TextView mForwardingNum;
63 | TextView mCommentNum;
64 | TextView mLikeNum;
65 |
66 | public ItemViewHolder(View itemView) {
67 | super(itemView);
68 | mCoverImage = $(R.id.item_image);
69 | mContent = $(R.id.item_text);
70 | mHeadImage = $(R.id.item_head_image);
71 | mUserName = $(R.id.item_user_name);
72 | mDate = $(R.id.item_date);
73 | mForwardingNum = $(R.id.item_forwarding);
74 | mCommentNum = $(R.id.item_comment);
75 | mLikeNum = $(R.id.item_like);
76 |
77 | }
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/cnsunrun/debugdemo/mvp/ui/adapter/base/AbsRecyclerViewAdapter.java:
--------------------------------------------------------------------------------
1 | package com.example.cnsunrun.debugdemo.mvp.ui.adapter.base;
2 |
3 | import android.content.Context;
4 | import android.support.annotation.IdRes;
5 | import android.support.v7.widget.RecyclerView;
6 | import android.view.View;
7 |
8 | import java.util.List;
9 |
10 |
11 | public abstract class AbsRecyclerViewAdapter
12 | extends RecyclerView.Adapter {
13 |
14 | private Context context;
15 |
16 | public List mDataSources;
17 |
18 | private OnItemClickListener itemClickListener;
19 |
20 | private OnItemLongClickListener itemLongClickListener;
21 |
22 |
23 | public void setOnItemClickListener(OnItemClickListener listener) {
24 |
25 | this.itemClickListener = listener;
26 | }
27 |
28 |
29 | public void setOnItemLongClickListener(OnItemLongClickListener listener) {
30 |
31 | this.itemLongClickListener = listener;
32 | }
33 |
34 |
35 | /**
36 | * 设置RecyclerView数据源
37 | */
38 | public void setDataSources(List dataSources) {
39 |
40 | this.mDataSources = dataSources;
41 | }
42 |
43 |
44 | /**
45 | * 设置RecyclerView的count
46 | */
47 | @Override
48 | public int getItemCount() {
49 |
50 | return mDataSources == null ? 0 : mDataSources.size();
51 | }
52 |
53 |
54 | /**
55 | * 设置Context
56 | */
57 | public void bindContext(Context context) {
58 |
59 | this.context = context;
60 | }
61 |
62 |
63 | /**
64 | * 获取Context
65 | */
66 | public Context getContext() {
67 |
68 | return this.context;
69 | }
70 |
71 |
72 | /**
73 | * 重写onBindViewHolder设置item的点击和长按事件的监听
74 | */
75 | @Override
76 | public void onBindViewHolder(final ClickableViewHolder holder, final int position) {
77 |
78 | holder.getParentView().setOnClickListener(new View.OnClickListener() {
79 | @Override
80 | public void onClick(View v) {
81 | if (itemClickListener != null) {
82 | itemClickListener.onItemClick(position, holder);
83 | }
84 | }
85 | });
86 | }
87 |
88 |
89 | /**
90 | * Item点击事件接口
91 | */
92 | public interface OnItemClickListener {
93 |
94 | void onItemClick(int position, ClickableViewHolder holder);
95 | }
96 |
97 | /**
98 | * Item长按事件接口
99 | */
100 | public interface OnItemLongClickListener {
101 |
102 | boolean onItemLongClick(int position, ClickableViewHolder holder);
103 | }
104 |
105 | public static class ClickableViewHolder extends RecyclerView.ViewHolder {
106 |
107 | private View parentView;
108 |
109 |
110 | public ClickableViewHolder(View itemView) {
111 |
112 | super(itemView);
113 | this.parentView = itemView;
114 | }
115 |
116 |
117 | public View getParentView() {
118 |
119 | return parentView;
120 | }
121 |
122 |
123 | @SuppressWarnings("unchecked")
124 | public T $(@IdRes int id) {
125 |
126 | return (T) parentView.findViewById(id);
127 | }
128 | }
129 | }
130 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/cnsunrun/debugdemo/mvp/ui/adapter/base/EndlessRecyclerOnScrollListener.java:
--------------------------------------------------------------------------------
1 | package com.example.cnsunrun.debugdemo.mvp.ui.adapter.base;
2 |
3 | import android.support.v7.widget.LinearLayoutManager;
4 | import android.support.v7.widget.RecyclerView;
5 |
6 | /**
7 | * Created by cnsunrun on 2017/4/24.
8 | */
9 |
10 | public abstract class EndlessRecyclerOnScrollListener extends RecyclerView.OnScrollListener {
11 |
12 | private int previousTotal = 0;
13 |
14 | private boolean loading = true;
15 |
16 | private int currentPage = 1;
17 |
18 | private LinearLayoutManager mLinearLayoutManager;
19 |
20 |
21 | protected EndlessRecyclerOnScrollListener(LinearLayoutManager linearLayoutManager) {
22 |
23 | this.mLinearLayoutManager = linearLayoutManager;
24 | }
25 |
26 |
27 | @Override
28 | public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
29 |
30 | super.onScrolled(recyclerView, dx, dy);
31 |
32 | if (dy == 0) {
33 | return;
34 | }
35 |
36 | int visibleItemCount = recyclerView.getChildCount();
37 | int totalItemCount = mLinearLayoutManager.getItemCount();
38 | int lastCompletelyVisiableItemPosition
39 | = mLinearLayoutManager.findLastCompletelyVisibleItemPosition();
40 |
41 | if (loading) {
42 | if (totalItemCount > previousTotal) {
43 | loading = false;
44 | previousTotal = totalItemCount;
45 | }
46 | }
47 |
48 | if (!loading && (visibleItemCount > 0) &&
49 | (lastCompletelyVisiableItemPosition >= totalItemCount - 1)) {
50 | currentPage++;
51 | onLoadMore(currentPage);
52 | loading = true;
53 | }
54 | }
55 |
56 |
57 | public void refresh() {
58 |
59 | loading = true;
60 | previousTotal = 0;
61 | currentPage = 1;
62 | }
63 |
64 |
65 | public abstract void onLoadMore(int currentPage);
66 | }
67 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/cnsunrun/debugdemo/mvp/ui/adapter/base/HeaderViewRecyclerAdapter.java:
--------------------------------------------------------------------------------
1 | package com.example.cnsunrun.debugdemo.mvp.ui.adapter.base;
2 |
3 | import android.support.v7.widget.RecyclerView;
4 | import android.view.View;
5 | import android.view.ViewGroup;
6 |
7 | import java.util.ArrayList;
8 | import java.util.HashMap;
9 | import java.util.List;
10 | import java.util.Map;
11 |
12 | /**
13 | * Created by hcc on 16/8/7 21:18
14 | * 100332338@qq.com
15 | *
16 | * RecyclerView添加HeadAndFoot辅助类
17 | */
18 | public class HeaderViewRecyclerAdapter extends RecyclerView.Adapter {
19 |
20 | private static final int HEADERS_START = Integer.MIN_VALUE;
21 |
22 | private static final int FOOTERS_START = Integer.MIN_VALUE + 10;
23 |
24 | private static final int ITEMS_START = Integer.MIN_VALUE + 20;
25 |
26 | private static final int ADAPTER_MAX_TYPES = 100;
27 |
28 | private RecyclerView.Adapter mWrappedAdapter;
29 |
30 | private List mHeaderViews, mFooterViews;
31 |
32 | private Map mItemTypesOffset;
33 |
34 |
35 | public HeaderViewRecyclerAdapter(RecyclerView.Adapter adapter) {
36 |
37 | mHeaderViews = new ArrayList<>();
38 | mFooterViews = new ArrayList<>();
39 | mItemTypesOffset = new HashMap<>();
40 | setWrappedAdapter(adapter);
41 | }
42 |
43 |
44 | public void setAdapter(RecyclerView.Adapter adapter) {
45 |
46 | if (mWrappedAdapter != null && mWrappedAdapter.getItemCount() > 0) {
47 | notifyItemRangeRemoved(getHeaderCount(), mWrappedAdapter.getItemCount());
48 | }
49 | setWrappedAdapter(adapter);
50 | notifyItemRangeInserted(getHeaderCount(), mWrappedAdapter.getItemCount());
51 | }
52 |
53 |
54 | @Override
55 | public int getItemViewType(int position) {
56 |
57 | int hCount = getHeaderCount();
58 | if (position < hCount) {
59 | return HEADERS_START + position;
60 | } else {
61 | int itemCount = mWrappedAdapter.getItemCount();
62 | if (position < hCount + itemCount) {
63 | return getAdapterTypeOffset() + mWrappedAdapter.getItemViewType(position - hCount);
64 | } else {
65 | return FOOTERS_START + position - hCount - itemCount;
66 | }
67 | }
68 | }
69 |
70 |
71 | @Override
72 | public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
73 |
74 | if (viewType < HEADERS_START + getHeaderCount()) {
75 | return new StaticViewHolder(mHeaderViews.get(viewType - HEADERS_START));
76 | } else if (viewType < FOOTERS_START + getFooterCount()) {
77 | return new StaticViewHolder(mFooterViews.get(viewType - FOOTERS_START));
78 | } else {
79 | return mWrappedAdapter.onCreateViewHolder(viewGroup, viewType - getAdapterTypeOffset());
80 | }
81 | }
82 |
83 |
84 | @Override
85 | public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
86 |
87 | int hCount = getHeaderCount();
88 | if (position >= hCount && position < hCount + mWrappedAdapter.getItemCount()) {
89 | mWrappedAdapter.onBindViewHolder(viewHolder, position - hCount);
90 | }
91 | }
92 |
93 |
94 | public void addHeaderView(View view) {
95 |
96 | mHeaderViews.add(view);
97 | }
98 |
99 |
100 | public void addFooterView(View view) {
101 |
102 | mFooterViews.add(view);
103 | }
104 |
105 |
106 | public void removeHeadView() {
107 |
108 | mHeaderViews.clear();
109 | }
110 |
111 |
112 | public void removeFootView() {
113 | mFooterViews.clear();
114 | }
115 |
116 |
117 | @Override
118 | public int getItemCount() {
119 |
120 | return getHeaderCount() + getFooterCount() + getWrappedItemCount();
121 | }
122 |
123 |
124 | private int getWrappedItemCount() {
125 |
126 | return mWrappedAdapter.getItemCount();
127 | }
128 |
129 |
130 | private int getHeaderCount() {
131 |
132 | return mHeaderViews.size();
133 | }
134 |
135 |
136 | private int getFooterCount() {
137 |
138 | return mFooterViews.size();
139 | }
140 |
141 |
142 | private void setWrappedAdapter(RecyclerView.Adapter adapter) {
143 |
144 | if (mWrappedAdapter != null) mWrappedAdapter.unregisterAdapterDataObserver(mDataObserver);
145 | mWrappedAdapter = adapter;
146 | Class adapterClass = mWrappedAdapter.getClass();
147 | if (!mItemTypesOffset.containsKey(adapterClass)) putAdapterTypeOffset(adapterClass);
148 | mWrappedAdapter.registerAdapterDataObserver(mDataObserver);
149 | }
150 |
151 |
152 | private void putAdapterTypeOffset(Class adapterClass) {
153 |
154 | mItemTypesOffset.put(adapterClass, ITEMS_START + mItemTypesOffset.size() * ADAPTER_MAX_TYPES);
155 | }
156 |
157 |
158 | private int getAdapterTypeOffset() {
159 |
160 | return mItemTypesOffset.get(mWrappedAdapter.getClass());
161 | }
162 |
163 |
164 | private RecyclerView.AdapterDataObserver mDataObserver = new RecyclerView.AdapterDataObserver() {
165 |
166 | @Override
167 | public void onChanged() {
168 |
169 | super.onChanged();
170 | notifyDataSetChanged();
171 | }
172 |
173 |
174 | @Override
175 | public void onItemRangeChanged(int positionStart, int itemCount) {
176 |
177 | super.onItemRangeChanged(positionStart, itemCount);
178 | notifyItemRangeChanged(positionStart + getHeaderCount(), itemCount);
179 | }
180 |
181 |
182 | @Override
183 | public void onItemRangeInserted(int positionStart, int itemCount) {
184 |
185 | super.onItemRangeInserted(positionStart, itemCount);
186 | notifyItemRangeInserted(positionStart + getHeaderCount(), itemCount);
187 | }
188 |
189 |
190 | @Override
191 | public void onItemRangeRemoved(int positionStart, int itemCount) {
192 |
193 | super.onItemRangeRemoved(positionStart, itemCount);
194 | notifyItemRangeRemoved(positionStart + getHeaderCount(), itemCount);
195 | }
196 |
197 |
198 | @Override
199 | public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
200 |
201 | super.onItemRangeMoved(fromPosition, toPosition, itemCount);
202 | int hCount = getHeaderCount();
203 | // TODO: No notifyItemRangeMoved method?
204 | notifyItemRangeChanged(fromPosition + hCount, toPosition + hCount + itemCount);
205 | }
206 | };
207 |
208 | private static class StaticViewHolder extends RecyclerView.ViewHolder {
209 |
210 | StaticViewHolder(View itemView) {
211 |
212 | super(itemView);
213 | }
214 | }
215 | }
216 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/cnsunrun/debugdemo/mvp/ui/fragment/CommunityFragment.java:
--------------------------------------------------------------------------------
1 | package com.example.cnsunrun.debugdemo.mvp.ui.fragment;
2 |
3 | import android.os.Bundle;
4 | import android.support.annotation.Nullable;
5 | import android.support.v4.app.Fragment;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 |
10 | import com.example.cnsunrun.debugdemo.R;
11 |
12 | /**
13 | * Created by cnsunrun on 2017/4/19.
14 | */
15 |
16 | public class CommunityFragment extends Fragment {
17 |
18 |
19 | public static CommunityFragment newInstance() {
20 | return new CommunityFragment();
21 | }
22 |
23 | @Nullable
24 | @Override
25 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
26 | View view = inflater.inflate(R.layout.fragment_community, container, false);
27 | return view;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/cnsunrun/debugdemo/mvp/ui/fragment/CopyListFragment.java:
--------------------------------------------------------------------------------
1 | package com.example.cnsunrun.debugdemo.mvp.ui.fragment;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.support.annotation.Nullable;
6 | import android.support.v4.app.Fragment;
7 | import android.support.v4.widget.SwipeRefreshLayout;
8 | import android.support.v7.widget.LinearLayoutManager;
9 | import android.support.v7.widget.RecyclerView;
10 | import android.view.LayoutInflater;
11 | import android.view.View;
12 | import android.view.ViewGroup;
13 |
14 | import com.example.cnsunrun.debugdemo.DebugDemoApp;
15 | import com.example.cnsunrun.debugdemo.R;
16 | import com.example.cnsunrun.debugdemo.mvp.contract.CopyListContract;
17 | import com.example.cnsunrun.debugdemo.mvp.model.bean.CopyInfo;
18 | import com.example.cnsunrun.debugdemo.mvp.presenter.CopyListPresenter;
19 | import com.example.cnsunrun.debugdemo.mvp.ui.activity.CopyDetailsActivity;
20 | import com.example.cnsunrun.debugdemo.mvp.ui.activity.component.DaggerCopyListComponent;
21 | import com.example.cnsunrun.debugdemo.mvp.ui.activity.module.CopyListModule;
22 | import com.example.cnsunrun.debugdemo.mvp.ui.adapter.CopyAdapter;
23 | import com.github.nukc.LoadMoreWrapper.LoadMoreWrapper;
24 |
25 | import java.util.ArrayList;
26 | import java.util.List;
27 |
28 | import javax.inject.Inject;
29 |
30 | import butterknife.Bind;
31 | import butterknife.ButterKnife;
32 |
33 | /**
34 | * Created by cnsunrun on 2017/4/19.
35 | */
36 |
37 | public class CopyListFragment extends Fragment implements CopyListContract.View {
38 |
39 | @Bind(R.id.recycler_view)
40 | RecyclerView mRecyclerView;
41 | @Bind(R.id.swipe_refresh)
42 | SwipeRefreshLayout mSwipeRefreshLayout;
43 |
44 | @Inject
45 | CopyListPresenter copyListPresenter;
46 |
47 | private List datas = new ArrayList<>();
48 | private CopyAdapter mAdapter;
49 | private int page = 1;
50 |
51 | public static CopyListFragment newInstance() {
52 | return new CopyListFragment();
53 | }
54 |
55 |
56 | @Override
57 | public void onCreate(@Nullable Bundle savedInstanceState) {
58 | super.onCreate(savedInstanceState);
59 | DaggerCopyListComponent.builder()
60 | .applicationComponent(DebugDemoApp.getAppContext().getApplicationComponent())
61 | .copyListModule(new CopyListModule(this))
62 | .build().inject(this);
63 | }
64 |
65 | @Nullable
66 | @Override
67 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
68 | View view = inflater.inflate(R.layout.fragment_copy_list, container, false);
69 | ButterKnife.bind(this, view);
70 | initSwipeRefreshLayout();
71 | initRecyclerView();
72 | copyListPresenter.subscribe();
73 | return view;
74 | }
75 |
76 | private void initSwipeRefreshLayout() {
77 | mSwipeRefreshLayout.setColorSchemeResources(R.color.colorControlNormal);
78 | mSwipeRefreshLayout.setOnRefreshListener(() -> {
79 | datas.clear();
80 | copyListPresenter.loadData();
81 | });
82 | }
83 |
84 | private void initRecyclerView() {
85 | mRecyclerView.setHasFixedSize(true);
86 | mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
87 | mAdapter = new CopyAdapter();
88 | mRecyclerView.setAdapter(mAdapter);
89 | mAdapter.setOnItemClickListener((position, holder) -> {
90 | CopyInfo.ActivityoListBean activityoListBean = datas.get(position);
91 | Intent intent = new Intent(getActivity(), CopyDetailsActivity.class);
92 | intent.putExtra("activityId",activityoListBean.getActivityid());
93 | getActivity().startActivity(intent);
94 | });
95 | LoadMoreWrapper.with(mAdapter)
96 | .setFooterView(R.layout.layout_load_more)
97 | .setShowNoMoreEnabled(true)
98 | .setListener(enabled -> {
99 | page++;
100 | copyListPresenter.loadMoreData(page);
101 | }).into(mRecyclerView);
102 | }
103 |
104 | @Override
105 | public void setPresenter(CopyListContract.Presenter presenter) {
106 | }
107 |
108 | @Override
109 | public void displayData(List copyInfos) {
110 | mSwipeRefreshLayout.setRefreshing(false);
111 | datas.addAll(copyInfos);
112 | mAdapter.setDataSources(datas);
113 | mAdapter.notifyDataSetChanged();
114 |
115 | }
116 |
117 | @Override
118 | public void onDestroyView() {
119 | super.onDestroyView();
120 | ButterKnife.unbind(this);
121 | copyListPresenter.unSubscribe();
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/cnsunrun/debugdemo/mvp/ui/fragment/ImageDetailsFragment.java:
--------------------------------------------------------------------------------
1 | package com.example.cnsunrun.debugdemo.mvp.ui.fragment;
2 |
3 | import android.os.Bundle;
4 | import android.support.annotation.Nullable;
5 | import android.support.v4.app.Fragment;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 | import android.widget.ImageView;
10 |
11 | import com.bumptech.glide.Glide;
12 | import com.bumptech.glide.load.engine.DiskCacheStrategy;
13 | import com.bumptech.glide.load.resource.drawable.GlideDrawable;
14 | import com.bumptech.glide.request.RequestListener;
15 | import com.bumptech.glide.request.target.Target;
16 | import com.example.cnsunrun.debugdemo.R;
17 | import com.example.cnsunrun.debugdemo.widget.CircleProgressView;
18 |
19 | import butterknife.Bind;
20 | import butterknife.ButterKnife;
21 | import uk.co.senab.photoview.PhotoViewAttacher;
22 |
23 | /**
24 | * Created by cnsunrun on 2017/4/24.
25 | */
26 |
27 | public class ImageDetailsFragment extends Fragment implements RequestListener {
28 |
29 | @Bind(R.id.circle_progress)
30 | CircleProgressView mCircleProgressView;
31 |
32 | @Bind(R.id.iv_image_details)
33 | ImageView mImageView;
34 |
35 | private String url;
36 | private PhotoViewAttacher mPhotoViewAttacher;
37 |
38 | public static ImageDetailsFragment newInstance(String url) {
39 | ImageDetailsFragment fragment = new ImageDetailsFragment();
40 | Bundle bundle = new Bundle();
41 | bundle.putString("url", url);
42 | fragment.setArguments(bundle);
43 | return fragment;
44 | }
45 |
46 | @Nullable
47 | @Override
48 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
49 | View view = inflater.inflate(R.layout.fragment_image_details, container, false);
50 | ButterKnife.bind(this, view);
51 | url = getArguments().getString("url");
52 | initView();
53 | return view;
54 | }
55 |
56 | private void initView() {
57 | mCircleProgressView.setVisibility(View.VISIBLE);
58 | mCircleProgressView.spin();
59 |
60 | Glide.with(this).load(url)
61 | .diskCacheStrategy(DiskCacheStrategy.ALL)
62 | .crossFade(0)
63 | .listener(this)
64 | .into(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL);
65 | }
66 |
67 | @Override
68 | public boolean onException(Exception e, String model, Target target, boolean isFirstResource) {
69 | mCircleProgressView.setVisibility(View.GONE);
70 | mCircleProgressView.stopSpinning();
71 | return false;
72 | }
73 |
74 | @Override
75 | public boolean onResourceReady(GlideDrawable resource, String model, Target target, boolean isFromMemoryCache, boolean isFirstResource) {
76 | mCircleProgressView.setVisibility(View.GONE);
77 | mCircleProgressView.stopSpinning();
78 | mImageView.setImageDrawable(resource);
79 | mPhotoViewAttacher = new PhotoViewAttacher(mImageView);
80 | mPhotoViewAttacher.setOnViewTapListener((view, v, v1) -> getActivity().finish());
81 |
82 | return false;
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/cnsunrun/debugdemo/mvp/ui/fragment/MineFragment.java:
--------------------------------------------------------------------------------
1 | package com.example.cnsunrun.debugdemo.mvp.ui.fragment;
2 |
3 | import android.os.Bundle;
4 | import android.support.annotation.Nullable;
5 | import android.support.v4.app.Fragment;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 | import android.widget.TextView;
10 |
11 | import com.example.cnsunrun.debugdemo.R;
12 |
13 | /**
14 | * Created by cnsunrun on 2017/4/19.
15 | */
16 |
17 | public class MineFragment extends Fragment {
18 |
19 | public static MineFragment newInstance() {
20 | return new MineFragment();
21 | }
22 |
23 | @Nullable
24 | @Override
25 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
26 | View view = inflater.inflate(R.layout.fragment_mine, container, false);
27 | TextView mTextView = (TextView) view.findViewById(R.id.tv_test);
28 | mTextView.setOnClickListener(new View.OnClickListener() {
29 | @Override
30 | public void onClick(View v) {
31 |
32 | }
33 | });
34 | return view;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/cnsunrun/debugdemo/mvp/ui/fragment/QuanziListFragment.java:
--------------------------------------------------------------------------------
1 | package com.example.cnsunrun.debugdemo.mvp.ui.fragment;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.support.annotation.Nullable;
6 | import android.support.v4.app.Fragment;
7 | import android.support.v4.widget.SwipeRefreshLayout;
8 | import android.support.v7.widget.RecyclerView;
9 | import android.support.v7.widget.StaggeredGridLayoutManager;
10 | import android.view.LayoutInflater;
11 | import android.view.View;
12 | import android.view.ViewGroup;
13 |
14 | import com.example.cnsunrun.debugdemo.DebugDemoApp;
15 | import com.example.cnsunrun.debugdemo.R;
16 | import com.example.cnsunrun.debugdemo.mvp.contract.QuanziListContract;
17 | import com.example.cnsunrun.debugdemo.mvp.model.bean.QuanziInfo;
18 | import com.example.cnsunrun.debugdemo.mvp.presenter.QuanziListPresenter;
19 | import com.example.cnsunrun.debugdemo.mvp.ui.activity.QuanziDetailsActivity;
20 | import com.example.cnsunrun.debugdemo.mvp.ui.activity.component.DaggerQuanziListComponent;
21 | import com.example.cnsunrun.debugdemo.mvp.ui.activity.module.QuanziListModule;
22 | import com.example.cnsunrun.debugdemo.mvp.ui.adapter.QuanziAdapter;
23 | import com.github.nukc.LoadMoreWrapper.LoadMoreWrapper;
24 |
25 | import java.util.ArrayList;
26 | import java.util.List;
27 |
28 | import javax.inject.Inject;
29 |
30 | import butterknife.Bind;
31 | import butterknife.ButterKnife;
32 |
33 | /**
34 | * Created by cnsunrun on 2017/4/18.
35 | */
36 |
37 | public class QuanziListFragment extends Fragment implements QuanziListContract.View {
38 |
39 |
40 | @Bind(R.id.recycler_view)
41 | RecyclerView mRecyclerView;
42 | @Bind(R.id.swipe_refresh)
43 | SwipeRefreshLayout mSwipeRefreshLayout;
44 |
45 | @Inject
46 | QuanziListPresenter quanziListPresenter;
47 |
48 | private QuanziAdapter mAdapter;
49 | private List blogList = new ArrayList<>();
50 |
51 | public static QuanziListFragment newInstance() {
52 | return new QuanziListFragment();
53 | }
54 |
55 | @Override
56 | public void onCreate(@Nullable Bundle savedInstanceState) {
57 | super.onCreate(savedInstanceState);
58 |
59 | DaggerQuanziListComponent.builder()
60 | .applicationComponent(DebugDemoApp.getAppContext().getApplicationComponent())
61 | .quanziListModule(new QuanziListModule(this))
62 | .build().inject(this);
63 | }
64 |
65 | @Nullable
66 | @Override
67 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
68 | View view = inflater.inflate(R.layout.fragment_quanzi_list, container, false);
69 | ButterKnife.bind(this, view);
70 | initSwipeRefreshLayout();
71 | initRecyclerView();
72 | quanziListPresenter.subscribe();
73 | return view;
74 | }
75 |
76 | private void initSwipeRefreshLayout() {
77 | mSwipeRefreshLayout.setColorSchemeResources(R.color.colorControlNormal);
78 | mSwipeRefreshLayout.setOnRefreshListener(() -> {
79 | blogList.clear();
80 | quanziListPresenter.loadData();
81 | });
82 | }
83 |
84 | private void initRecyclerView() {
85 | mRecyclerView.setHasFixedSize(true);
86 | mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL));
87 | mAdapter = new QuanziAdapter();
88 | mRecyclerView.setAdapter(mAdapter);
89 | mAdapter.setOnItemClickListener((position, holder) -> {
90 | Intent intent = new Intent(getActivity(), QuanziDetailsActivity.class);
91 | intent.putExtra("id", blogList.get(position).getBlog_id());
92 | intent.putExtra("title",blogList.get(position).getContent());
93 | getActivity().startActivity(intent);
94 | });
95 | LoadMoreWrapper.with(mAdapter)
96 | .setFooterView(R.layout.layout_load_more)
97 | .setLoadMoreEnabled(true)
98 | .setListener(enabled -> {
99 | long lastId = -1;
100 | long hotLastId = -1;
101 | int size = blogList.size();
102 | if (size >= 2) {
103 | lastId = Long.valueOf(blogList.get(blogList.size() - 2).getBlog_id());
104 | hotLastId = Long.valueOf(blogList.get(blogList.size() - 1).getBlog_id());
105 | quanziListPresenter.loadMoreData(lastId, hotLastId);
106 | }
107 | })
108 | .into(mRecyclerView);
109 | }
110 |
111 | @Override
112 | public void setPresenter(QuanziListContract.Presenter presenter) {
113 | }
114 |
115 |
116 | @Override
117 | public void displayData(List quanziInfos) {
118 | mSwipeRefreshLayout.setRefreshing(false);
119 | blogList.addAll(quanziInfos);
120 | mAdapter.setDataSources(blogList);
121 | mAdapter.notifyDataSetChanged();
122 | }
123 |
124 | @Override
125 | public void onDestroyView() {
126 | super.onDestroyView();
127 | ButterKnife.unbind(this);
128 | quanziListPresenter.unSubscribe();
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/cnsunrun/debugdemo/utils/ActivityScoped.java:
--------------------------------------------------------------------------------
1 | package com.example.cnsunrun.debugdemo.utils;
2 |
3 | import java.lang.annotation.Documented;
4 | import java.lang.annotation.Retention;
5 | import java.lang.annotation.RetentionPolicy;
6 |
7 | import javax.inject.Scope;
8 |
9 |
10 | @Scope
11 | @Documented
12 | @Retention(RetentionPolicy.RUNTIME)
13 | public @interface ActivityScoped {
14 | }
15 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/cnsunrun/debugdemo/utils/ActivityUtils.java:
--------------------------------------------------------------------------------
1 | package com.example.cnsunrun.debugdemo.utils;
2 |
3 | import android.support.v4.app.Fragment;
4 | import android.support.v4.app.FragmentManager;
5 | import android.support.v4.app.FragmentTransaction;
6 |
7 | /**
8 | * Created by cnsunrun on 2017/4/18.
9 | */
10 |
11 | public class ActivityUtils {
12 |
13 | public static void addFragmentToActivity(FragmentManager fragmentManager, Fragment fragment, int frameId) {
14 | FragmentTransaction transaction = fragmentManager.beginTransaction();
15 | transaction.add(frameId, fragment);
16 | transaction.commit();
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/cnsunrun/debugdemo/utils/DisplayUtil.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Project Name: juju_android
3 | * Package Name: la.juju.android.util
4 | * File Name: DisplayUtil.java
5 | * Created Time: 2014-10-6 下午2:28:12
6 | * Copyright (c) 2014, imRock.juju.la All Rights Reserved.
7 | */
8 | package com.example.cnsunrun.debugdemo.utils;
9 |
10 | import android.content.Context;
11 | import android.content.res.Resources;
12 | import android.util.DisplayMetrics;
13 | import android.util.TypedValue;
14 | import android.view.Display;
15 | import android.view.WindowManager;
16 |
17 | import java.lang.reflect.Field;
18 |
19 | import static android.util.Log.w;
20 |
21 | /**
22 | * Utils for getting display metrics such as screen size, dp, sp and px...
23 | * depend on different user device.
24 | * This class is thread safe.
25 | *
26 | * @author imRock, *rockyoungljy@gmail.com*
27 | * @version DisplayUtil, v 0.1
28 | */
29 | public class DisplayUtil {
30 |
31 | private static final String DEBUG_TAG = DisplayUtil.class.getSimpleName();
32 |
33 | private static Context appContext;
34 |
35 | private static int screenWidth;
36 | private static int screenHeight;
37 |
38 | private static int statusBarHeight;
39 |
40 | private DisplayUtil() {
41 | }
42 |
43 | /**
44 | * If want to use the more convenient method like {@link #getScreenWidth()},
45 | * {@link #getScreenHeight()} and {@link #getStatusBarHeight()}, should call this
46 | * with application context before. it's good to initialize in the application's
47 | * onCreate call back.
48 | *
49 | * @param appContext must be application context for best practise
50 | */
51 | public synchronized static void init(Context appContext) {
52 | DisplayUtil.appContext = appContext;
53 | int[] size = getScreenSize(appContext);
54 | screenWidth = size[0];
55 | screenHeight = size[1];
56 | statusBarHeight = getStatusBarHeight(appContext);
57 | }
58 |
59 | /**
60 | * This method is guaranteed to get the proper screen width and height.
61 | *
62 | * @param context any activity or application context
63 | * @return the size with width and height pixels of screen
64 | */
65 | public synchronized static int[] getScreenSize(Context context) {
66 | final String name = Context.WINDOW_SERVICE;
67 | final Object service = context.getSystemService(name);
68 | final WindowManager wm = (WindowManager) service;
69 | final Display display = wm.getDefaultDisplay();
70 | final DisplayMetrics dm = new DisplayMetrics();
71 | display.getMetrics(dm);
72 | screenWidth = dm.widthPixels;
73 | screenHeight = dm.heightPixels;
74 | int[] size = new int[2];
75 | size[0] = screenWidth;
76 | size[1] = screenHeight;
77 | // Log.d("screenWidth of size[0]", String.valueOf(size[0]));
78 | // Log.d("screenHeight of size[1]", String.valueOf(size[1]));
79 | return size;
80 | }
81 |
82 | private static final String DIMEN_CLASS_NAME = "com.android.internal.R$dimen";
83 | private static final String SB_HEIGHT_FIELD_NAME = "status_bar_height";
84 |
85 | /**
86 | * Get the proper system status bar's height using reflection.
87 | *
88 | * @param context any activity or application context
89 | * @return the height in pixel of system status bar
90 | */
91 | public synchronized static int getStatusBarHeight(Context context) {
92 | try {
93 | final Class> theClass = Class.forName(DIMEN_CLASS_NAME);
94 | final Object classObj = theClass.newInstance();
95 | final Field field = theClass.getField(SB_HEIGHT_FIELD_NAME);
96 | final Object idObj = field.get(classObj);
97 | final String idStr = idObj.toString();
98 | final int id = Integer.parseInt(idStr);
99 | final Resources resources = context.getResources();
100 | statusBarHeight = resources.getDimensionPixelSize(id);
101 | } catch (Exception e) {
102 | e.printStackTrace();
103 | }
104 | // Log.d("statusBarHeight", String.valueOf(statusBarHeight));
105 | return statusBarHeight;
106 | }
107 |
108 | /**
109 | * Get the user device's screen width, the correctness is not guaranteed,
110 | * because it's depend on the calling sequence.
111 | * WARNING: Should calling {@link #init(Context)} or {@link #getScreenSize(Context)} before,
112 | * or you may get 0 as result.
113 | *
114 | * @return the pixel width of screen, return 0 if the call order is wrong
115 | */
116 | public synchronized static int getScreenWidth() {
117 | if (screenWidth == 0 && appContext != null) {
118 | int[] size = getScreenSize(appContext);
119 | screenWidth = size[0];
120 | screenHeight = size[1];
121 | }
122 | return screenWidth;
123 | }
124 |
125 | /**
126 | * Get the user device's screen height, the correctness is not guaranteed,
127 | * because it's depend on the calling sequence.
128 | * WARNING: Should calling {@link #init(Context)} or {@link #getScreenSize(Context)} before,
129 | * or you may get 0 as result.
130 | *
131 | * @return the pixel height of screen, return 0 if the call order is wrong
132 | */
133 | public synchronized static int getScreenHeight() {
134 | if (screenHeight == 0 && appContext != null) {
135 | int[] size = getScreenSize(appContext);
136 | screenWidth = size[0];
137 | screenHeight = size[1];
138 | }
139 | return screenHeight;
140 | }
141 |
142 | public synchronized static float getScreenRate() {
143 | if ((screenWidth == 0 || screenHeight == 0) && appContext != null) {
144 | int[] size = getScreenSize(appContext);
145 | screenWidth = size[0];
146 | screenHeight = size[1];
147 | }
148 | return (float) screenHeight / (float) screenWidth;
149 | }
150 |
151 | /**
152 | * Get the system status bar's height, the correctness is not guaranteed,
153 | * because it's depend on the calling sequence.
154 | * WARNING: Should calling {@link #init(Context)} or {@link #getStatusBarHeight(Context)} before,
155 | * or you may get 0 as result.
156 | *
157 | * @return the pixel height of system status bar, return 0 if the call order is wrong
158 | */
159 | public synchronized static int getStatusBarHeight() {
160 | if (statusBarHeight == 0 && appContext != null) {
161 | statusBarHeight = getStatusBarHeight(appContext);
162 | }
163 | return statusBarHeight;
164 | }
165 |
166 |
167 | private static final String WARNING_MSG0 = "Should call init(Context appContext) before this!";
168 | private static final String WARNING_MSG1 = "The result from this method is WRONG basically!";
169 |
170 | /**
171 | * Another way to convert dp(density-independent pixels) unit to equivalent px(pixels),
172 | * depending on device {@link DisplayMetrics}, using {@link TypedValue}.
173 | * This method is more recommended compared to {@link #convertDpToPx(float, Context)}.
174 | *
175 | * @param dp value in dp unit which will be converted into px
176 | * @param context context to get resources and device specific display metrics
177 | * @return a float value to represent px equivalent to dp
178 | */
179 | public synchronized static float dpToPx(float dp, Context context) {
180 | final Resources resources = context.getResources();
181 | final DisplayMetrics metrics = resources.getDisplayMetrics();
182 | final int unit = TypedValue.COMPLEX_UNIT_DIP;
183 | return TypedValue.applyDimension(unit, dp, metrics);
184 | }
185 |
186 | /**
187 | * Calling this instead of {@link #dpToPx(float, Context)} for convenience, ONLY
188 | * IF you have {@link #init(Context)} with the application context before.
189 | * WARNING: Will return the original value passed in by @param dp when calling
190 | * sequence is wrong!
191 | *
192 | * @param dp value in dp unit which will be converted into px
193 | * @return a float value to represent px equivalent to dp
194 | */
195 | public synchronized static float dpToPx(float dp) {
196 | if (appContext != null) {
197 | return dpToPx(dp, appContext);
198 | } else {
199 | w(DEBUG_TAG + ".dpToPx()", WARNING_MSG0);
200 | w(DEBUG_TAG + ".dpToPx()", WARNING_MSG1);
201 | return dp;
202 | }
203 | }
204 |
205 | /**
206 | * Convert dp(density-independent pixels) unit to equivalent px(pixels), depending on
207 | * device densityDpi of {@link DisplayMetrics}.
208 | *
209 | * @param dp value in dp unit which will be converted into px
210 | * @param context context to get resources and device specific display metrics
211 | * @return a float value to represent px equivalent to dp
212 | */
213 | public synchronized static float convertDpToPx(float dp, Context context) {
214 | Resources resources = context.getResources();
215 | DisplayMetrics metrics = resources.getDisplayMetrics();
216 | final int densityDpi = metrics.densityDpi;
217 | return dp * (densityDpi / 160f);
218 | }
219 |
220 | /**
221 | * Calling this instead of {@link #convertDpToPx(float, Context)} for convenience,
222 | * ONLY IF you have {@link #init(Context)} with the application context before.
223 | * WARNING: Will return the original value passed in by @param dp when calling
224 | * sequence is wrong!
225 | *
226 | * @param dp value in dp unit which will be converted into px
227 | * @return a float value to represent px equivalent to dp
228 | */
229 | public synchronized static float convertDpToPx(float dp) {
230 | if (appContext != null) {
231 | return convertDpToPx(dp, appContext);
232 | } else {
233 | w(DEBUG_TAG + ".convertDpToPixel()", WARNING_MSG0);
234 | w(DEBUG_TAG + ".convertDpToPixel()", WARNING_MSG1);
235 | return dp;
236 | }
237 | }
238 |
239 | /**
240 | * Convert px(pixels) unit to equivalent dp(density-independent pixels), depending on
241 | * device densityDpi of {@link DisplayMetrics}.
242 | *
243 | * @param px value in px unit which will be converted into dp
244 | * @param context context to get resources and device specific display metrics
245 | * @return a float value to represent dp equivalent to px
246 | */
247 | public synchronized static float convertPxToDp(float px, Context context) {
248 | Resources resources = context.getResources();
249 | DisplayMetrics metrics = resources.getDisplayMetrics();
250 | final int densityDpi = metrics.densityDpi;
251 | return px / (densityDpi / 160f);
252 | }
253 |
254 | /**
255 | * Calling this instead of {@link #convertPxToDp(float, Context)} for convenience,
256 | * ONLY IF you have {@link #init(Context)} with the application context before.
257 | * WARNING: Will return the original value passed in by @param px when calling
258 | * sequence is wrong!
259 | *
260 | * @param px value in px unit which will be converted into dp
261 | * @return a float value to represent dp equivalent to px
262 | */
263 | public synchronized static float convertPxToDp(float px) {
264 | if (appContext != null) {
265 | return convertPxToDp(px, appContext);
266 | } else {
267 | w(DEBUG_TAG + ".convertPixelsToDp()", WARNING_MSG0);
268 | w(DEBUG_TAG + ".convertPixelsToDp()", WARNING_MSG1);
269 | return px;
270 | }
271 | }
272 |
273 | /**
274 | * Convert sp(scale-independent pixels) unit to equivalent px(pixels), depending on
275 | * device scaledDensity of {@link DisplayMetrics}.
276 | *
277 | * @param sp value in sp unit which will be converted into px
278 | * @param context context to get resources and device specific display metrics
279 | * @return a float value to represent px equivalent to sp
280 | */
281 | public synchronized static float convertSpToPx(float sp, Context context) {
282 | final Resources resources = context.getResources();
283 | final DisplayMetrics metrics = resources.getDisplayMetrics();
284 | final float fontScale = metrics.scaledDensity;
285 | return sp * fontScale;
286 | }
287 |
288 | /**
289 | * Calling this instead of {@link #convertSpToPx(float, Context)} for convenience,
290 | * ONLY IF you have {@link #init(Context)} with the application context before.
291 | * WARNING: Will return the original value passed in by @param px when calling
292 | * sequence is wrong!
293 | *
294 | * @param sp value in sp unit which will be converted into px
295 | * @return a float value to represent px equivalent to sp
296 | */
297 | public synchronized static float convertSpToPx(float sp) {
298 | if (appContext != null) {
299 | return convertSpToPx(sp, appContext);
300 | } else {
301 | w(DEBUG_TAG + ".spToPx()", WARNING_MSG0);
302 | w(DEBUG_TAG + ".spToPx()", WARNING_MSG1);
303 | return sp;
304 | }
305 | }
306 |
307 | /**
308 | * Convert px(pixels) unit to equivalent sp(scale-independent pixels), depending on
309 | * device scaledDensity of {@link DisplayMetrics}.
310 | *
311 | * @param px value in px unit which will be converted into sp
312 | * @param context context to get resources and device specific display metrics
313 | * @return a float value to represent sp equivalent to px
314 | */
315 | public synchronized static float convertPxToSp(float px, Context context) {
316 | final Resources resources = context.getResources();
317 | final DisplayMetrics metrics = resources.getDisplayMetrics();
318 | final float fontScale = metrics.scaledDensity;
319 | return px / fontScale;
320 | }
321 |
322 | /**
323 | * Calling this instead of {@link #convertPxToSp(float, Context)} for convenience,
324 | * ONLY IF you have {@link #init(Context)} with the application context before.
325 | * WARNING: Will return the original value passed in by @param px when calling
326 | * sequence is wrong!
327 | *
328 | * @param px value in px unit which will be converted into sp
329 | * @return a float value to represent sp equivalent to px
330 | */
331 | public synchronized static float convertPxToSp(float px) {
332 | if (appContext != null) {
333 | return convertPxToSp(px, appContext);
334 | } else {
335 | w(DEBUG_TAG + ".pxToSp()", WARNING_MSG0);
336 | w(DEBUG_TAG + ".pxToSp()", WARNING_MSG1);
337 | return px;
338 | }
339 | }
340 |
341 | }
342 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/cnsunrun/debugdemo/utils/ImgUrlUtil.java:
--------------------------------------------------------------------------------
1 | package com.example.cnsunrun.debugdemo.utils;
2 |
3 | import android.text.TextUtils;
4 |
5 | import java.io.File;
6 |
7 |
8 | /**
9 | * Created by imRock on 15/6/30.
10 | * Under package la.juju.android.util.
11 | */
12 | public class ImgUrlUtil {
13 |
14 | public static String TOPIC_DOWNLOAD_BASE_URL = "http://juju.inbbuy.cn";
15 | public static String COMMENT_DOWNLOAD_BASE_URL = "http://juju1.inbbuy.cn";
16 | public static String AVATAR_DOWNLOAD_BASE_URL = "http://juju2.inbbuy.cn";
17 | public static String PIC_QUALITY_KEY = "pic_quality";
18 |
19 | public static int quality;
20 | public static final int LOW_QUALITY = 40;
21 | public static final int MIDDLE_QUALITY = 60;
22 | public static final int HIGH_QUALITY = 90;
23 |
24 | public enum QUALITY {
25 | L, // 40Q
26 | M, // 60Q
27 | H, // 80Q
28 | X, // 90Q
29 | O, // 100Q
30 | }
31 |
32 | private ImgUrlUtil() {
33 | }
34 |
35 | // public synchronized boolean isValidUrl() {
36 | //
37 | // }
38 |
39 | public enum AVATAR_NORMS {
40 | /**
41 | * 0dp < size < 36dp
42 | */
43 | SMALL,
44 | /**
45 | * 36dp <= size < 66dp
46 | */
47 | NORMAL,
48 | /**
49 | * 66dp < size
50 | */
51 | LARGE
52 | }
53 |
54 | public synchronized static String getAvatarImgUrl(String urlOrOssKey, float dpSize) {
55 | final StringBuilder sb = ossKeyToUrl(urlOrOssKey, IMG_TYPE.AVATAR);
56 | if (sb.length() == 0) {
57 | return sb.toString(); // TODO should return a default failure pic url
58 | }
59 | float realToGetDpSize;
60 | if (0f < dpSize && dpSize < 36f) {
61 | realToGetDpSize = 24f; // small
62 | } else if (36f <= dpSize && dpSize < 66f) {
63 | realToGetDpSize = 48f; // normal
64 | } else if (66f < dpSize) {
65 | realToGetDpSize = 84f; // large
66 | } else {
67 | realToGetDpSize = 48f; //normal
68 | }
69 | final float sizeFloat = DisplayUtil.dpToPx(realToGetDpSize);
70 | int size = resizeQuality((int) Math.ceil(sizeFloat), quality);
71 | sb.append("@");
72 | sb.append(size);
73 | sb.append("w_");
74 | sb.append(size);
75 | sb.append("h_");
76 | sb.append(quality);
77 | sb.append("Q_");
78 | sb.append("2o_");
79 | sb.append("1e_1c.src");// 按短边缩放并自动中间裁减
80 | return sb.toString();
81 | }
82 |
83 | public synchronized static String getAvatarImgUrl(String urlOrOssKey) {
84 | final StringBuilder sb = ossKeyToUrl(urlOrOssKey, IMG_TYPE.AVATAR);
85 | if (sb.length() == 0) {
86 | return sb.toString(); // TODO should return a default failure pic url
87 | }
88 | return sb.toString();
89 | }
90 |
91 |
92 | public synchronized static String getTopicImgUrlInWaterFlow(String urlOrOssKey, int pxh) {
93 | // final StringBuilder sb = ossKeyToUrl(urlOrOssKey, IMG_TYPE.TOPIC);
94 | // if (sb.length() == 0) {
95 | // return sb.toString(); // TODO should return a default failure pic url
96 | // }
97 | final int screenWidth = DisplayUtil.getScreenWidth();
98 | final float gapsDp = 33.75f;
99 | final float gapsPx = DisplayUtil.dpToPx(gapsDp);
100 | final int pxw = (int) Math.ceil((screenWidth - gapsPx) / 2f);
101 | int heightC = (int) Math.ceil(((double) pxw * 1.5));
102 | if (pxh > 0)
103 | if (pxh > heightC) {
104 | pxh = heightC;
105 | }
106 | return getTopicImgUrl(urlOrOssKey, pxw, pxh);
107 | // sb.append("@");
108 | // sb.append(pxw);
109 | // sb.append("w_");
110 | // sb.append(quality);
111 | // sb.append("Q_");
112 | // sb.append("1l.jpg");// 如果目标缩略图大于原图不处理
113 | // return sb.toString();
114 | }
115 |
116 | public synchronized static String getTopicImgUrl(String urlOrOssKey) {
117 | final StringBuilder sb = ossKeyToUrl(urlOrOssKey, IMG_TYPE.TOPIC);
118 | if (sb.length() == 0) {
119 | return sb.toString(); // TODO should return a default failure pic url
120 | }
121 | return sb.toString();
122 | }
123 |
124 | public synchronized static String getTopicImgUrl(String urlOrOssKey, int pxw) {
125 | final StringBuilder sb = ossKeyToUrl(urlOrOssKey, IMG_TYPE.TOPIC);
126 | if (sb.length() == 0) {
127 | return sb.toString(); // TODO should return a default failure pic url
128 | }
129 | sb.append("@");
130 | sb.append(resizeQuality(pxw, quality));
131 | sb.append("w_");
132 | sb.append(quality);
133 | sb.append("Q_");
134 | sb.append("2o_");
135 | sb.append("1l.src");// 如果目标缩略图大于原图不处理
136 | return sb.toString();
137 | }
138 |
139 | public synchronized static String getTopicSourceImgUrl(String urlOrOssKey) {
140 | final StringBuilder sb = ossKeyToUrl(urlOrOssKey, IMG_TYPE.TOPIC);
141 | if (sb.length() == 0) {
142 | return sb.toString(); // TODO should return a default failure pic url
143 | }
144 | sb.append("@");
145 | sb.append(DisplayUtil.getScreenWidth());
146 | sb.append("w_");
147 | sb.append(100);
148 | sb.append("Q_");
149 | sb.append("2o_");
150 | sb.append("1l.src");// 如果目标缩略图大于原图不处理
151 | return sb.toString();
152 | }
153 |
154 | public synchronized static String getAvatarSourceImgUrl(String urlOrOssKey) {
155 | final StringBuilder sb = ossKeyToUrl(urlOrOssKey, IMG_TYPE.AVATAR);
156 | if (sb.length() == 0) {
157 | return sb.toString(); // TODO should return a default failure pic url
158 | }
159 | sb.append("@");
160 | sb.append(DisplayUtil.getScreenWidth());
161 | sb.append("w_");
162 | sb.append(100);
163 | sb.append("Q_");
164 | sb.append("2o_");
165 | sb.append("1l.src");// 如果目标缩略图大于原图不处理
166 | return sb.toString();
167 | }
168 |
169 | public synchronized static String getCommentSourceImgUrl(String urlOrOssKey) {
170 | final StringBuilder sb = ossKeyToUrl(urlOrOssKey, IMG_TYPE.COMMENT);
171 | if (sb.length() == 0) {
172 | return sb.toString(); // TODO should return a default failure pic url
173 | }
174 | sb.append("@");
175 | sb.append(DisplayUtil.getScreenWidth());
176 | sb.append("w_");
177 | sb.append(100);
178 | sb.append("Q_");
179 | sb.append("2o_");
180 | sb.append("1l.src");// 如果目标缩略图大于原图不处理
181 | return sb.toString();
182 | }
183 |
184 | public synchronized static String getEventImgUrl(String urlOrOssKey, int pxw, int pxh) {
185 | final StringBuilder sb = ossKeyToUrl(urlOrOssKey, IMG_TYPE.AVATAR);
186 | if (sb.length() == 0) {
187 | return sb.toString(); // TODO should return a default failure pic url
188 | }
189 | sb.append("@");
190 | sb.append(resizeQuality(pxw, quality));
191 | sb.append("w_");
192 | sb.append(resizeQuality(pxh, quality));
193 | sb.append("h_");
194 | sb.append(quality);
195 | sb.append("Q_");
196 | sb.append("2o_");
197 | sb.append("1l_1c.src");// 自动中间裁减, 如果目标缩略图大于原图不处理
198 | return sb.toString();
199 | }
200 |
201 |
202 | public synchronized static String getTopicImgUrl(String urlOrOssKey, int pxw, int pxh) {
203 | final StringBuilder sb = ossKeyToUrl(urlOrOssKey, IMG_TYPE.TOPIC);
204 | if (sb.length() == 0) {
205 | return sb.toString(); // TODO should return a default failure pic url
206 | }
207 | sb.append("@");
208 | sb.append(resizeQuality(pxw, quality));
209 | sb.append("w_");
210 | sb.append(resizeQuality(pxh, quality));
211 | sb.append("h_");
212 | sb.append(quality);
213 | sb.append("Q_");
214 | sb.append("2o_");
215 | sb.append("1l_1c.src");// 自动中间裁减, 如果目标缩略图大于原图不处理
216 | return sb.toString();
217 | }
218 |
219 | public synchronized static String getMomentTopicImgUrl(String urlOrOssKey, int pxw, int pxh) {
220 | final StringBuilder sb = ossKeyToUrl(urlOrOssKey, IMG_TYPE.TOPIC);
221 | if (sb.length() == 0) {
222 | return sb.toString(); // TODO should return a default failure pic url
223 | }
224 | sb.append("@");
225 | sb.append(resizeQuality(pxw, quality));
226 | sb.append("w_");
227 | sb.append(resizeQuality(pxh, quality));
228 | sb.append("h_");
229 | sb.append(quality);
230 | sb.append("Q_");
231 | sb.append("2o_");
232 | sb.append("1l.src");// 如果目标缩略图大于原图不处理
233 | return sb.toString();
234 | }
235 |
236 |
237 | public synchronized static String getCommentImgUrl(String urlOrOssKey, int pxw, int pxh) {
238 | final StringBuilder sb = ossKeyToUrl(urlOrOssKey, IMG_TYPE.COMMENT);
239 | if (sb.length() == 0) {
240 | return sb.toString(); // TODO should return a default failure pic url
241 | }
242 | sb.append("@");
243 | sb.append(resizeQuality(pxw, quality));
244 | sb.append("w_");
245 | sb.append(resizeQuality(pxh, quality));
246 | sb.append("h_");
247 | sb.append(quality);
248 | sb.append("Q_");
249 | sb.append("2o_");
250 | sb.append("1l_1c.src");// 自动中间裁减, 如果目标缩略图大于原图不处理
251 | return sb.toString();
252 | }
253 |
254 | public synchronized static String getCommentImgUrl(String urlOrOssKey, int pxw) {
255 | final StringBuilder sb = ossKeyToUrl(urlOrOssKey, IMG_TYPE.COMMENT);
256 | if (sb.length() == 0) {
257 | return sb.toString(); // TODO should return a default failure pic url
258 | }
259 | sb.append("@");
260 | sb.append(resizeQuality(pxw, quality));
261 | sb.append("w_");
262 | sb.append(quality);
263 | sb.append("Q_");
264 | sb.append("2o_");
265 | sb.append("1l.src");// 如果目标缩略图大于原图不处理
266 | return sb.toString();
267 | }
268 |
269 | public synchronized static String getCommentImgUrl(String urlOrOssKey) {
270 | final StringBuilder sb = ossKeyToUrl(urlOrOssKey, IMG_TYPE.COMMENT);
271 | if (sb.length() == 0) {
272 | return sb.toString(); // TODO should return a default failure pic url
273 | }
274 | return sb.toString();
275 | }
276 |
277 | public enum IMG_TYPE {
278 | AVATAR, TOPIC, COMMENT
279 | }
280 |
281 | private static int resizeQuality(int size, int quality) {
282 | switch (quality) {
283 | case LOW_QUALITY:
284 | size = size / 2;
285 | break;
286 | case MIDDLE_QUALITY:
287 | size = (int) (size / 1.5);
288 | break;
289 | case HIGH_QUALITY:
290 | break;
291 | }
292 | return size;
293 | }
294 |
295 |
296 | public synchronized static String getImgUrl(String urlOrOssKey, IMG_TYPE type, boolean isOrigin) {
297 | if (type==null){
298 | return urlOrOssKey;
299 | }
300 | switch (type) {
301 | case AVATAR:
302 | return isOrigin ? getAvatarImgUrl(urlOrOssKey) : getAvatarSourceImgUrl(urlOrOssKey);
303 | case TOPIC:
304 | return isOrigin ? getTopicImgUrl(urlOrOssKey) : getTopicSourceImgUrl(urlOrOssKey);
305 | case COMMENT:
306 | return isOrigin ? getCommentImgUrl(urlOrOssKey) : getCommentSourceImgUrl(urlOrOssKey);
307 | default:
308 | return "";
309 | }
310 | }
311 |
312 | // 兼容老板版数据
313 | public synchronized static StringBuilder ossKeyToUrl(String urlOrOssKey, IMG_TYPE type) {
314 | final StringBuilder sb = new StringBuilder();
315 | if (TextUtils.isEmpty(urlOrOssKey)) {
316 | return sb;
317 | }
318 | if (urlOrOssKey.startsWith("http")) {
319 | sb.append(urlOrOssKey);
320 | } else {
321 | switch (type) {
322 | case AVATAR:
323 | sb.append(AVATAR_DOWNLOAD_BASE_URL);
324 | break;
325 | case TOPIC:
326 | sb.append(TOPIC_DOWNLOAD_BASE_URL);
327 | break;
328 | case COMMENT:
329 | sb.append(COMMENT_DOWNLOAD_BASE_URL);
330 | break;
331 | }
332 | final String fs = File.separator;
333 | final int p = urlOrOssKey.indexOf(fs);
334 | if (0 != p) {
335 | sb.append(fs);
336 | }
337 | sb.append(urlOrOssKey);
338 | }
339 | return sb;
340 | }
341 |
342 | }
343 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/cnsunrun/debugdemo/widget/CircleImageView.java:
--------------------------------------------------------------------------------
1 | package com.example.cnsunrun.debugdemo.widget;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.content.Context;
5 | import android.content.res.TypedArray;
6 | import android.graphics.Bitmap;
7 | import android.graphics.BitmapShader;
8 | import android.graphics.Canvas;
9 | import android.graphics.Color;
10 | import android.graphics.ColorFilter;
11 | import android.graphics.Matrix;
12 | import android.graphics.Paint;
13 | import android.graphics.RectF;
14 | import android.graphics.Shader;
15 | import android.graphics.drawable.BitmapDrawable;
16 | import android.graphics.drawable.ColorDrawable;
17 | import android.graphics.drawable.Drawable;
18 | import android.net.Uri;
19 | import android.support.annotation.ColorRes;
20 | import android.support.annotation.DrawableRes;
21 | import android.util.AttributeSet;
22 | import android.widget.ImageView;
23 |
24 | import com.example.cnsunrun.debugdemo.R;
25 |
26 | /**
27 | * Created by hcc on 16/8/7 21:18
28 | * 100332338@qq.com
29 | *
30 | * 圆形头像
31 | */
32 | @SuppressLint("AppCompatCustomView")
33 | public class CircleImageView extends ImageView {
34 |
35 | private static final ScaleType SCALE_TYPE = ScaleType.CENTER_CROP;
36 |
37 | private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888;
38 |
39 | private static final int COLORDRAWABLE_DIMENSION = 2;
40 |
41 | private static final int DEFAULT_BORDER_WIDTH = 0;
42 |
43 | private static final int DEFAULT_BORDER_COLOR = Color.BLACK;
44 |
45 | private static final boolean DEFAULT_BORDER_OVERLAY = false;
46 |
47 | private final RectF mDrawableRect = new RectF();
48 |
49 | private final RectF mBorderRect = new RectF();
50 |
51 | private final Matrix mShaderMatrix = new Matrix();
52 |
53 | private final Paint mBitmapPaint = new Paint();
54 |
55 | private final Paint mBorderPaint = new Paint();
56 |
57 | private int mBorderColor = DEFAULT_BORDER_COLOR;
58 |
59 | private int mBorderWidth = DEFAULT_BORDER_WIDTH;
60 |
61 | private Bitmap mBitmap;
62 |
63 | private BitmapShader mBitmapShader;
64 |
65 | private int mBitmapWidth;
66 |
67 | private int mBitmapHeight;
68 |
69 | private float mDrawableRadius;
70 |
71 | private float mBorderRadius;
72 |
73 | private ColorFilter mColorFilter;
74 |
75 | private boolean mReady;
76 |
77 | private boolean mSetupPending;
78 |
79 | private boolean mBorderOverlay;
80 |
81 |
82 | public CircleImageView(Context context) {
83 |
84 | super(context);
85 |
86 | init();
87 | }
88 |
89 |
90 | public CircleImageView(Context context, AttributeSet attrs) {
91 |
92 | this(context, attrs, 0);
93 | }
94 |
95 |
96 | public CircleImageView(Context context, AttributeSet attrs, int defStyle) {
97 |
98 | super(context, attrs, defStyle);
99 |
100 | TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView, defStyle, 0);
101 |
102 | mBorderWidth = a.getDimensionPixelSize(R.styleable.CircleImageView_border_width,
103 | DEFAULT_BORDER_WIDTH);
104 | mBorderColor = a.getColor(R.styleable.CircleImageView_border_color, DEFAULT_BORDER_COLOR);
105 | mBorderOverlay = a.getBoolean(R.styleable.CircleImageView_border_overlay,
106 | DEFAULT_BORDER_OVERLAY);
107 |
108 | a.recycle();
109 |
110 | init();
111 | }
112 |
113 |
114 | private void init() {
115 |
116 | super.setScaleType(SCALE_TYPE);
117 | mReady = true;
118 |
119 | if (mSetupPending) {
120 | setup();
121 | mSetupPending = false;
122 | }
123 | }
124 |
125 |
126 | @Override
127 | public ScaleType getScaleType() {
128 |
129 | return SCALE_TYPE;
130 | }
131 |
132 |
133 | @Override
134 | public void setScaleType(ScaleType scaleType) {
135 |
136 | if (scaleType != SCALE_TYPE) {
137 | throw new IllegalArgumentException(String.format("ScaleType %s not supported.", scaleType));
138 | }
139 | }
140 |
141 |
142 | @Override
143 | public void setAdjustViewBounds(boolean adjustViewBounds) {
144 |
145 | if (adjustViewBounds) {
146 | throw new IllegalArgumentException("adjustViewBounds not supported.");
147 | }
148 | }
149 |
150 |
151 | @Override
152 | protected void onDraw(Canvas canvas) {
153 |
154 | if (getDrawable() == null) {
155 | return;
156 | }
157 |
158 | canvas.drawCircle(getWidth() / 2, getHeight() / 2, mDrawableRadius, mBitmapPaint);
159 | if (mBorderWidth != 0) {
160 | canvas.drawCircle(getWidth() / 2, getHeight() / 2, mBorderRadius, mBorderPaint);
161 | }
162 | }
163 |
164 |
165 | @Override
166 | protected void onSizeChanged(int w, int h, int oldw, int oldh) {
167 |
168 | super.onSizeChanged(w, h, oldw, oldh);
169 | setup();
170 | }
171 |
172 |
173 | public int getBorderColor() {
174 |
175 | return mBorderColor;
176 | }
177 |
178 |
179 | public void setBorderColor(int borderColor) {
180 |
181 | if (borderColor == mBorderColor) {
182 | return;
183 | }
184 |
185 | mBorderColor = borderColor;
186 | mBorderPaint.setColor(mBorderColor);
187 | invalidate();
188 | }
189 |
190 |
191 | public void setBorderColorResource(@ColorRes int borderColorRes) {
192 |
193 | setBorderColor(getContext().getResources().getColor(borderColorRes));
194 | }
195 |
196 |
197 | public int getBorderWidth() {
198 |
199 | return mBorderWidth;
200 | }
201 |
202 |
203 | public void setBorderWidth(int borderWidth) {
204 |
205 | if (borderWidth == mBorderWidth) {
206 | return;
207 | }
208 |
209 | mBorderWidth = borderWidth;
210 | setup();
211 | }
212 |
213 |
214 | public boolean isBorderOverlay() {
215 |
216 | return mBorderOverlay;
217 | }
218 |
219 |
220 | public void setBorderOverlay(boolean borderOverlay) {
221 |
222 | if (borderOverlay == mBorderOverlay) {
223 | return;
224 | }
225 |
226 | mBorderOverlay = borderOverlay;
227 | setup();
228 | }
229 |
230 |
231 | @Override
232 | public void setImageBitmap(Bitmap bm) {
233 |
234 | super.setImageBitmap(bm);
235 | mBitmap = bm;
236 | setup();
237 | }
238 |
239 |
240 | @Override
241 | public void setImageDrawable(Drawable drawable) {
242 |
243 | super.setImageDrawable(drawable);
244 | mBitmap = getBitmapFromDrawable(drawable);
245 | setup();
246 | }
247 |
248 |
249 | @Override
250 | public void setImageResource(@DrawableRes int resId) {
251 |
252 | super.setImageResource(resId);
253 | mBitmap = getBitmapFromDrawable(getDrawable());
254 | setup();
255 | }
256 |
257 |
258 | @Override
259 | public void setImageURI(Uri uri) {
260 |
261 | super.setImageURI(uri);
262 | mBitmap = getBitmapFromDrawable(getDrawable());
263 | setup();
264 | }
265 |
266 |
267 | @Override
268 | public void setColorFilter(ColorFilter cf) {
269 |
270 | if (cf == mColorFilter) {
271 | return;
272 | }
273 |
274 | mColorFilter = cf;
275 | mBitmapPaint.setColorFilter(mColorFilter);
276 | invalidate();
277 | }
278 |
279 |
280 | private Bitmap getBitmapFromDrawable(Drawable drawable) {
281 |
282 | if (drawable == null) {
283 | return null;
284 | }
285 |
286 | if (drawable instanceof BitmapDrawable) {
287 | return ((BitmapDrawable) drawable).getBitmap();
288 | }
289 |
290 | try {
291 | Bitmap bitmap;
292 |
293 | if (drawable instanceof ColorDrawable) {
294 | bitmap = Bitmap.createBitmap(COLORDRAWABLE_DIMENSION, COLORDRAWABLE_DIMENSION,
295 | BITMAP_CONFIG);
296 | } else {
297 | bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(),
298 | BITMAP_CONFIG);
299 | }
300 |
301 | Canvas canvas = new Canvas(bitmap);
302 | drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
303 | drawable.draw(canvas);
304 | return bitmap;
305 | } catch (OutOfMemoryError e) {
306 | return null;
307 | }
308 | }
309 |
310 |
311 | private void setup() {
312 |
313 | if (!mReady) {
314 | mSetupPending = true;
315 | return;
316 | }
317 |
318 | if (mBitmap == null) {
319 | return;
320 | }
321 |
322 | mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
323 |
324 | mBitmapPaint.setAntiAlias(true);
325 | mBitmapPaint.setShader(mBitmapShader);
326 |
327 | mBorderPaint.setStyle(Paint.Style.STROKE);
328 | mBorderPaint.setAntiAlias(true);
329 | mBorderPaint.setColor(mBorderColor);
330 | mBorderPaint.setStrokeWidth(mBorderWidth);
331 |
332 | mBitmapHeight = mBitmap.getHeight();
333 | mBitmapWidth = mBitmap.getWidth();
334 |
335 | mBorderRect.set(0, 0, getWidth(), getHeight());
336 | mBorderRadius = Math.min((mBorderRect.height() - mBorderWidth) / 2,
337 | (mBorderRect.width() - mBorderWidth) / 2);
338 |
339 | mDrawableRect.set(mBorderRect);
340 | if (!mBorderOverlay) {
341 | mDrawableRect.inset(mBorderWidth, mBorderWidth);
342 | }
343 | mDrawableRadius = Math.min(mDrawableRect.height() / 2, mDrawableRect.width() / 2);
344 |
345 | updateShaderMatrix();
346 | invalidate();
347 | }
348 |
349 |
350 | private void updateShaderMatrix() {
351 |
352 | float scale;
353 | float dx = 0;
354 | float dy = 0;
355 |
356 | mShaderMatrix.set(null);
357 |
358 | if (mBitmapWidth * mDrawableRect.height() > mDrawableRect.width() * mBitmapHeight) {
359 | scale = mDrawableRect.height() / (float) mBitmapHeight;
360 | dx = (mDrawableRect.width() - mBitmapWidth * scale) * 0.5f;
361 | } else {
362 | scale = mDrawableRect.width() / (float) mBitmapWidth;
363 | dy = (mDrawableRect.height() - mBitmapHeight * scale) * 0.5f;
364 | }
365 |
366 | mShaderMatrix.setScale(scale, scale);
367 | mShaderMatrix.postTranslate((int) (dx + 0.5f) + mDrawableRect.left,
368 | (int) (dy + 0.5f) + mDrawableRect.top);
369 |
370 | mBitmapShader.setLocalMatrix(mShaderMatrix);
371 | }
372 | }
373 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/cnsunrun/debugdemo/widget/MomentPicView.java:
--------------------------------------------------------------------------------
1 | package com.example.cnsunrun.debugdemo.widget;
2 |
3 | import android.content.Context;
4 | import android.content.res.TypedArray;
5 | import android.graphics.Bitmap;
6 | import android.graphics.BitmapFactory;
7 | import android.graphics.BitmapShader;
8 | import android.graphics.Canvas;
9 | import android.graphics.Color;
10 | import android.graphics.Matrix;
11 | import android.graphics.Paint;
12 | import android.graphics.Rect;
13 | import android.graphics.RectF;
14 | import android.graphics.Shader;
15 | import android.util.AttributeSet;
16 | import android.view.MotionEvent;
17 | import android.view.View;
18 | import android.view.ViewConfiguration;
19 |
20 | import com.bumptech.glide.Glide;
21 | import com.bumptech.glide.load.engine.DiskCacheStrategy;
22 | import com.bumptech.glide.request.animation.GlideAnimation;
23 | import com.bumptech.glide.request.target.SimpleTarget;
24 | import com.bumptech.glide.request.target.Target;
25 | import com.example.cnsunrun.debugdemo.R;
26 | import com.example.cnsunrun.debugdemo.utils.DisplayUtil;
27 |
28 | import java.util.ArrayList;
29 | import java.util.Arrays;
30 | import java.util.Collection;
31 | import java.util.Collections;
32 |
33 |
34 |
35 |
36 | /**
37 | * Created by fan on 16/3/16.
38 | */
39 | public class MomentPicView extends View {
40 |
41 | private String[] mImageUrls;
42 | private Bitmap[] mBitmaps;
43 | private Bitmap mPlaceHolder;
44 | private int mHorizontalSpace = 10;
45 | private int mVerticalSpace = 10;
46 | private int mRadius = 0;
47 | private int mImageWidth = 0;
48 | private int mImageHeight = 0;
49 | private float mRatio = 1f;
50 | private int mColumns;
51 | private int mRows;
52 | private Matrix matrix = new Matrix();
53 | private final Paint mPaint = new Paint();
54 | private final Paint mTextPaint = new Paint();
55 | private final Paint mTextBgPaint = new Paint();
56 | private OnClickItemListener onClickItemListener;
57 | private MotionEvent mEventDown;
58 | private int mDown;
59 | private RectF[] mDrawRects;
60 | private boolean haveRule;//是否4列
61 | private Target[] mTargets = new Target[0];
62 |
63 |
64 | public MomentPicView(Context context) {
65 | this(context, null);
66 | }
67 |
68 | public MomentPicView(Context context, AttributeSet attrs) {
69 | this(context, attrs, 0);
70 | }
71 |
72 | public MomentPicView(Context context, AttributeSet attrs, int defStyleAttr) {
73 | super(context, attrs, defStyleAttr);
74 | if (attrs != null) {
75 | TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MomentPicView);
76 | try {
77 | for (int i = 0; i < a.getIndexCount(); i++) {
78 | int attr = a.getIndex(i);
79 | switch (attr) {
80 | case R.styleable.MomentPicView_mpvHorizontalSpace:
81 | mHorizontalSpace = a.getDimensionPixelSize(attr, mHorizontalSpace);
82 | break;
83 | case R.styleable.MomentPicView_mpvVerticalSpace:
84 | mVerticalSpace = a.getDimensionPixelSize(attr, mVerticalSpace);
85 | break;
86 | case R.styleable.MomentPicView_mpvRadius:
87 | mRadius = a.getDimensionPixelSize(attr, mRadius);
88 | break;
89 | case R.styleable.MomentPicView_mpvRatio:
90 | mRatio = a.getFloat(attr, mRatio);
91 | break;
92 | }
93 | }
94 | } finally {
95 | a.recycle();
96 | }
97 | }
98 |
99 | mPaint.setAntiAlias(true);
100 | mTextPaint.setAntiAlias(true);
101 | mPlaceHolder = BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_placeholder);
102 |
103 | setImageUrls(null);
104 | }
105 |
106 | @Override
107 | protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
108 | super.onLayout(changed, left, top, right, bottom);
109 | for (int i = 0; i < mImageUrls.length; i++) {
110 | loadBitmap(i, mImageUrls[i]);
111 | }
112 | }
113 |
114 | @Override
115 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
116 | if (mImageUrls.length != 0) {
117 | int width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
118 | mImageWidth = (width - (mColumns - 1) * mHorizontalSpace - getPaddingLeft() - getPaddingRight()) / mColumns;
119 | mImageHeight = (int) (mImageWidth * mRatio);
120 | mRows = (int) Math.ceil(mImageUrls.length * 1f / mColumns);
121 | int height = mImageHeight * mRows + (mRows - 1) * mVerticalSpace + getPaddingTop() + getPaddingBottom();
122 | setMeasuredDimension(width, height);
123 | } else {
124 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
125 | }
126 | }
127 |
128 |
129 | @Override
130 | protected void onDraw(Canvas canvas) {
131 | super.onDraw(canvas);
132 | if (mBitmaps.length != 0) {
133 | for (int row = 0; row < mRows; row++) {
134 | for (int column = 0; column < mColumns; column++) {
135 | int i = row * mColumns + column;
136 | boolean isGif;
137 | if (i >= mImageUrls.length) {
138 | break;
139 | } else {
140 | isGif = mImageUrls[i].toLowerCase().contains(".gif");
141 | }
142 | Bitmap bitmap = mBitmaps[i];
143 | if (bitmap == null) {
144 | bitmap = mPlaceHolder;
145 | }
146 |
147 |
148 | float left = getPaddingLeft() + column * mHorizontalSpace + column * mImageWidth;
149 | float top = getPaddingTop() + row * mVerticalSpace + row * mImageHeight;
150 | float scale;
151 | float dx = 0, dy = 0;
152 |
153 | int dwidth = bitmap.getWidth();
154 | int dheight = bitmap.getHeight();
155 | int vwidth = mImageWidth;
156 | int vheight = mImageHeight;
157 | if (dwidth * vheight > vwidth * dheight) {
158 | scale = (float) vheight / (float) dheight;
159 | dx = (vwidth - dwidth * scale) * 0.5f;
160 | } else {
161 | scale = (float) vwidth / (float) dwidth;
162 | dy = (vheight - dheight * scale) * 0.5f;
163 | }
164 |
165 | matrix.setScale(scale, scale);
166 | matrix.postTranslate(left + Math.round(dx), top + Math.round(dy));
167 |
168 | BitmapShader mBitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
169 | mBitmapShader.setLocalMatrix(matrix);
170 | mPaint.setShader(mBitmapShader);
171 | RectF rectF = new RectF();
172 | rectF.set(left, top, left + mImageWidth, top + mImageHeight);
173 | mDrawRects[i] = rectF;
174 | canvas.drawRoundRect(rectF, mRadius, mRadius, mPaint);
175 | if (isGif) {
176 | String gifString = "GIF";
177 | mTextPaint.setTextSize(DisplayUtil.dpToPx(12));
178 | mTextPaint.setColor(Color.WHITE);
179 | Rect bounds = new Rect();
180 | mTextPaint.getTextBounds(gifString, 0, gifString.length(), bounds);
181 | mTextBgPaint.setColor(Color.BLACK);
182 | mTextBgPaint.setAlpha(60);
183 | RectF rectB = new RectF();
184 | rectB.set(left + DisplayUtil.dpToPx(6), top + DisplayUtil.dpToPx(6),
185 | left + DisplayUtil.dpToPx(6) * 2 + bounds.width(), top + DisplayUtil.dpToPx(6) * 2 + bounds.height());
186 | canvas.drawRoundRect(rectB, mRadius, mRadius, mTextBgPaint);
187 | canvas.drawText(gifString, left + DisplayUtil.dpToPx(9), top + DisplayUtil.dpToPx(9) + bounds.height(), mTextPaint);
188 | }
189 | }
190 | }
191 | }
192 | }
193 |
194 |
195 | @Override
196 | public boolean onTouchEvent(MotionEvent event) {
197 | boolean isClickItem = false;
198 | int action = event.getActionMasked();
199 | switch (action) {
200 | case MotionEvent.ACTION_DOWN:
201 | mEventDown = MotionEvent.obtain(event);
202 | mDown = getClickItem(mEventDown);
203 | isClickItem = mDown > -1;
204 | break;
205 | case MotionEvent.ACTION_UP:
206 | if (mEventDown != null) {
207 | float distance = (float) Math.sqrt(Math.pow((event.getX() - mEventDown.getX()), 2) + Math.pow((event.getY() - mEventDown.getY()), 2));
208 | if (distance < ViewConfiguration.getTouchSlop()) {
209 | int iUp = getClickItem(event);
210 | if (mDown == iUp && iUp > -1) {
211 | isClickItem = true;
212 | if (onClickItemListener != null) {
213 | onClickItemListener.onClick(iUp, new ArrayList<>(Arrays.asList(mImageUrls)));
214 | }
215 | }
216 | }
217 | }
218 | break;
219 | }
220 | return isClickItem || super.onTouchEvent(event);
221 | }
222 |
223 | private int getClickItem(MotionEvent event) {
224 | for (int i = 0; i < mDrawRects.length; i++) {
225 | if (mDrawRects[i] != null && mDrawRects[i].contains(event.getX(), event.getY())) {
226 | return i;
227 | }
228 | }
229 | return -1;
230 | }
231 |
232 |
233 | public interface OnClickItemListener {
234 | void onClick(int i, ArrayList url);
235 | }
236 |
237 | private void loadBitmap(final int i, final String url) {
238 | Glide.with(getContext())
239 | .load(url)
240 | .asBitmap()
241 | .diskCacheStrategy(DiskCacheStrategy.ALL)
242 | .override(mImageWidth, mImageHeight)
243 | .into(mTargets[i]);
244 | }
245 |
246 |
247 | public void setImageUrls(Collection imageUrls) {
248 | // clean up outdated stuff
249 | for (Target target : mTargets) {
250 | Glide.clear(target); // clears mBitmaps[i] as well
251 | }
252 | if (imageUrls == null) imageUrls = Collections.emptyList();
253 | int newSize = imageUrls.size();
254 | mImageUrls = imageUrls.toArray(new String[newSize]);
255 | mBitmaps = new Bitmap[newSize];
256 | mDrawRects = new RectF[newSize];
257 | mTargets = new Target[newSize];
258 | if (!haveRule) {
259 | mColumns = imageUrls.size() <= 4 ? 2 : 3;
260 | }
261 | for (int i = 0; i < imageUrls.size(); i++) {
262 | mTargets[i] = new PositionTarget(i);
263 | }
264 | requestLayout();
265 | }
266 |
267 |
268 | public void setColumns(int columns) {
269 | mColumns = columns;
270 | haveRule = true;
271 | }
272 |
273 |
274 | public void setOnClickItemListener(OnClickItemListener onClickItemListener) {
275 | this.onClickItemListener = onClickItemListener;
276 | }
277 |
278 | private void setImageRect(int pos) {
279 | int column = pos / mColumns;
280 | int row = pos % mColumns;
281 |
282 | int left = getPaddingLeft() + column * mHorizontalSpace + column * mImageWidth;
283 | int top = getPaddingTop() + row * mVerticalSpace + mImageHeight;
284 | invalidate(left, top, left + mImageWidth, top + mImageHeight);
285 | }
286 |
287 | private class PositionTarget extends SimpleTarget {
288 | private final int i;
289 |
290 | PositionTarget(int i) {
291 | this.i = i;
292 | }
293 |
294 | @Override
295 | public void onResourceReady(Bitmap resource, GlideAnimation super Bitmap> glideAnimation) {
296 | mBitmaps[i] = resource;
297 | setImageRect(i);
298 | }
299 |
300 | }
301 | }
302 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HotBitmapGG/Acg/25414834e776fb555d2b73e4dc39e9d00472c711/app/src/main/res/drawable-hdpi/ic_logo.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_tab_community.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HotBitmapGG/Acg/25414834e776fb555d2b73e4dc39e9d00472c711/app/src/main/res/drawable-hdpi/ic_tab_community.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_tab_home.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HotBitmapGG/Acg/25414834e776fb555d2b73e4dc39e9d00472c711/app/src/main/res/drawable-hdpi/ic_tab_home.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_tab_mine.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HotBitmapGG/Acg/25414834e776fb555d2b73e4dc39e9d00472c711/app/src/main/res/drawable-hdpi/ic_tab_mine.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_tab_quanzi.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HotBitmapGG/Acg/25414834e776fb555d2b73e4dc39e9d00472c711/app/src/main/res/drawable-hdpi/ic_tab_quanzi.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_placeholder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HotBitmapGG/Acg/25414834e776fb555d2b73e4dc39e9d00472c711/app/src/main/res/drawable-xhdpi/ic_placeholder.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/bg_announcement.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HotBitmapGG/Acg/25414834e776fb555d2b73e4dc39e9d00472c711/app/src/main/res/drawable-xxhdpi/bg_announcement.9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_arrow_right_gray.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HotBitmapGG/Acg/25414834e776fb555d2b73e4dc39e9d00472c711/app/src/main/res/drawable-xxhdpi/ic_arrow_right_gray.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_event_album.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HotBitmapGG/Acg/25414834e776fb555d2b73e4dc39e9d00472c711/app/src/main/res/drawable-xxhdpi/ic_event_album.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_event_bbs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HotBitmapGG/Acg/25414834e776fb555d2b73e4dc39e9d00472c711/app/src/main/res/drawable-xxhdpi/ic_event_bbs.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_event_tag.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HotBitmapGG/Acg/25414834e776fb555d2b73e4dc39e9d00472c711/app/src/main/res/drawable-xxhdpi/ic_event_tag.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_event_time.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HotBitmapGG/Acg/25414834e776fb555d2b73e4dc39e9d00472c711/app/src/main/res/drawable-xxhdpi/ic_event_time.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_event_topic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HotBitmapGG/Acg/25414834e776fb555d2b73e4dc39e9d00472c711/app/src/main/res/drawable-xxhdpi/ic_event_topic.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_event_user.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HotBitmapGG/Acg/25414834e776fb555d2b73e4dc39e9d00472c711/app/src/main/res/drawable-xxhdpi/ic_event_user.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_hot_topic_detail.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HotBitmapGG/Acg/25414834e776fb555d2b73e4dc39e9d00472c711/app/src/main/res/drawable-xxhdpi/ic_hot_topic_detail.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_no_module.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HotBitmapGG/Acg/25414834e776fb555d2b73e4dc39e9d00472c711/app/src/main/res/drawable-xxhdpi/ic_no_module.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_original_topic_detail.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HotBitmapGG/Acg/25414834e776fb555d2b73e4dc39e9d00472c711/app/src/main/res/drawable-xxhdpi/ic_original_topic_detail.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_tag.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HotBitmapGG/Acg/25414834e776fb555d2b73e4dc39e9d00472c711/app/src/main/res/drawable-xxhdpi/ic_tag.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_uncomment_chart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HotBitmapGG/Acg/25414834e776fb555d2b73e4dc39e9d00472c711/app/src/main/res/drawable-xxhdpi/ic_uncomment_chart.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_unfavour_heart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HotBitmapGG/Acg/25414834e776fb555d2b73e4dc39e9d00472c711/app/src/main/res/drawable-xxhdpi/ic_unfavour_heart.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_water_comment.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HotBitmapGG/Acg/25414834e776fb555d2b73e4dc39e9d00472c711/app/src/main/res/drawable-xxhdpi/ic_water_comment.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_message_board_in_online_event.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_tag_secondary.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_topic_tag.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
7 |
8 |
9 |
10 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_type.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/divider_gray.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_copy_details.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
10 |
11 |
12 |
13 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_image_details.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
17 |
18 |
19 |
26 |
27 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
12 |
13 |
21 |
22 |
23 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
45 |
46 |
47 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_quanzi_details.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
13 |
14 |
25 |
26 |
33 |
34 |
39 |
40 |
52 |
53 |
65 |
66 |
67 |
68 |
69 |
74 |
75 |
80 |
81 |
90 |
91 |
95 |
96 |
102 |
103 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
122 |
123 |
124 |
130 |
131 |
139 |
140 |
146 |
147 |
148 |
155 |
156 |
169 |
170 |
181 |
182 |
183 |
184 |
188 |
189 |
190 |
199 |
200 |
204 |
205 |
206 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_community.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_copy_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_image_details.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_mine.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
14 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_quanzi_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
14 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_comment.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
14 |
15 |
26 |
27 |
28 |
32 |
33 |
39 |
40 |
47 |
48 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
69 |
70 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_copy.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
17 |
18 |
23 |
24 |
25 |
29 |
30 |
40 |
41 |
42 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_copy_details.xml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
16 |
17 |
22 |
23 |
35 |
36 |
48 |
49 |
50 |
51 |
52 |
57 |
58 |
62 |
63 |
68 |
69 |
80 |
81 |
94 |
95 |
96 |
97 |
111 |
112 |
122 |
123 |
124 |
132 |
133 |
139 |
140 |
150 |
151 |
152 |
157 |
158 |
162 |
163 |
168 |
169 |
179 |
180 |
181 |
186 |
187 |
197 |
198 |
199 |
204 |
205 |
215 |
216 |
217 |
218 |
219 |
223 |
224 |
225 |
226 |
227 |
228 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_quanzi.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
17 |
18 |
23 |
24 |
33 |
34 |
38 |
39 |
45 |
46 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
64 |
65 |
74 |
75 |
80 |
81 |
91 |
92 |
102 |
103 |
104 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_item_tag.xml:
--------------------------------------------------------------------------------
1 |
2 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_load_more.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_loading.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_toolbar.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HotBitmapGG/Acg/25414834e776fb555d2b73e4dc39e9d00472c711/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HotBitmapGG/Acg/25414834e776fb555d2b73e4dc39e9d00472c711/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HotBitmapGG/Acg/25414834e776fb555d2b73e4dc39e9d00472c711/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HotBitmapGG/Acg/25414834e776fb555d2b73e4dc39e9d00472c711/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HotBitmapGG/Acg/25414834e776fb555d2b73e4dc39e9d00472c711/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #000000
4 | #ededed
5 |
6 | #ffffff
7 | #bf000000
8 | #f1f1f1
9 | @color/colorPrimaryDark_below_23
10 | #000000
11 | #123123
12 | #ff292929
13 | #ffdedede
14 |
15 | #ffffff
16 | #00000000
17 |
18 | #ff000000
19 | #787474
20 | #a5abb5
21 | #000000
22 | #de6c6969
23 | #ffee483c
24 | #ff4dcbff
25 | #ff333333
26 |
27 | #432e2a
28 |
29 | #90ffffff
30 | #f2f2f2
31 | @color/white
32 | #48000000
33 | #ededed
34 |
35 |
36 | @color/white
37 | @android:color/black
38 | @android:color/black
39 | @android:color/black
40 | @color/toolbarBackground
41 | @color/toolbarTextColor
42 | @color/window_background
43 | #ffffff
44 |
45 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | おたく、
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
11 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/app/src/test/java/com/example/cnsunrun/debugdemo/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.example.cnsunrun.debugdemo;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/art/01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HotBitmapGG/Acg/25414834e776fb555d2b73e4dc39e9d00472c711/art/01.png
--------------------------------------------------------------------------------
/art/02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HotBitmapGG/Acg/25414834e776fb555d2b73e4dc39e9d00472c711/art/02.png
--------------------------------------------------------------------------------
/art/03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HotBitmapGG/Acg/25414834e776fb555d2b73e4dc39e9d00472c711/art/03.png
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:2.3.2'
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 | maven { url "https://jitpack.io" }
19 | }
20 | }
21 |
22 | task clean(type: Delete) {
23 | delete rootProject.buildDir
24 | }
25 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | org.gradle.jvmargs=-Xmx1536m
13 |
14 | # When configured, Gradle will run in incubating parallel mode.
15 | # This option should only be used with decoupled projects. More details, visit
16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
17 | # org.gradle.parallel=true
18 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HotBitmapGG/Acg/25414834e776fb555d2b73e4dc39e9d00472c711/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sat Mar 11 13:46:05 CST 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------