├── .gitignore ├── .idea ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── dictionaries │ └── wangchenlong.xml ├── encodings.xml ├── gradle.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── me │ │ └── chunyu │ │ └── spike │ │ └── springrainnews │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── me │ │ │ └── chunyu │ │ │ └── spike │ │ │ └── springrainnews │ │ │ ├── NewsApplication.java │ │ │ ├── injectors │ │ │ ├── components │ │ │ │ ├── AppComponent.java │ │ │ │ └── AppGraph.java │ │ │ └── modules │ │ │ │ ├── AppModule.java │ │ │ │ └── AppScope.java │ │ │ ├── mvp │ │ │ ├── models │ │ │ │ ├── AvengersCharacter.java │ │ │ │ └── Repository.java │ │ │ ├── presenters │ │ │ │ ├── BasePresenter.java │ │ │ │ └── MainPresenter.java │ │ │ └── views │ │ │ │ ├── BaseView.java │ │ │ │ └── MainView.java │ │ │ ├── networks │ │ │ ├── RestDataSource.java │ │ │ ├── deserializers │ │ │ │ └── MarvelResultsDeserializer.java │ │ │ ├── interceptors │ │ │ │ ├── MarvelApiUtils.java │ │ │ │ └── MarvelSigningInterceptor.java │ │ │ └── services │ │ │ │ └── MarvelService.java │ │ │ └── uis │ │ │ ├── activities │ │ │ └── MainActivity.java │ │ │ └── adapters │ │ │ └── MainListAdapter.java │ └── res │ │ ├── drawable-nodpi │ │ └── image_not_available.png │ │ ├── drawable-v21 │ │ ├── ic_menu_camera.xml │ │ ├── ic_menu_gallery.xml │ │ ├── ic_menu_manage.xml │ │ ├── ic_menu_send.xml │ │ ├── ic_menu_share.xml │ │ └── ic_menu_slideshow.xml │ │ ├── drawable │ │ └── side_nav_bar.xml │ │ ├── layout │ │ ├── activity_main.xml │ │ ├── app_bar_main.xml │ │ ├── content_main.xml │ │ ├── item_main_list.xml │ │ └── nav_header_main.xml │ │ ├── menu │ │ ├── activity_main_drawer.xml │ │ └── main.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── values-v21 │ │ └── styles.xml │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── drawables.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── me │ └── chunyu │ └── spike │ └── springrainnews │ └── ExampleUnitTest.java ├── 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 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/dictionaries/wangchenlong.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | 14 | 26 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | Android > Lint > Correctness 46 | 47 | 48 | C/C++ 49 | 50 | 51 | Data flow issuesJava 52 | 53 | 54 | General 55 | 56 | 57 | Java 58 | 59 | 60 | Unused codeC/C++ 61 | 62 | 63 | 64 | 65 | Android 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 87 | 88 | $USER_HOME$/.subversion 89 | 90 | 91 | 92 | 93 | 94 | 1.8 95 | 96 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 112 | 113 | 114 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' // Android应用 2 | apply plugin: 'me.tatarka.retrolambda' // Lambda表达式 3 | apply plugin: 'com.neenbedankt.android-apt' // 编译时类 4 | apply plugin: 'com.android.databinding' // 数据绑定 5 | 6 | def libs = rootProject.ext.libraries // 库 7 | 8 | android { 9 | compileSdkVersion 23 10 | buildToolsVersion "23.0.2" 11 | 12 | defaultConfig { 13 | applicationId "me.chunyu.spike.springrainnews" 14 | minSdkVersion 14 15 | targetSdkVersion 23 16 | versionCode 1 17 | versionName "1.0" 18 | buildConfigField "String", "MARVEL_PUBLIC_KEY", "\"${marvel_public_key}\"" 19 | buildConfigField "String", "MARVEL_PRIVATE_KEY", "\"${marvel_private_key}\"" 20 | } 21 | 22 | buildTypes { 23 | release { 24 | minifyEnabled false 25 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 26 | } 27 | } 28 | 29 | compileOptions { 30 | sourceCompatibility JavaVersion.VERSION_1_8 31 | targetCompatibility JavaVersion.VERSION_1_8 32 | } 33 | 34 | // 注释冲突 35 | packagingOptions { 36 | exclude 'META-INF/services/javax.annotation.processing.Processor' 37 | } 38 | } 39 | 40 | dependencies { 41 | compile fileTree(dir: 'libs', include: ['*.jar']) 42 | testCompile 'junit:junit:4.12' 43 | // Android 44 | compile "com.android.support:design:${libs.supportVersion}" 45 | compile "com.android.support:appcompat-v7:${libs.supportVersion}" 46 | compile "com.android.support:cardview-v7:${libs.supportVersion}" 47 | compile "com.android.support:recyclerview-v7:${libs.supportVersion}" 48 | compile "com.android.support:palette-v7:${libs.supportVersion}" 49 | 50 | // Retrofit 51 | compile "com.squareup.retrofit2:retrofit:${libs.retrofit}" 52 | compile "com.squareup.retrofit2:converter-gson:${libs.retrofit}" 53 | compile "com.squareup.retrofit2:adapter-rxjava:${libs.retrofit}" 54 | compile "com.squareup.okhttp3:logging-interceptor:${libs.okhttp}" 55 | 56 | // ReactiveX 57 | compile "io.reactivex:rxjava:${libs.rxandroid}" 58 | compile "io.reactivex:rxandroid:${libs.rxandroid}" 59 | 60 | // Dagger 61 | compile "com.google.dagger:dagger:${libs.dagger}" 62 | apt "com.google.dagger:dagger-compiler:${libs.dagger}" 63 | compile "org.glassfish:javax.annotation:${libs.javax_annotation}" 64 | 65 | // Others 66 | compile "com.jakewharton:butterknife:${libs.butterknife}" // 资源注入 67 | compile "com.github.bumptech.glide:glide:${libs.glide}" // 图片处理 68 | compile "jp.wasabeef:recyclerview-animators:${libs.recycler_animators}" // Recycler动画 69 | compile "de.hdodenhof:circleimageview:${libs.circleimageview}" // 头像视图 70 | } 71 | -------------------------------------------------------------------------------- /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 /Users/wangchenlong/Installations/android-sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/me/chunyu/spike/springrainnews/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package me.chunyu.spike.springrainnews; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 14 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/java/me/chunyu/spike/springrainnews/NewsApplication.java: -------------------------------------------------------------------------------- 1 | package me.chunyu.spike.springrainnews; 2 | 3 | import android.app.Application; 4 | 5 | import me.chunyu.spike.springrainnews.injectors.components.AppComponent; 6 | import me.chunyu.spike.springrainnews.injectors.components.AppGraph; 7 | 8 | /** 9 | * 项目应用 10 | *

11 | * Created by wangchenlong on 16/1/21. 12 | */ 13 | public class NewsApplication extends Application { 14 | private static NewsApplication sApplication; 15 | 16 | private static AppGraph sAppGraph; 17 | 18 | @Override public void onCreate() { 19 | super.onCreate(); 20 | sApplication = this; 21 | buildComponentAndInject(); 22 | } 23 | 24 | public static AppGraph component() { 25 | return sAppGraph; 26 | } 27 | 28 | // 初始化组件 29 | private static void buildComponentAndInject() { 30 | sAppGraph = AppComponent.Initializer.init(sApplication); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/src/main/java/me/chunyu/spike/springrainnews/injectors/components/AppComponent.java: -------------------------------------------------------------------------------- 1 | package me.chunyu.spike.springrainnews.injectors.components; 2 | 3 | import javax.inject.Singleton; 4 | 5 | import dagger.Component; 6 | import me.chunyu.spike.springrainnews.NewsApplication; 7 | import me.chunyu.spike.springrainnews.injectors.modules.AppModule; 8 | import me.chunyu.spike.springrainnews.injectors.modules.AppScope; 9 | 10 | /** 11 | * App的组件 12 | *

13 | * Created by wangchenlong on 16/1/21. 14 | */ 15 | @Singleton 16 | @Component(modules = AppModule.class) 17 | public interface AppComponent extends AppGraph { 18 | final class Initializer { 19 | private Initializer() { 20 | } // No instances. 21 | 22 | // 初始化组件 23 | public static AppComponent init(NewsApplication app) { 24 | return DaggerAppComponent.builder() 25 | .appModule(new AppModule(app)) 26 | .build(); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/me/chunyu/spike/springrainnews/injectors/components/AppGraph.java: -------------------------------------------------------------------------------- 1 | package me.chunyu.spike.springrainnews.injectors.components; 2 | 3 | import me.chunyu.spike.springrainnews.injectors.modules.AppScope; 4 | import me.chunyu.spike.springrainnews.uis.activities.MainActivity; 5 | import me.chunyu.spike.springrainnews.uis.adapters.MainListAdapter; 6 | 7 | /** 8 | * App的类图 9 | *

10 | * Created by wangchenlong on 16/1/21. 11 | */ 12 | public interface AppGraph { 13 | void inject(MainActivity mainActivity); // 注入MainActivity 14 | 15 | void inject(MainListAdapter mainListAdapter); // 注入MainListAdapter 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/me/chunyu/spike/springrainnews/injectors/modules/AppModule.java: -------------------------------------------------------------------------------- 1 | package me.chunyu.spike.springrainnews.injectors.modules; 2 | 3 | import android.content.Context; 4 | import android.content.res.Resources; 5 | 6 | import javax.inject.Singleton; 7 | 8 | import dagger.Module; 9 | import dagger.Provides; 10 | import me.chunyu.spike.springrainnews.NewsApplication; 11 | import me.chunyu.spike.springrainnews.mvp.models.Repository; 12 | import me.chunyu.spike.springrainnews.networks.RestDataSource; 13 | 14 | /** 15 | * App的模块 16 | *

17 | * Created by wangchenlong on 16/1/21. 18 | */ 19 | @Module 20 | public class AppModule { 21 | private final NewsApplication mApplication; 22 | 23 | public AppModule(NewsApplication application) { 24 | mApplication = application; 25 | } 26 | 27 | // 注入Application的Context 28 | @Provides @Singleton 29 | protected Context provideApplication() { 30 | return mApplication; 31 | } 32 | 33 | // 注入资源 34 | @Provides @Singleton 35 | protected Resources provideResources() { 36 | return mApplication.getResources(); 37 | } 38 | 39 | // 注入REST数据源 40 | @Provides @Singleton 41 | protected Repository provideDataRepository(RestDataSource restDataSource) { 42 | return restDataSource; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/src/main/java/me/chunyu/spike/springrainnews/injectors/modules/AppScope.java: -------------------------------------------------------------------------------- 1 | package me.chunyu.spike.springrainnews.injectors.modules; 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 | * 主要的域 11 | *

12 | * Created by wangchenlong on 16/7/28. 13 | */ 14 | @Scope 15 | @Documented 16 | @Retention(RetentionPolicy.RUNTIME) 17 | public @interface AppScope { 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/me/chunyu/spike/springrainnews/mvp/models/AvengersCharacter.java: -------------------------------------------------------------------------------- 1 | package me.chunyu.spike.springrainnews.mvp.models; 2 | 3 | /** 4 | * 复仇者成员类 5 | *

6 | * Created by wangchenlong on 16/1/21. 7 | */ 8 | @SuppressWarnings("unused") 9 | public class AvengersCharacter { 10 | 11 | private int id; 12 | private String name; 13 | private String description; 14 | private ThumbnailEntity thumbnail; 15 | 16 | public void setId(int id) { 17 | this.id = id; 18 | } 19 | 20 | public void setName(String name) { 21 | this.name = name; 22 | } 23 | 24 | public void setDescription(String description) { 25 | this.description = description; 26 | } 27 | 28 | public void setThumbnail(ThumbnailEntity thumbnail) { 29 | this.thumbnail = thumbnail; 30 | } 31 | 32 | public int getId() { 33 | return id; 34 | } 35 | 36 | public String getName() { 37 | return name; 38 | } 39 | 40 | public String getDescription() { 41 | return description; 42 | } 43 | 44 | public ThumbnailEntity getThumbnail() { 45 | return thumbnail; 46 | } 47 | 48 | // 返回图片路径 49 | public String getThumbImage() { 50 | return String.format("%s.%s", thumbnail.path, thumbnail.extension); 51 | } 52 | 53 | public static class ThumbnailEntity { 54 | private String path; 55 | private String extension; 56 | 57 | public void setPath(String path) { 58 | this.path = path; 59 | } 60 | 61 | public void setExtension(String extension) { 62 | this.extension = extension; 63 | } 64 | 65 | public String getPath() { 66 | return path; 67 | } 68 | 69 | public String getExtension() { 70 | return extension; 71 | } 72 | } 73 | } 74 | 75 | 76 | -------------------------------------------------------------------------------- /app/src/main/java/me/chunyu/spike/springrainnews/mvp/models/Repository.java: -------------------------------------------------------------------------------- 1 | package me.chunyu.spike.springrainnews.mvp.models; 2 | 3 | import java.util.List; 4 | 5 | import rx.Observable; 6 | 7 | /** 8 | * 请求的库 9 | *

10 | * Created by wangchenlong on 16/1/21. 11 | */ 12 | public interface Repository { 13 | Observable> getCharacters(int offset); 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/me/chunyu/spike/springrainnews/mvp/presenters/BasePresenter.java: -------------------------------------------------------------------------------- 1 | package me.chunyu.spike.springrainnews.mvp.presenters; 2 | 3 | import me.chunyu.spike.springrainnews.mvp.views.BaseView; 4 | 5 | /** 6 | * 展示页面 7 | *

8 | * Created by wangchenlong on 16/1/21. 9 | */ 10 | @SuppressWarnings("EmptyMethod") 11 | public interface BasePresenter { 12 | void onCreate(); 13 | 14 | void onResume(); 15 | 16 | void onStop(); 17 | 18 | void onDestroy(); 19 | 20 | void attachView(BaseView v); 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/me/chunyu/spike/springrainnews/mvp/presenters/MainPresenter.java: -------------------------------------------------------------------------------- 1 | package me.chunyu.spike.springrainnews.mvp.presenters; 2 | 3 | import javax.inject.Inject; 4 | 5 | import me.chunyu.spike.springrainnews.mvp.models.Repository; 6 | import me.chunyu.spike.springrainnews.mvp.views.BaseView; 7 | import me.chunyu.spike.springrainnews.mvp.views.MainView; 8 | import rx.Subscription; 9 | import rx.android.schedulers.AndroidSchedulers; 10 | import rx.schedulers.Schedulers; 11 | 12 | /** 13 | * 主页的展示逻辑 14 | *

15 | * Created by wangchenlong on 16/1/21. 16 | */ 17 | public class MainPresenter implements BasePresenter { 18 | 19 | private final Repository mRepository; // 网络库 20 | 21 | private MainView mMainView; // 主页 22 | 23 | private Subscription mCharactersSubscription; // 订阅成员 24 | 25 | @Inject 26 | public MainPresenter(Repository repository) { 27 | mRepository = repository; 28 | } 29 | 30 | @Override public void onCreate() { 31 | loadData(); 32 | } 33 | 34 | private void loadData() { 35 | mCharactersSubscription = mRepository.getCharacters(0) 36 | .subscribeOn(Schedulers.io()) 37 | .observeOn(AndroidSchedulers.mainThread()) 38 | .subscribe(avengersCharacters -> { 39 | mMainView.setListData(avengersCharacters); 40 | }); 41 | } 42 | 43 | @Override public void onResume() { 44 | 45 | } 46 | 47 | @Override public void onStop() { 48 | mCharactersSubscription.unsubscribe(); 49 | } 50 | 51 | @Override public void onDestroy() { 52 | 53 | } 54 | 55 | @Override public void attachView(BaseView v) { 56 | mMainView = (MainView) v; // 绑定视图 57 | } 58 | 59 | 60 | 61 | } 62 | -------------------------------------------------------------------------------- /app/src/main/java/me/chunyu/spike/springrainnews/mvp/views/BaseView.java: -------------------------------------------------------------------------------- 1 | package me.chunyu.spike.springrainnews.mvp.views; 2 | 3 | /** 4 | * mvp的基本视图 5 | *

6 | * Created by wangchenlong on 16/1/21. 7 | */ 8 | public interface BaseView { 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/me/chunyu/spike/springrainnews/mvp/views/MainView.java: -------------------------------------------------------------------------------- 1 | package me.chunyu.spike.springrainnews.mvp.views; 2 | 3 | import java.util.List; 4 | 5 | import me.chunyu.spike.springrainnews.mvp.models.AvengersCharacter; 6 | 7 | /** 8 | * 主页的Views 9 | *

10 | * Created by wangchenlong on 16/1/21. 11 | */ 12 | public interface MainView extends BaseView { 13 | void setListData(List characters); 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/me/chunyu/spike/springrainnews/networks/RestDataSource.java: -------------------------------------------------------------------------------- 1 | package me.chunyu.spike.springrainnews.networks; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.GsonBuilder; 5 | import com.google.gson.reflect.TypeToken; 6 | 7 | import java.util.List; 8 | 9 | import javax.inject.Inject; 10 | 11 | import me.chunyu.spike.springrainnews.BuildConfig; 12 | import me.chunyu.spike.springrainnews.mvp.models.AvengersCharacter; 13 | import me.chunyu.spike.springrainnews.mvp.models.Repository; 14 | import me.chunyu.spike.springrainnews.networks.deserializers.MarvelResultsDeserializer; 15 | import me.chunyu.spike.springrainnews.networks.interceptors.MarvelSigningInterceptor; 16 | import me.chunyu.spike.springrainnews.networks.services.MarvelService; 17 | import okhttp3.OkHttpClient; 18 | import okhttp3.logging.HttpLoggingInterceptor; 19 | import retrofit2.GsonConverterFactory; 20 | import retrofit2.Retrofit; 21 | import retrofit2.RxJavaCallAdapterFactory; 22 | import rx.Observable; 23 | 24 | /** 25 | * 数据源 26 | * 27 | * @author wangchenlong 28 | */ 29 | public class RestDataSource implements Repository { 30 | 31 | private final MarvelService mMarvelService; 32 | 33 | @Inject 34 | public RestDataSource() { 35 | 36 | // Log信息插值器 37 | HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(); 38 | loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BASIC); 39 | 40 | // 公共密匙插值器 41 | MarvelSigningInterceptor signingInterceptor = new MarvelSigningInterceptor( 42 | BuildConfig.MARVEL_PUBLIC_KEY, BuildConfig.MARVEL_PRIVATE_KEY); 43 | 44 | // 在OkHttp3.0中添加差值器 45 | OkHttpClient client = new OkHttpClient.Builder() 46 | .addInterceptor(signingInterceptor) 47 | .addInterceptor(loggingInterceptor) 48 | .build(); 49 | 50 | // 返回数据反序列化的过滤处理 51 | MarvelResultsDeserializer deserializer = 52 | new MarvelResultsDeserializer(); 53 | 54 | // 定制的Gson反序列化 55 | Gson customGsonInstance = new GsonBuilder() 56 | .registerTypeAdapter( 57 | new TypeToken>() { 58 | }.getType(), 59 | deserializer) 60 | .create(); 61 | 62 | // 添加Host, 添加Gson解析, 添加RxJava适配器, 添加OKHttp. 63 | Retrofit retrofitAdapter = new Retrofit.Builder() 64 | .baseUrl(MarvelService.END_POINT) 65 | .addConverterFactory(GsonConverterFactory.create(customGsonInstance)) 66 | .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 67 | .client(client) 68 | .build(); 69 | 70 | // mMarvelService是服务器接口, marvelApiAdapter是Retrofit对象 71 | mMarvelService = retrofitAdapter.create(MarvelService.class); 72 | } 73 | 74 | @Override 75 | public Observable> getCharacters(int currentOffset) { 76 | // 调用接口, 返回Observable信息 77 | return mMarvelService.getCharacters(currentOffset); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /app/src/main/java/me/chunyu/spike/springrainnews/networks/deserializers/MarvelResultsDeserializer.java: -------------------------------------------------------------------------------- 1 | package me.chunyu.spike.springrainnews.networks.deserializers; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.JsonDeserializationContext; 5 | import com.google.gson.JsonDeserializer; 6 | import com.google.gson.JsonElement; 7 | import com.google.gson.JsonParseException; 8 | 9 | import java.lang.reflect.Type; 10 | import java.util.List; 11 | 12 | public class MarvelResultsDeserializer implements JsonDeserializer> { 13 | @Override 14 | public List deserialize(JsonElement je, Type typeOfT, 15 | JsonDeserializationContext context) throws JsonParseException { 16 | // 转换Json的数据, 获取内部有用的信息 17 | JsonElement results = je.getAsJsonObject().get("data") 18 | .getAsJsonObject().get("results"); 19 | return new Gson().fromJson(results, typeOfT); 20 | } 21 | } -------------------------------------------------------------------------------- /app/src/main/java/me/chunyu/spike/springrainnews/networks/interceptors/MarvelApiUtils.java: -------------------------------------------------------------------------------- 1 | package me.chunyu.spike.springrainnews.networks.interceptors; 2 | 3 | import java.security.MessageDigest; 4 | import java.security.NoSuchAlgorithmException; 5 | 6 | public class MarvelApiUtils { 7 | 8 | public static String generateMarvelHash(String publicKey, String privateKey) { 9 | 10 | String marvelHash = ""; 11 | 12 | try { 13 | String timeStamp = getUnixTimeStamp(); 14 | String marvelData = timeStamp + privateKey + publicKey; 15 | 16 | MessageDigest messageDigest = MessageDigest.getInstance("MD5"); 17 | byte[] hash = messageDigest.digest(marvelData.getBytes()); 18 | 19 | StringBuilder stringBuilder = new StringBuilder(2 * hash.length); 20 | 21 | for (byte b : hash) 22 | stringBuilder.append(String.format("%02x", b & 0xff)); 23 | 24 | marvelHash = stringBuilder.toString(); 25 | 26 | } catch (NoSuchAlgorithmException e) { 27 | 28 | System.out.println("[DEBUG]" + " MarvelApiUtils generateMarvelHash - " + 29 | "NoSuchAlgorithmException"); 30 | } 31 | 32 | return marvelHash; 33 | } 34 | 35 | public static String getUnixTimeStamp() { 36 | 37 | return String.valueOf(System.currentTimeMillis() / 1000L); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/src/main/java/me/chunyu/spike/springrainnews/networks/interceptors/MarvelSigningInterceptor.java: -------------------------------------------------------------------------------- 1 | package me.chunyu.spike.springrainnews.networks.interceptors; 2 | 3 | import java.io.IOException; 4 | 5 | import me.chunyu.spike.springrainnews.networks.services.MarvelService; 6 | import okhttp3.HttpUrl; 7 | import okhttp3.Interceptor; 8 | import okhttp3.Request; 9 | import okhttp3.Response; 10 | 11 | /** 12 | * 添加Key和密码 13 | *

14 | * Created by wangchenlong on 16/1/21. 15 | */ 16 | public class MarvelSigningInterceptor implements Interceptor { 17 | private final String mApiKey; 18 | private final String mApiSecret; 19 | 20 | public MarvelSigningInterceptor(String apiKey, String apiSecret) { 21 | mApiKey = apiKey; 22 | mApiSecret = apiSecret; 23 | } 24 | 25 | @Override public Response intercept(Interceptor.Chain chain) throws IOException { 26 | String marvelHash = MarvelApiUtils.generateMarvelHash(mApiKey, mApiSecret); 27 | Request oldRequest = chain.request(); 28 | 29 | // 添加新的参数 30 | HttpUrl.Builder authorizedUrlBuilder = oldRequest.url() 31 | .newBuilder() 32 | .scheme(oldRequest.url().scheme()) 33 | .host(oldRequest.url().host()) 34 | .addQueryParameter(MarvelService.PARAM_API_KEY, mApiKey) 35 | .addQueryParameter(MarvelService.PARAM_TIMESTAMP, MarvelApiUtils.getUnixTimeStamp()) 36 | .addQueryParameter(MarvelService.PARAM_HASH, marvelHash); 37 | 38 | // 新的请求 39 | Request newRequest = oldRequest.newBuilder() 40 | .method(oldRequest.method(), oldRequest.body()) 41 | .url(authorizedUrlBuilder.build()) 42 | .build(); 43 | 44 | return chain.proceed(newRequest); 45 | } 46 | } 47 | 48 | -------------------------------------------------------------------------------- /app/src/main/java/me/chunyu/spike/springrainnews/networks/services/MarvelService.java: -------------------------------------------------------------------------------- 1 | package me.chunyu.spike.springrainnews.networks.services; 2 | 3 | import java.util.List; 4 | 5 | import me.chunyu.spike.springrainnews.mvp.models.AvengersCharacter; 6 | import retrofit2.http.GET; 7 | import retrofit2.http.Query; 8 | import rx.Observable; 9 | 10 | /** 11 | * 网络请求 12 | *

13 | * Created by wangchenlong on 16/1/21. 14 | */ 15 | public interface MarvelService { 16 | String END_POINT = "http://gateway.marvel.com/"; 17 | String PARAM_API_KEY = "apikey"; 18 | String PARAM_HASH = "hash"; 19 | String PARAM_TIMESTAMP = "ts"; 20 | 21 | @GET("/v1/public/characters") 22 | Observable> getCharacters(@Query("offset") int offset); 23 | } -------------------------------------------------------------------------------- /app/src/main/java/me/chunyu/spike/springrainnews/uis/activities/MainActivity.java: -------------------------------------------------------------------------------- 1 | package me.chunyu.spike.springrainnews.uis.activities; 2 | 3 | import android.content.Context; 4 | import android.os.Bundle; 5 | import android.support.design.widget.FloatingActionButton; 6 | import android.support.design.widget.NavigationView; 7 | import android.support.design.widget.Snackbar; 8 | import android.support.v4.view.GravityCompat; 9 | import android.support.v4.widget.DrawerLayout; 10 | import android.support.v7.app.ActionBarDrawerToggle; 11 | import android.support.v7.app.AppCompatActivity; 12 | import android.support.v7.widget.LinearLayoutManager; 13 | import android.support.v7.widget.RecyclerView; 14 | import android.support.v7.widget.Toolbar; 15 | import android.view.Menu; 16 | import android.view.MenuItem; 17 | import android.widget.Toast; 18 | 19 | import java.util.List; 20 | 21 | import javax.inject.Inject; 22 | 23 | import butterknife.Bind; 24 | import butterknife.ButterKnife; 25 | import me.chunyu.spike.springrainnews.NewsApplication; 26 | import me.chunyu.spike.springrainnews.R; 27 | import me.chunyu.spike.springrainnews.mvp.models.AvengersCharacter; 28 | import me.chunyu.spike.springrainnews.mvp.presenters.MainPresenter; 29 | import me.chunyu.spike.springrainnews.mvp.views.MainView; 30 | import me.chunyu.spike.springrainnews.uis.adapters.MainListAdapter; 31 | 32 | public class MainActivity extends AppCompatActivity implements MainView { 33 | 34 | private static final String TAG = "DEBUG-WCL: " + MainActivity.class.getSimpleName(); 35 | 36 | @Inject MainPresenter mMainPresenter; 37 | 38 | @Inject Context mAppContext; 39 | 40 | @Bind(R.id.toolbar) Toolbar mToolbar; 41 | @Bind(R.id.fab) FloatingActionButton mFab; 42 | @Bind(R.id.nav_view) NavigationView mNavView; 43 | @Bind(R.id.drawer_layout) DrawerLayout mDrawerLayout; 44 | 45 | @Bind(R.id.main_rv_list) RecyclerView mRvList; // 列表视图 46 | 47 | private MainListAdapter mListAdapter; // 列表视图的适配器 48 | 49 | @Override 50 | protected void onCreate(Bundle savedInstanceState) { 51 | super.onCreate(savedInstanceState); 52 | initUi(); // 初始化Ui 53 | initList(); 54 | initDi(); // 初始化依赖注入 55 | initDefault(); // 默认配置 56 | initPresenter(); // 初始化展示 57 | } 58 | 59 | @Override protected void onResume() { 60 | super.onResume(); 61 | mMainPresenter.onResume(); 62 | } 63 | 64 | @Override protected void onStop() { 65 | super.onStop(); 66 | mMainPresenter.onStop(); 67 | } 68 | 69 | @Override protected void onDestroy() { 70 | super.onDestroy(); 71 | mMainPresenter.onDestroy(); 72 | } 73 | 74 | @Override 75 | public void onBackPressed() { 76 | DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); 77 | if (drawer.isDrawerOpen(GravityCompat.START)) { 78 | drawer.closeDrawer(GravityCompat.START); 79 | } else { 80 | super.onBackPressed(); 81 | } 82 | } 83 | 84 | @SuppressWarnings("StatementWithEmptyBody") 85 | public boolean onNavigationItemSelected(MenuItem item) { 86 | int id = item.getItemId(); 87 | 88 | if (id == R.id.nav_camera) { 89 | // Handle the camera action 90 | } else if (id == R.id.nav_gallery) { 91 | 92 | } else if (id == R.id.nav_slideshow) { 93 | 94 | } else if (id == R.id.nav_manage) { 95 | 96 | } else if (id == R.id.nav_share) { 97 | 98 | } else if (id == R.id.nav_send) { 99 | 100 | } 101 | 102 | DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); 103 | drawer.closeDrawer(GravityCompat.START); 104 | return true; 105 | } 106 | 107 | 108 | @Override 109 | public boolean onCreateOptionsMenu(Menu menu) { 110 | // Inflate the menu; this adds items to the action bar if it is present. 111 | getMenuInflater().inflate(R.menu.main, menu); 112 | return true; 113 | } 114 | 115 | @Override 116 | public boolean onOptionsItemSelected(MenuItem item) { 117 | // Handle action bar item clicks here. The action bar will 118 | // automatically handle clicks on the Home/Up button, so long 119 | // as you specify a parent activity in AndroidManifest.xml. 120 | int id = item.getItemId(); 121 | 122 | //noinspection SimplifiableIfStatement 123 | if (id == R.id.action_settings) { 124 | return true; 125 | } 126 | 127 | return super.onOptionsItemSelected(item); 128 | } 129 | 130 | @Override public void setListData(List characters) { 131 | Toast.makeText(mAppContext, "数量: " + characters.size(), Toast.LENGTH_SHORT).show(); 132 | mListAdapter.setCharacters(characters); 133 | } 134 | 135 | // 初始化Ui 136 | private void initUi() { 137 | setContentView(R.layout.activity_main); 138 | ButterKnife.bind(this); 139 | } 140 | 141 | // 初始化列表 142 | private void initList() { 143 | mRvList.setLayoutManager(new LinearLayoutManager(mAppContext)); 144 | mListAdapter = new MainListAdapter(); 145 | mRvList.setAdapter(mListAdapter); 146 | } 147 | 148 | // 初始化依赖注入 149 | private void initDi() { 150 | NewsApplication.component().inject(this); // 注入 151 | } 152 | 153 | // 初始化默认配置 154 | private void initDefault() { 155 | setSupportActionBar(mToolbar); 156 | 157 | mFab.setOnClickListener(view -> 158 | Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) 159 | .setAction("Action", null).show() 160 | ); 161 | 162 | ActionBarDrawerToggle toggle = new ActionBarDrawerToggle( 163 | this, mDrawerLayout, mToolbar, R.string.navigation_drawer_open, 164 | R.string.navigation_drawer_close); 165 | mDrawerLayout.setDrawerListener(toggle); 166 | toggle.syncState(); 167 | 168 | mNavView.setNavigationItemSelectedListener(this::onNavigationItemSelected); 169 | } 170 | 171 | // 初始化展示 172 | private void initPresenter() { 173 | mMainPresenter.attachView(this); 174 | mMainPresenter.onCreate(); 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /app/src/main/java/me/chunyu/spike/springrainnews/uis/adapters/MainListAdapter.java: -------------------------------------------------------------------------------- 1 | package me.chunyu.spike.springrainnews.uis.adapters; 2 | 3 | import android.content.Context; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.ImageView; 9 | import android.widget.TextView; 10 | import android.widget.Toast; 11 | 12 | import com.bumptech.glide.Glide; 13 | 14 | import java.util.ArrayList; 15 | import java.util.List; 16 | 17 | import javax.inject.Inject; 18 | 19 | import butterknife.Bind; 20 | import butterknife.ButterKnife; 21 | import me.chunyu.spike.springrainnews.NewsApplication; 22 | import me.chunyu.spike.springrainnews.R; 23 | import me.chunyu.spike.springrainnews.mvp.models.AvengersCharacter; 24 | 25 | /** 26 | * 主页列表的适配器 27 | *

28 | * Created by wangchenlong on 16/1/22. 29 | */ 30 | public class MainListAdapter extends RecyclerView.Adapter { 31 | 32 | @Inject Context mAppContext; 33 | 34 | private List mCharacters; 35 | 36 | public MainListAdapter() { 37 | mCharacters = new ArrayList<>(); 38 | NewsApplication.component().inject(this); 39 | } 40 | 41 | public void setCharacters(List characters) { 42 | mCharacters = characters; 43 | notifyDataSetChanged(); 44 | } 45 | 46 | @Override 47 | public MainListViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 48 | View view = LayoutInflater.from(parent.getContext()) 49 | .inflate(R.layout.item_main_list, parent, false); 50 | MainListClickListener listener = new MainListClickListener() { 51 | @Override public void onClick(int position) { 52 | Toast.makeText(mAppContext, "序号: " + position, Toast.LENGTH_SHORT).show(); 53 | } 54 | }; 55 | return new MainListViewHolder(view, listener); 56 | } 57 | 58 | @Override 59 | public void onBindViewHolder(MainListViewHolder holder, int position) { 60 | holder.bindTo(mCharacters.get(position)); 61 | } 62 | 63 | @Override public int getItemCount() { 64 | return mCharacters.size(); 65 | } 66 | 67 | public class MainListViewHolder extends RecyclerView.ViewHolder { 68 | @Bind(R.id.ml_item_iv_avenger_thumb) ImageView mIvAvengerThumb; 69 | @Bind(R.id.ml_item_tv_avenger_title) TextView mTvAvengerTitle; 70 | 71 | public MainListViewHolder(View itemView, MainListClickListener listener) { 72 | super(itemView); 73 | ButterKnife.bind(this, itemView); 74 | bindListener(itemView, listener); 75 | } 76 | 77 | public void bindTo(AvengersCharacter character) { 78 | Glide.with(mAppContext) 79 | .load(character.getThumbImage()) 80 | .placeholder(R.drawable.image_not_available) 81 | .crossFade() 82 | .into(mIvAvengerThumb); 83 | 84 | mTvAvengerTitle.setText(character.getName()); 85 | } 86 | 87 | private void bindListener(View itemView, final MainListClickListener listener) { 88 | itemView.setOnClickListener(v -> listener.onClick(getAdapterPosition())); 89 | } 90 | } 91 | 92 | // 点击位置监听 93 | public interface MainListClickListener { 94 | void onClick(int position); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/image_not_available.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpikeKing/SpringRainNews/b95fd627dfda15d48d3164871b81998a730e56d2/app/src/main/res/drawable-nodpi/image_not_available.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v21/ic_menu_camera.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v21/ic_menu_gallery.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v21/ic_menu_manage.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v21/ic_menu_send.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v21/ic_menu_share.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v21/ic_menu_slideshow.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/side_nav_bar.xml: -------------------------------------------------------------------------------- 1 | 3 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 16 | 17 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/layout/app_bar_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 15 | 16 | 22 | 23 | 24 | 25 | 26 | 27 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /app/src/main/res/layout/content_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_main_list.xml: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 23 | 24 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /app/src/main/res/layout/nav_header_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 20 | 21 | 27 | 28 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/menu/activity_main_drawer.xml: -------------------------------------------------------------------------------- 1 | 2 |

3 | 4 | 5 | 9 | 13 | 17 | 21 | 22 | 23 | 24 | 25 | 29 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /app/src/main/res/menu/main.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpikeKing/SpringRainNews/b95fd627dfda15d48d3164871b81998a730e56d2/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpikeKing/SpringRainNews/b95fd627dfda15d48d3164871b81998a730e56d2/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpikeKing/SpringRainNews/b95fd627dfda15d48d3164871b81998a730e56d2/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpikeKing/SpringRainNews/b95fd627dfda15d48d3164871b81998a730e56d2/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/values-v21/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | 8 | #FFFFFF 9 | #FFFFF0 10 | #FFFFE0 11 | #FFFF00 12 | #FFFAFA 13 | #FFFAF0 14 | #FFFACD 15 | #FFF8DC 16 | #FFF5EE 17 | #FFF0F5 18 | #FFEFD5 19 | #FFEBCD 20 | #FFE4E1 21 | #FFE4C4 22 | #FFE4B5 23 | #FFDEAD 24 | #FFDAB9 25 | #FFD700 26 | #FFC0CB 27 | #FFB6C1 28 | #FFA500 29 | #FFA07A 30 | #FF8C00 31 | #FF7F50 32 | #FF69B4 33 | #FF6347 34 | #FF4500 35 | #FF1493 36 | #FF00FF 37 | #FF00FF 38 | #FF0000 39 | #FDF5E6 40 | #FAFAD2 41 | #FAF0E6 42 | #FAEBD7 43 | #FA8072 44 | #F8F8FF 45 | #F5FFFA 46 | #F5F5F5 47 | #F5F5DC 48 | #F5DEB3 49 | #F4A460 50 | #F0FFFF 51 | #F0FFF0 52 | #F0F8FF 53 | #F0E68C 54 | #F08080 55 | #EEE8AA 56 | #EE82EE 57 | #E9967A 58 | #E6E6FA 59 | #E0FFFF 60 | #DEB887 61 | #DDA0DD 62 | #DCDCDC 63 | #DC143C 64 | #DB7093 65 | #DAA520 66 | #DA70D6 67 | #D8BFD8 68 | #D3D3D3 69 | #D3D3D3 70 | #D2B48C 71 | #D2691E 72 | #CD853F 73 | #CD5C5C 74 | #C71585 75 | #C0C0C0 76 | #BDB76B 77 | #BC8F8F 78 | #BA55D3 79 | #B8860B 80 | #B22222 81 | #B0E0E6 82 | #B0C4DE 83 | #AFEEEE 84 | #ADFF2F 85 | #ADD8E6 86 | #A9A9A9 87 | #A9A9A9 88 | #A52A2A 89 | #A0522D 90 | #9932CC 91 | #98FB98 92 | #9400D3 93 | #9370DB 94 | #90EE90 95 | #8FBC8F 96 | #8B4513 97 | #8B008B 98 | #8B0000 99 | #8A2BE2 100 | #87CEFA 101 | #87CEEB 102 | #808080 103 | #808080 104 | #808000 105 | #800080 106 | #800000 107 | #7FFFD4 108 | #7FFF00 109 | #7CFC00 110 | #7B68EE 111 | #778899 112 | #778899 113 | #708090 114 | #708090 115 | #6B8E23 116 | #6A5ACD 117 | #696969 118 | #696969 119 | #66CDAA 120 | #6495ED 121 | #5F9EA0 122 | #556B2F 123 | #4B0082 124 | #48D1CC 125 | #483D8B 126 | #4682B4 127 | #4169E1 128 | #40E0D0 129 | #3CB371 130 | #32CD32 131 | #2F4F4F 132 | #2F4F4F 133 | #2E8B57 134 | #228B22 135 | #20B2AA 136 | #1E90FF 137 | #191970 138 | #00FFFF 139 | #00FFFF 140 | #00FF7F 141 | #00FF00 142 | #00FA9A 143 | #00CED1 144 | #00BFFF 145 | #008B8B 146 | #008080 147 | #008000 148 | #006400 149 | #0000FF 150 | #0000CD 151 | #00008B 152 | #000080 153 | #000000 154 | 155 | 156 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 160dp 5 | 6 | 16dp 7 | 16dp 8 | 16dp 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/values/drawables.xml: -------------------------------------------------------------------------------- 1 | 2 | @android:drawable/ic_menu_camera 3 | @android:drawable/ic_menu_gallery 4 | @android:drawable/ic_menu_slideshow 5 | @android:drawable/ic_menu_manage 6 | @android:drawable/ic_menu_share 7 | @android:drawable/ic_menu_send 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | SpringRainNews 3 | 4 | Open navigation drawer 5 | Close navigation drawer 6 | 7 | Settings 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 15 | 16 |